iphoneX 与之前机型对比
iphoneX 安全区域
PhoneX的适配,在iOS 11中采用了viewport-fit的meta标签作为适配方案;viewport-fit的默认值是auto
表头 | 表头 |
---|
auto | 默认:viewprot-fit:contain;页面内容显示在safe area内 | cover | viewport-fit:cover,页面内容充满屏幕 |
<meta name="viewport" content="width=device-width,initial-scale=1,viewport-fit=cover" />
在iOS 11+ 中的WebKit包含了一个新的CSS函数constant(),以及一组四个预定义的常量:safe-area-inset-left, safe-area-inset-right, safe-area-inset-top和 safe-area-inset-bottom 当合并一起使用时,允许样式引用每个方面的安全区域的大小。
padding-bottom: constant(safe-area-inset-bottom); /* 兼容 iOS < 11.2 */
padding-bottom: env(safe-area-inset-bottom); /* 兼容 iOS >= 11.2 */
之所以写了constant和env两种 是因为ios11.2版本以后constant废弃,env生效 写2种是兼容所有ios版本
<!-- 以四个不同方向上的按钮为例 -->
<div className="App">
<div className="top-area">
<div className="button-style">顶部按钮</div>
</div>
<div className="left-area">
<div className="button-style">左部按钮</div>
</div>
<div className="right-area">
<div className="button-style">右部按钮</div>
</div>
<div className="bottom-area">
<div className="button-style">底部按钮</div>
</div>
</div>
.area-style {
position: fixed;
height: 40px;
border-radius: 30px;
}
.button-style {
line-height: 40px;
font-size: 24px;
color: black;
}
.top-area {
.area-style;
top: 0;
width: 100%;
background-color: pink;
top: calc(constant(safe-area-inset-top) + 10px);
top: calc(env(safe-area-inset-top) + 10px);
}
.left-area {
.area-style;
width: 30%;
bottom: 100px;
left: 0;
background-color: grey;
left: calc(constant(safe-area-inset-left) + 0px);
left: calc(env(safe-area-inset-left) + 0px);
}
.right-area {
.area-style;
width: 30%;
bottom: 100px;
right: 0;
background-color: blue;
right: calc(constant(safe-area-inset-right) + 0px);
right: calc(env(safe-area-inset-right) + 0px);
}
.bottom-area {
.area-style;
width: 100%;
bottom: 0;
background-color: red;
bottom: calc(constant(safe-area-inset-bottom) + 10px);
bottom: calc(env(safe-area-inset-bottom) + 10px);
}
在iPhone8和iphone13效果如图所示:
竖屏:iphone13 && iphone12Pro && iphone8:
横屏:iphone13 && iphone12Pro && iphone8:
在横屏的时候安全区域的定义:
但即使能够通过constant和env函数帮助解决安全区域问题,仍有不足之处:
左右按钮的相对边框位置发生了改变
那么怎么保证竖屏和横屏时的页面布局尽可能保持一致呢?
官方在11.2版本之后 还增加了max() min() 去解决兼容横纵向切换时出现的问题 设置safe-area-inset-left左边距距离横向正常 恢复为纵向时,env(safe-area-inset-left)被解析为0px 左侧内容会紧贴屏幕所以使用如下方式做兼容
所以,我们可以对上面的左右按钮样式做出一点改造
.left-area {
position: fixed;
width: 30%;
bottom: 100px;
left: 0;
height: 40px;
border-radius: 30px;
background-color: grey;
left: max(calc(constant(safe-area-inset-left) + 0px), 6%);
left: max(calc(env(safe-area-inset-left) + 0px), 6%);
}
.right-area {
position: fixed;
width: 30%;
bottom: 100px;
right: 0;
height: 40px;
border-radius: 30px;
background-color: blue;
right: max(calc(constant(safe-area-inset-right) + 0px), 6%);
right: max(calc(env(safe-area-inset-right) + 0px), 6%);
}
这样竖屏的时候就会变成这样,风格和横屏的时候就较为一致了
软键盘差异
首先ios在点击input框的时候,为了防止页面被自动放大,我们需要增加 maximum-scale=1.0 或者 user-scalable=no属性禁止屏幕被放大
<meta name="viewport" content="width=device-width,maximum-scale=1.0,initial-scale=1,viewport-fit=cover" />
当我们统一采用fixed形式的布局后
<div className="grey-block"></div>
<div className="green-block"></div>
<input className="input-area" type="text" />
<div className="bottom-area">
<div className="button">底部按钮</div>
</div>
.input-area {
position: fixed;
width: 80%;
bottom: 200px;
left: 10%;
height: 20px;
bottom: calc(constant(safe-area-inset-bottom) + 200px);
bottom: calc(env(safe-area-inset-bottom) + 200px);
}
ios:
安卓:
当移动端软键盘被唤起后,ios的屏幕会被整个顶起,肉眼可见灰色区域和”顶部按钮“被顶到看不到的上方,但软键盘遮住的主屏幕是可以通过滑动看到灰色区域和”顶部按钮“, 也就是说ios中的任何布局,包含fixed也只是针对初始尺寸屏幕的fixed,再软键盘被唤起后,所谓的fixed变成了static的效果,页面所有元素的相对位置都被固定住
而安卓的fixed是针对可见范围内的fixed,除fixed之外的元素不会被影响布局,即页面所有元素的相对位置会发生改变,这样虽然会导致差异,但终究都是能正常显示的。
那如果我们尝试将input的position设置为static呢?
.input-area {
position: static;
width: 40%;
left: 30%;
height: 20px;
}
ios && 安卓:
在一些特殊情况下,如页面内容区域的底部存在输入框,同时页面底部有固定的按钮,在唤起软键盘后 ios还是原来的样子,static的输入框相对于fixed的按钮相对位置并没有变化,但安卓会以input框的下边界为输入框的上边界,紧贴着显示
这个时候ios采用的显示方式效果是优于安卓的,页面的布局没有发生任何变化,输入框还是清晰的展示出来, 但安卓却出现了按钮遮盖输入框的情况。真实的业务开发中其实经常会遇到底部固定按钮,搭配输入框在可视区域相对底部的情况
但解决这个问题也很容易:不要让input位于内容区域的最底部,给input下方增加一些安全距离就行
|