iPhoneX刘海屏适配

什么是刘海屏手机

  1. iPhoneX带来的手机新潮流,配合全面屏的概念:取消了物理按键,改成底部小黑条,顶部传感器形成一个如同刘海的区域,在其边上依然是屏幕的可视区域。
  2. 现在很多Android手机厂商也跟风,推出了很多类似设计的手机。
  3. 针对新的潮流,解决问题首先要分清问题类型:Web/Web App的适配,还是原生iOS/Android的适配。

Mobile Web的适配问题

  1. 对于网页而言,顶部的适配问题,浏览器/WebView(比如Hybird App里的)作为原生的容器等于已经帮我们做了处理,所以只要关注底部和小黑条。
  2. 具体到项目上,需要注意的点就是:吸底导航、返回顶部等相对底部fixed定位的元素。
  3. 所以只需要关注safe-area-inset-bottom

对Web App进行适配

Apple公司为Web开发的适配提供的解决方案:官方文档

meta标签

  1. 一般我们会有类似这样的设置<meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover">
  2. 其中,viewport-fit就是新增的属性,有三种值
    • contain:可视窗口完全包含网页内容,不会有内容被遮挡
    • cover: 网页内容完全覆盖可视窗口,需要自己配置,不然可能会被遮挡
    • auto:目前就和contain相当
  3. 用contain能够很好的避免遮挡问题,但是如果是全屏的Web App,这种方式带来的不受控制的边上的白色区域就很糟糕了——有时候和Web本身的背景色是格格不入的。这个时候就应该选择cover,将空间全部利用起来,并且配合接下面的设置

safe-area-inset-*

  1. 这是Apple提供的CSS解决方案,通过contant(safe-area-inset-*)这里的*就是“top、right、bottom、left”四个值。
  2. 这几个值可以自动判定装置是竖立还是横放 + 全屏幕显示还是一般显示 + iPhone的种类!然后自动计算出值
  3. 所以只要把对应的值放在容器的padding对应的地方就可以了。

    1
    2
    3
    4
    5
    6
    .container {
    padding-top: constant(safe-area-inset-top);
    padding-right: constant(safe-area-inset-right);
    padding-bottom: constant(safe-area-inset-bottom);
    padding-left: constant(safe-area-inset-left);
    }

constant()env()的问题

  1. 只有在设置了<meta name="viewport" viewport-fit=cover">的时候才会生效。
  2. 官方文档里有这么一句话:

    The env() function shipped in iOS 11 with the name constant(). Beginning with Safari Technology Preview 41 and the iOS 11.2 beta, constant() has been removed and replaced with env(). You can use the CSS fallback mechanism to support both versions, if necessary, but should prefer env() going forward.

  3. 所以应用上面的safe-area-inset-*的时候,要注意兼容不同的iOS版本,还要注意constant写在env之前这个顺序。比如:

    1
    2
    3
    4
    body {
    padding-bottom: constant(safe-area-inset-bottom); /* 兼容 iOS < 11.2 */
    padding-bottom: env(safe-area-inset-bottom); /* 兼容 iOS >= 11.2 */
    }
  4. 使用的时候还可以配合calc来做适配。比如对于吸底的元素,可以在设定高度的时候,通过height: calc(一般高度) + constant(safe-area-inset-bottom)来设置。当然,对于吸底的元素有很多处理方法,除了直接改变高度,还可以通过增加它的padding-bottom;对于非完全吸底的,比如回到顶部这种,则可以通过设置外边距margin或者calc配合bottom定位来做。

  5. 苹果官方的文档还推荐,使用minmax这两个CSS函数可以达到更好的视觉效果——单纯用一个值来判断可能会导致手机方向变化的时候,某个方向padding为0,导致页面内容紧贴手机边缘。所以有必要做改进:

    1
    2
    3
    4
    .post {
    padding-left: max(12px, env(safe-area-inset-left));
    padding-right: max(12px, env(safe-area-inset-right));
    }
  6. 但是min和max又并不能保证一定生效(浏览器未必支持),所以还需要用CSS的@supports来做兼容:

    1
    2
    3
    4
    5
    6
    @supports(padding: max(0px)) {
    .post {
    padding-left: max(12px, env(safe-area-inset-left));
    padding-right: max(12px, env(safe-area-inset-right));
    }
    }

惊悚的彩蛋

“大宝剑”可不是随便叫的,其实iPhone X带来的问题远不止刘海屏,它还带来了猎奇的屏幕比例,除了刘海和黑下巴,更多的适配还在等我们调整。