IphoneX适配正确姿势
IphoneX适配正确姿势
写在前面
距离18年9月iphonex发布以来已经快两年了(所以对于iphonex机型的头部刘海(sensor housing)和底部小黑条(Home Indicator)的内容本文不在做过多赘述了),相信还有一些同学为iphonex系列机型如何完美适配在发愁,笔者结合公司移动端h5项目和一些官方文档做了一个总结,希望可以帮到大家。
预备知识
在开撸之前,我们需要了解一下安全区域、viewport-fit、env() 和 constant()三个必备的知识点
安全区域
大家应该能看懂safe area是安全区域的意思吧?那顾名思义,如下图所示,安全区域就是指的不受头部刘海以及底部小黑条影响的那一部分区域。

苹果官网人机交互指南
viewport-fit
viewport-fit是 IOS 11 新增的特性,关于viewport-fit的枚举值介绍如下:
- contain: 可视窗口完全包含网页内容(左图)
- cover:网页内容完全覆盖可视窗口(右图)
- auto:默认值,跟 contain 表现一致


env() 和 constant()
各种 iphone x 都是不规则形状,我们需要把我们的页面内容控制在之前说的安全区域之内,那怎么把页面的顶部和底部空出来呢?不得不说apple挺贴心的,他们已经把安全区域的位置信息通过css常量的方式暴露给了开发者,这些css常量需要用env() 和 constant()这两个函数来包裹就可以拿到了。具体可以看这个issue
安全区域位置信息常量值
- safe-area-inset-top:从视口顶部开始的安全区域插入量(以CSS像素为单位)。
- safe-area-inset-bottom:从视口底部开始的安全区域插入量(以CSS像素为单位)。
- safe-area-inset-left:从视口左侧开始的安全区域插入量(以CSS像素为单位)。
- safe-area-inset-right:从视口右侧开始的安全区域插入量(以CSS像素为单位)。
env() 和 constant()介绍
env() 和 constant()是IOS 11的新增特性,是两个css函数,先来看看这两个函数的兼容性:

