H5 页面适配 iPhoneX 刘海屏

# 前言

最近写个移动端的项目, 需要适配各个机型, 其中有个 iPhoneX 的刘海屏印象比较深刻,给大家分享一下, 欢迎评论留言。

# 准备工作

Safe Area

其实关于苹果手机的 Safe Area 网上的资料已经非常多了,不在多说。为了便于比较,这里我们看一张苹果官方文档中,iPhone8之前的常规屏幕和刘海屏 Safe Area 区域的对比图, 如下:
2020-07-02_092226.jpg

如上不难看出:

  1. H5 页面使用原生 App 的 Navigation Bar 导航栏,status bar 状态栏 和 导航栏 都是原生控件,只需要专注的适配底部小黑条处的高度差异即可。
  2. H5 页面在 iOS 中占据全屏页面,在这种情况下,除了要兼顾底部小黑条,还要处理页面上部 跟 状态栏 接触的部分,避免内容出现在状态栏上。

env 函数

env() 函数以类似于 var 函数 的方式将用户代理定义的环境变量值插入到你的 CSS 中去。这个函数最初由 iOS 浏览器提供,用于允许开发人员将其内容放置在视口的安全区域中,该规范中定义的 safe-area-inset-* 值用于确保内容即使在非矩形的视区中也可以完全显示。

# 开始适配

我们首先得在页面的 meta 中添加一个新的值:viewport-fit=cover, 设置之后,视图端口被缩放以填充设备显示 ( 即网页会扩展到整个屏幕 )。


如何适配刘海屏呢, 如下代码:

body {
  padding:
    constant(safe-area-inset-top)
    constant(safe-area-inset-right)
    constant(safe-area-inset-bottom)
    constant(safe-area-inset-left); /* 兼容 iOS < 11.2 */
  padding:
    env(safe-area-inset-top)
    env(safe-area-inset-right)
    env(safe-area-inset-bottom)
    env(safe-area-inset-left); /* 兼容 iOS >= 11.2 */
}

这里有个 constant , 官方文档这么解释

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.

如上设置后, 可以看到页面的顶部,因为 safe-area-inset-top 避开了状态栏,
而底部因为 safe-area-inset-bottom 避开了小黑条,完美的显示在了 Safe Area 的区域中。

如果使用了原生导航栏,仅仅需要适配底部小黑条时,解决方案就更简单了,简单设置 safe-area-inset-bottom就可以:

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

# 特殊情况处理 - Fixed 和 绝对定位的情况

有时底部元素是通过 fixed 或者 absolute 定位放置的,对于这些元素,简单的使用 safe-area-inset-bottom 是无效的,但是我们可以对该元素单独增加内边距的 padding 来解决, 如下:

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

通过增加该元素的高度来解决

@element-height: 60px; /* 元素原始高度 */
.element {
  height: calc(@element-height + constant(safe-area-inset-bottom));
  height: calc(@element-height + env(safe-area-inset-bottom));
}

也可以通过 less、sass 的函数,通过媒体查询来准确的定位到刘海屏的手机,然后写入你希望刘海屏手机展示的任何样式, 栗子如下:

/**
 *  适配 iPhoneX 及以后的刘海屏手机,可以自行编写 rules 规则
 */
.safe-area(@rules) {
  /* iphone x / xs / 11 pro*/
  @media only screen and (device-width: 375px) and (device-height: 812px) and (-webkit-device-pixel-ratio: 3) { @rules(); }
  /* iphone xr / 11  stackoverflow 提供判断 */
  @media only screen and (device-width: 414px) and (device-height: 896px) and (-webkit-device-pixel-ratio: 2) { @rules(); }
  // 实际可用的 xr 判断
  @media only screen and (device-width: 375px) and (device-height: 812px) and (-webkit-device-pixel-ratio: 2) { @rules(); }
  /* iphone xs max / 11 pro max */
  @media only screen and (device-width: 414px) and (device-height: 896px) and (-webkit-device-pixel-ratio: 3) { @rules(); }
}

// 具体使用
.safe-area({
  height: 100px;
  padding-bottom: env(safe-area-bottom-height);
});

特此感谢 Originalee , 抱拳了

你可能感兴趣的:(H5 页面适配 iPhoneX 刘海屏)