(这是一个包含多个部分的问题,我将尽力总结一下这个场景。)
我们目前正在构建一个响应式web应用程序(新闻阅读器),它允许用户在选项卡内容之间滑动,以及在每个选项卡内容内垂直滚动。
解决此问题的常用方法是使用包装器div
填充浏览器视口,将overflow
设置为hidded
或auto
,然后在其中水平和/或垂直滚动。
这种方法很棒,但有一个主要缺点:由于文档的高度与浏览器视口完全相同,移动浏览器不会隐藏地址栏/导航菜单。
有许多hacks和viewport属性使我们能够获得更多的屏幕空间,但没有一个像minimal-ui
(在iOS 7.1中引入)那样有效。
昨天传来消息,iOS 8 beta4已经从Mobile Safari中删除了minimal-UI
(参见iOS 8发行说明中的Webkit部分),这让我们很疑惑:
Q1.移动Safari上还有可能隐藏地址栏吗?
据我们所知,iOS7不再响应window.scrollto
黑客攻击,这意味着我们必须与更小的屏幕空间一起生活,除非我们采用垂直布局或使用mobile-web-app-cable
。
Q2.还能有类似的软全屏体验吗?
所谓软全屏,我真正的意思是不使用mobile-web-app-cable
元标记。
我们的web应用程序是建立为可访问的,任何页面都可以被书签或共享使用本机浏览器菜单。通过添加mobile-web-app-cable
,我们可以防止用户调用这样的菜单(当它保存到主页时),这会使用户感到困惑和反感。
minimal-ui
曾经是一种折衷的方法,默认情况下隐藏菜单,但通过轻击保持它的可访问性--尽管苹果可能会出于其他可访问性考虑(比如用户不知道在哪里点击才能激活菜单)而将其删除。
Q3.全屏体验值得这么麻烦吗?
似乎全屏API不会很快出现在iOS上,但即使真的出现了,我也不知道该如何保持菜单的可访问性(Android上的Chrome也是如此)。
在这种情况下,也许我们应该让mobile safari保持原样,并考虑视口高度(对于iPhone5+,视口高度为460=568-108,其中108包括操作系统栏、地址栏和导航菜单;对于iPhone4或更高版本,视口高度为372)。
希望听到一些替代方案(除了构建一个原生应用程序)。
iOS 8不再支持minimal-ui视口属性。然而,最小UI本身并没有消失。用户可以通过“触摸-拖动”手势进入最小界面。
管理视图状态有几个前提条件和障碍,例如,要使最小UI工作,必须有足够的内容使用户能够滚动;要使minimal-ui持久存在,必须在页面加载时和方向更改后偏移窗口滚动。但是,无法使用screen
变量计算最小UI的尺寸,因此无法预先告知用户何时在最小UI中。
这些观察结果是作为为iOS 8开发Brim- 视图管理器的一部分进行研究的结果。最终实现的工作方式如下:
加载page时,Brim将创建一个treadmill元素。Treadmill元素用于为用户提供滚动的空间。treadmill元素的存在确保用户可以进入最小UI视图,并且如果用户重新加载页面或更改设备方向,它将继续保持。它对用户来说是不可见的。此元素的ID为brim-treadmill
。
加载页面或改变方向后,Brim使用尖叫来检测页面是否在最小UI视图中(如果内容高度大于视口高度,则先前在最小UI中并重新加载的页面将保留在最小UI中)。
当page在minimal-ui中时,Brim将禁用文档的滚动(它以一种不影响主元素内容的安全方式执行此操作)。禁用文档滚动可防止向上滚动时意外离开最小UI。按照最初的iOS7.1规范,点击顶部条将恢复Chrome的其余部分。
最终结果看起来是这样的:
出于文档的考虑,并且如果您更愿意编写自己的实现,值得注意的是,您不能在orientationchange事件之后直接使用尖叫来检测设备是否处于最小UI中,因为window
维度在旋转动画结束之前不会反映新的方向。必须将侦听器附加到orientationchangeend事件。
Scream和orientationchangeend已作为该项目的一部分开发。
由于没有编程方法来模拟minimal-UI
,我们提出了一个不同的解决方案,使用calc()
和已知的iOS地址栏高度,这对我们有利:
下面的演示页面(也可以在gist上获得,更多的技术细节在那里)将提示用户滚动,然后触发软全屏(隐藏地址栏/菜单),其中标题和内容填充新的视口。
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Scroll Test</title>
<style>
html, body {
height: 100%;
}
html {
background-color: red;
}
body {
background-color: blue;
margin: 0;
}
div.header {
width: 100%;
height: 40px;
background-color: green;
overflow: hidden;
}
div.content {
height: 100%;
height: calc(100% - 40px);
width: 100%;
background-color: purple;
overflow: hidden;
}
div.cover {
position: absolute;
top: 0;
left: 0;
z-index: 100;
width: 100%;
height: 100%;
overflow: hidden;
background-color: rgba(0, 0, 0, 0.5);
color: #fff;
display: none;
}
@media screen and (width: 320px) {
html {
height: calc(100% + 72px);
}
div.cover {
display: block;
}
}
</style>
<script>
var timeout;
window.addEventListener('scroll', function(ev) {
if (timeout) {
clearTimeout(timeout);
}
timeout = setTimeout(function() {
if (window.scrollY > 0) {
var cover = document.querySelector('div.cover');
cover.style.display = 'none';
}
}, 200);
});
</script>
</head>
<body>
<div class="header">
<p>header</p>
</div>
<div class="content">
<p>content</p>
</div>
<div class="cover">
<p>scroll to soft fullscreen</p>
</div>
</body>
</html>