前言

前些年的iphone X一出现 手机厂商纷纷取消了实体的物理按键,ios取而代之的是底部的一个大横条 安卓这边基本上也有不少虚拟按键的厂商 就会导致一些比较奇葩的问题出现 比如

Android 全面屏底部安全区颜色 屏幕安全区域_Android 全面屏底部安全区颜色


这种的情况的发生,或者说刘海屏,挖孔屏

一般来说这种时候,都需要我们前端去进行设备适配。

适配之前需要了解的几个新知识

安全区域
安全区域指的是一个可视窗口范围,处于安全区域的内容不受圆角(corners)、齐刘海(sensor housing)、小黑条(Home Indicator)的影响,以及横屏状态下他们的影响。
更详细说明介绍,参考官方文档:Human Interface Guidelines -iphone - X

viewport-fit

iOS11 新增特性,苹果公司为了适配 iPhoneX 对现有 viewport meta 标签的一个扩展,用于设置网页在可视窗口的布局方式,可设置三个值:

  • contain: 可视窗口完全包含网页内容(下图)
  • cover:网页内容完全覆盖可视窗口(下图)
  • auto:默认值,跟 contain 表现一致

Android 全面屏底部安全区颜色 屏幕安全区域_Android 全面屏底部安全区颜色_02

注意:网页默认不添加扩展的表现是 viewport-fit=contain,
需要适配 iPhoneX 必须设置 viewport-fit=cover,这是适配的关键步骤。

env() 和 constant()

iOS11 新增特性,Webkit 的一个 CSS 函数,用于设定安全区域与边界的距离,有四个预定义的变量:

  • safe-area-inset-left:安全区域距离左边边界距离
  • safe-area-inset-right:安全区域距离右边边界距离
  • safe-area-inset-top:安全区域距离顶部边界距离
  • safe-area-inset-bottom:安全区域距离底部边界距离

一般来说的话,只需要关注 safe-area-inset-bottom以及safe-area-inset-top即可,他俩的值代表的是顶部的刘海以及底部的黑条距离安全区的距离。

后来官方给其加了一段说明:
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. 这就意味着,之前使用的 constant() 在 iOS11.2 之后就不能使用的,但我们还是需要做向后兼容,像这样:

padding-bottom: constant(safe-area-inset-bottom); /* 兼容 iOS < 11.2 */
padding-bottom: env(safe-area-inset-bottom); /* 兼容 iOS >= 11.2 */

注意:env() 跟 constant() 需要同时存在,而且顺序不能换。

如何更加具体适配

第一步:设置网页在可视窗口的布局方式

新增 viweport-fit 属性,使得页面内容完全覆盖整个窗口:

<meta name="viewport" content="width=device-width, viewport-fit=cover">

第二步:页面主体内容限定在安全区域内

这一步根据实际页面场景选择,如果不设置这个值,可能存在小黑条遮挡页面最底部内容的情况。

body {
  padding-bottom: constant(safe-area-inset-bottom);
  padding-bottom: env(safe-area-inset-bottom);
}

第三步:fixed 元素的适配

如果说直接设置bottom = 0;

那么会出现底部固定定位和小黑条重叠的样式就和图示一样。

Android 全面屏底部安全区颜色 屏幕安全区域_css3_03


这种情况的话可以通过增加外部盒子的padding-bottom来解决这个问题

{
  padding-bottom: constant(safe-area-inset-bottom);
  padding-bottom: env(safe-area-inset-bottom);
}

还有一种方法就是通过增加一个空的底部固定定位占位元素,来实现小横条不重叠

/* 空元素css样式 */
{
  position: fixed;
  bottom: 0;
  width: 100%;
  height: constant(safe-area-inset-bottom);
  height: env(safe-area-inset-bottom);
  background-color: #fff;
}

类型二:fixed 非完全吸底元素(bottom ≠ 0),比如 “返回顶部”、“侧边广告” 等
像这种只是位置需要对应向上调整,可以仅通过外边距 margin 来处理:

{
  margin-bottom: constant(safe-area-inset-bottom);
  margin-bottom: env(safe-area-inset-bottom);
}