如何针对 iPhone X 设计网站?

如何针对 iPhone X 设计网站?

本文译自 webkit.org Designing Websites for iPhone X,首发

这是一篇来自苹果关于 iPhone X 适配的官方指南,希望可以帮助各位前端开发者做好 iPhone X 的适配。


广告

下面关于安全边距的内容于2017年10月20日有更新,跟进 iOS 11.2 beta 的一些变化。

在全面屏的 iPhone X 上,不需要而外的代码,Safari 可以非常完美的展示现有的网站。整个网站的内容都会自动地展示在一个“安全区域”内,并不会被四周的圆角或者“小刘海”遮挡住。

Safari 使用页面的背景色(一般就是 <body> 或者 <html> 元素的 background-color)来填充周围空出的区域,与页面的其他部分保持协调。这种方式可以解决网站大部分的问题。如果本身就是一个固定背景色上堆叠一些文字或者图片的网站,默认的填充区域看起来会很协调。

不过还有一些网站——尤其是那些有横向贯穿的导航条的网站,像下面这样的就需要做一点额外的工作,使得在这种新的显示下继续利用全面屏的优势,且不显得突兀。iPhone X Human Interface Guidelines 详细解释了一些需要注意的设计准则,UIKit documentation 也给出了一些 Native App 可以采用的机制来保证视觉效果。同样,在网站这边,也可以利用 iOS 11 里 Safari 引入的特定 API 来使用好全面屏显示的优点。

下面的每个图都可以点击打开可对应的demo,方便大家查看效果和源码。

Safari 带默认安全边距的样子

全屏显示

第一个新特性扩展了现有 viewport 这个 meta 标记,添加了名字为 viewport-fit 的属性,用来控制网页的安全边距。viewport-fit 在 iOS 11 上才有效。

viewport-fit 的默认值是 auto,效果如上图,默认留出安全边距。如果想要全屏显示,需要将 viewport-fit 设置为 cover。meta 标记看上去像下面这样:

<metaname='viewport'content='initial-scale=1, viewport-fit=cover’> 

刷新页面,导航栏扩展到了屏两端,看起来舒服多了。但是,马上我们就会发现系统默认让出安全边距是很有必要的:网页内容被 iPhone 的小刘海覆盖了,底部的导航也好难使用。


使用 viewport-fit 开启全屏。

安全边距

接下来需要让使用了 viewport-fit=cover 之后界面还是可用的。我们需要有选择地给那些包含重要信息的元素加上内边距,避免它们受到屏幕形状的影响。这样不但可以充分利用 iPhone X 扩大的屏幕,也可以避免手机四个角、小刘海和退到主屏标志的影响。


横向 iPhone X 上的安全和非安全区域,包括安全边距示意图。

如何达到这个目标?iOS 11 的 WebKit 引入了一个新的 CSS 函数——env(),还有四个预定义的环境变量。—— safe-area-inset-left, safe-area-inset-right, safe-area-inset-top, 和 safe-area-inset-bottom。结合这两个新东西,就可以在样式中使用安全边距。

env() 函数在 iOS 11 发布的时候用的名字是 constant()。Safari Technology Preview 41 和 iOS 11.2 beta 发布的时候,constant() 被替换成了 env()。可以利用 CSS 的降级机制同时支持这两个版本的不同函数。但如果不考虑兼容性,往后就使用 env()

env() 可以用在任何支持 var() 的地方——举个例子,padding 属性中使用:

.post {
    padding: 12px;
    padding-left: env(safe-area-inset-left);
    padding-right: env(safe-area-inset-right);
} 

在不支持 env() 函数的浏览器中,这条 CSS 规则会被忽略。因此,针对每个使用 env() 的地方,加一条 CSS 备用规则尤其重要。

设置安全边距后,重要内容完全可见了。

借力 min() 或者 max() 横竖屏兼容

本节说的特性都是 Safari Technology Preview 41 和 iOS 11.2 beta 上引入的新特性。

如果你已经给自己的站点添加了安全边距,可能就会发现,指定了安全边距后,无法再给元素指定一个最小边距。如上面到例子,把 12px 的左边距换成 env(safe-area-inset-left) ,当把手机竖起来,安全边距变成了 0px,文字内容立马就和手机边缘粘在一起了。

安全边距无法完全替代外边距。

为了解决这个问题,就需要在默认边距和安全边距中选择较大值。我们可以使用 Safari Technology Preview 新增的 CSS 函数 min() 或 max() 来实现。这两个函数都接受任意个数字,返回其中最小或者最大值。两个函数都可以使用在 calc() 中,也可以互相嵌套,也允许在函数内使用计算(就如 calc() 的那样)。

使用 max() 解决战斗:

@supports(padding: max(0px)) {
    .post {
        padding-left: max(12px, env(safe-area-inset-left));
        padding-right: max(12px, env(safe-area-inset-right));
    }
} 

别忘了使用 @supports 来对 min 和 max 函数特性进行兼容性检查,因为不是所有浏览器都支持这个特性。由于 CSS 对 无效 variable 的处理,不要在 @supports 查询中使用 variable。

手机处于竖屏状态时,env(safe-area-inset-left) 取值为 0px,因此 max() 函数的取值为 12px。横屏时,env(safe-area-inset-left) 因为小刘海的存在,会比较大,max() 就会返回安全边距,这样就可以保证重要的内容总是可见。

使用 max() 结合使用安全边距和默认边距。

经验老到的 Web 开发者可能碰到过像上看这样的“CSS locks”原理,用来将 CSS 属性值限制在一个特定范围内。min()max() 可以让这件事变得更简单,对以后快速实现响应式设计将会非常有用。

译注:CSS locks 具体是什么,不太理解,哪位大大给分享一下?

问题反馈

大家现在就可以开始适配 viewport-fit 和安全边距了,可以使用 iPhone X 模拟器上的 Safari 来测试,这需要安装 Xcode 9。欢迎你把利用上面特性来做兼容的方案分享给我们,也可以给我们提交问题和反馈,发邮件到 web-evangelist@apple.com ,或者在 Twitter 上直接 @webkit 留言。碰到任何 bug 可以提到 WebKit’s bug tracker

编辑于 2018-01-01 21:32