我们可以看到在IOS 11.0-11.2是支持constant函数的,在11.3往后是废弃了constant函数,取而代之的是env函数。
简单示例
空出底部安全距离
padding-bottom: constant(safe-area-inset-bottom); // 兼容 11.0 < iOS < 11.2
padding-bottom: env(safe-area-inset-bottom); // 兼容 iOS >= 11.2
注意点
- 需要设置viewport-fit=cover,安全区域位置信息才有;
- 写的时候需要constant和env函数都写上,以达到可以兼容所有IOS 11系统;
小结
需要注意使用安全区域位置信息的前置条件是设置viewport-fit=cover,然后上述所说的信息属于IOS 11新增内容,iphonex出厂系统是大于等于11.0的,所以可以放心大胆的去用来做iphonex的兼容。
正确姿势
看完前面以后,大家的一些奇怪的知识已经具备了,接下来就开始正式进入适配iphonex系列机型环节。当然,看完下面以后我们就会用最完美最简洁的姿势去进行适配了,不要眨眼,go~
前置条件
设置viewport-fit=cover
<meta name="viewport" content="width=device-width,viewport-fit=cover">
需要适配的iphonex系列机型“容器”
我们的移动端h5页面一般无非在四个“容器”中打开:微信、网页、App、小程序。所以我们需要针对这四个“容器”对我们的页面做一些适配以便在iphonex系列机型中完美展现妾身的舞姿。
在微信、小程序、网页中的适配
头部
因为在这些“容器中”,头部都已经由“容器”给我们适配好了(懂王自然懂),所以我们只需要关注底部即可。
底部
姿势:页面整体底部空出安全距离(不同的项目布局方式不同,视情况决定加在哪个地方更加合理(page,basicPage)):
body {
box-sizing: border-box;
padding-bottom: constant(safe-area-inset-bottom);
padding-bottom: env(safe-area-inset-bottom);
}
在App中的适配
头部
头部兼容我们需要在自己项目的导航头组件下手,思路就是给导航头加上顶部安全距离,避免导航头顶到刘海里面。
- 判断在ios并且处在app环境中的时候加一个特定的类名,比如:ipx-head-nav
- 给ipx-head-nav加一个padding-top值空出来顶部安全距离
.ipx-head-nav {
padding-top: 20px; // iphonex系列机型之前顶部安全距离均为20px
padding-top: constant(safe-area-inset-top);
padding-top: env(safe-area-inset-top);
}
padding-top为20px去兼容iphonex以及IOS 11系统之前的机型,constant和env函数去适配iphonex以及IOS 11系统之后的机型。
底部
和在微信、小程序、网页中的底部适配姿势一致,统一姿势。
一些特殊场景的处理
吸底(bottom === 0)的按钮
建议吸底按钮都改为fixed定位,然后我们用这个姿势去适配:
.btn {
position: fixed;
bottom: 0; // 当constant和env函数都不支持的时候,这个会生效
bottom: constant(safe-area-inset-bottom);
bottom: env(safe-area-inset-bottom);
&:after {
content: ' ';
position: fixed;
left: 0;
right: 0;
bottom: 0;
background-color: #ffffff;
height: constant(safe-area-inset-bottom);
height: env(safe-area-inset-bottom);
}
}
因为在iphonex上,按钮bottom为底部安全距离,那和最下面就会有一段镂空的空档,所以还需要把这个空档给补上。
思路:
- 按钮bottom值先适配iphonex;
- 添加一个新的元素补到空档的位置,高度就是安全距离的高度。
fixed定位的非完全吸底(bottom !== 0)元素,比如“返回顶部”按钮
在这里我们假设有一个需求,一个“返回顶部”的按钮,需要距离底部30px,还需要适配iphonex,那么我们就可以使用下面的姿势:
.back-top-btn {
bottom: 30px;
bottom: calc(30px + constant(safe-area-inset-bottom));
bottom: calc(30px + env(safe-area-inset-bottom));
}
在不支持constant和env函数的系统中,bottom计算出来的值是无效的,bottom: 30px会生效。
小福利
相信大家现在已经掌握了适配iphonex系列机型的正确姿势了,如果你的项目里是使用scss去编写样式的,在这里送大家3个牛逼的姿势秘籍,这么简单的姿势应该一看就能懂是怎么用的,不懂的话可以在评论区留言提问:
// ipx系列底部padding值
@mixin iphonex-padding-bottom($paddingBottom: 0px) {
padding-bottom: $paddingBottom;
padding-bottom: calc(#{$paddingBottom} + constant(safe-area-inset-bottom));
padding-bottom: calc(#{$paddingBottom} + env(safe-area-inset-bottom));
}
// ipx系列fixed定位底部bottom值
@mixin iphonex-fixed-bottom($bottom:0px) {
bottom: $bottom;
bottom: calc(#{$bottom} + constant(safe-area-inset-bottom));
bottom: calc(#{$bottom} + env(safe-area-inset-bottom));
}
// ipx系列fixed定位bottom为0的处理函数
@mixin iphonex-fixed-bottom-zero($backgroundColor: #ffffff) {
@include iphonex-fixed-bottom();
&:after {
content: ' ';
position: fixed;
left: 0;
right: 0;
bottom: 0;
background-color: $backgroundColor;
height: constant(safe-area-inset-bottom);
height: env(safe-area-inset-bottom);
}
}
写在最后
以上分享的姿势是笔者总结出来的比较通用的解决方案,但方案并不是唯一的,只是希望能给大家提供一种解决思路,让自己的应用更加完美。最后当然是要感谢大家的阅读啦,thank you~
作者:渴望成为大牛的男人。本文首发地址:https://juejin.cn/post/6865873665104773128
IphoneX适配正确姿势的更多相关文章
- Taro 多端开发的正确姿势:打造三端统一的网易严选(小程序、H5、React Native)
笔者所在的趣店 FED 早在去年 10 月份就已全面使用 Taro 框架开发小程序(当时版本为 1.1.0-beta.4),至今也上线了 2 个微信小程序.2 个支付宝小程序. 之所以选用 Taro, ...
- 判断是否为gif/png图片的正确姿势
判断是否为gif/png图片的正确姿势 1.在能取到图片后缀的前提下 1 2 3 4 5 6 7 8 9 //假设这是一个网络获取的URL NSString *path = @"http:/ ...
- 在Linux(ubuntu server)上面安装NodeJS的正确姿势
上一篇文章,我介绍了 在Windows中安装NodeJS的正确姿势,这一篇,我们继续来看一下在Linux上面安装和配置NodeJS. 为了保持一致,这里也列举三个方法 第一个方法:通过官网下载安装 h ...
- 程序员取悦女朋友的正确姿势---Tips(iOS美容篇)
前言 女孩子都喜欢用美图工具进行图片美容,近来无事时,特意为某人写了个自定义图片滤镜生成器,安装到手机即可完成自定义滤镜渲染照片.app独一无二,虽简亦繁. JH定律:魔镜:最漂亮的女人是你老婆魔镜: ...
- ios监听ScrollView/TableView滚动的正确姿势
主要介绍 监测tableView垂直滚动的舒畅姿势 监测scrollView/collectionView横向滚动的正确姿势 1.监测tableView垂直滚动的舒畅姿势 通常我们用KVO或者在scr ...
- 玩转 Ceph 的正确姿势
玩转 Ceph 的正确姿势 本文先介绍 Ceph, 然后会聊到一些正确使用 Ceph 的姿势:在集群规模小的时候,Ceph 怎么玩都没问题:但集群大了(到PB级别),这些准则可是保证集群健康运行的不二 ...
- 解锁redis锁的正确姿势
解锁redis锁的正确姿势 redis是php的好朋友,在php写业务过程中,有时候会使用到锁的概念,同时只能有一个人可以操作某个行为.这个时候我们就要用到锁.锁的方式有好几种,php不能在内存中用锁 ...
- jquery选中radio或checkbox的正确姿势
jquery选中radio或checkbox的正确姿势 Intro 前几天突然遇到一个问题,没有任何征兆的..,jquery 选中radio button单选框时,一直没有办法选中,后来查了许多资料, ...
- 程序员节应该写博客之.NET下使用HTTP请求的正确姿势
程序员节应该写博客之.NET下使用HTTP请求的正确姿势 一.前言 去年9月份的时候我看到过外国朋友关于.NET Framework下HttpClient缺陷的分析后对HttpClient有了一定的了 ...
随机推荐
- leetcode116. 填充每个节点的下一个右侧指针
给定一个完美二叉树,其所有叶子节点都在同一层,每个父节点都有两个子节点.二叉树定义如下:struct Node { int val; Node *left; Node *right; Node ...
- redlock分布式锁真的安全吗
此文是对http://zhangtielei.com/posts/blog-redlock-reasoning-part2.html文章的个人归纳,如有问题请联系删除 什么是redlock redlo ...
- centos7 ping: baidu.com: Name or service not known
虚拟机 centos7配置ip后 ping 网关可以ping 通,但是ping不通外网 baidu.com 报错为: ping: baidu.com: Name or service not know ...
- TCP接收窗口为什么变大了?
今天用wireshark抓取TCP连接时的报文发现客户端的Win变大了,这里是使用了Window Scale来扩张TCP接收窗口,使得接收窗口可以大于65535字节. 首先1号包是TCP第一次握手连接 ...
- 关于Jersey框架下的Aop日志 和Spring 框架下的Aop日志
摘要 最近新接手的项目经常要查问题,但是,前面一拨人,日志打的非常乱,好多就根本没有打日志,所以弄一个AOP统一打印一下 请求数据和响应数据 框架 spring+springmvc+jersey 正文 ...
- Contest 1428
A 移动次数是 \(\left|x_1-x_2\right|+\left|y_1-y_2\right|\). 如果 \(x_1\not=x_2\) 且 \(y_1\not=y_2\) 说明要换方向,两 ...
- C++基础知识篇:C++ 常量
常量是固定值,在程序执行期间不会改变.这些固定的值,又叫做字面量. 常量可以是任何的基本数据类型,可分为整型数字.浮点数字.字符.字符串和布尔值. 常量就像是常规的变量,只不过常量的值在定义后不能进行 ...
- ZAB
ZAB=ZooKeeper Atomic Broadcast ZooKeeper原子消息广播协议,支持崩溃回复的原子广播协议. zk使用一个单一的主进程来接受并处理客户端的所有事务请求,并采用ZAB的 ...
- 区块链V1版本实现之四
部分程序代码(添加区块): //添加区块 func (bc *BlockChain) AddBlock(data string) { //创建一个区块 //bc.Block的最后一个区块的Hash值就 ...
- 【2020.12.01提高组模拟】卡特兰数(catalan)
题目 题目描述 今天,接触信息学不久的小\(A\)刚刚学习了卡特兰数. 卡特兰数的一个经典定义是,将\(n\)个数依次入栈,合法的出栈序列个数. 小\(A\)觉得这样的情况太平凡了.于是,他给出了\( ...