一、方案
(原理见第二部分)
1、简单粗暴的方法,不需要知道是不是iphonex,有safe area就空出来。
padding-bottom: constant(safe-area-inset-bottom); /* 兼容 iOS < 11.2 */
padding-bottom: env(safe-area-inset-bottom); /* 兼容 iOS >= 11.2 */
2、多媒体查询
/* iPhone X 和 iPhone XS */
@media only screen and (device-width: 375px) and (device-height: 812px) and (-webkit-device-pixel-ratio: 3) {
}
/* iPhone XR */
@media only screen and (device-width: 414px) and (device-height: 896px) and (-webkit-device-pixel-ratio: 2) {
}
/* iPhone XS Max */
@media only screen and (device-width: 414px) and (device-height: 896px) and (-webkit-device-pixel-ratio: 3) {
}
3、js判断宽度逻辑与多媒体查询相似,判定长宽即可。适用与针对iphonex做功能适配的场景。
function isIPhoneX(fn){
var u = navigator.userAgent;
var isIOS = !!u.match(/\(i[^;]+;( U;)? CPU.+Mac OS X/); //ios终端
if (isIOS) {
if (screen.height == 812 && screen.width == 375){
//是iphoneX
}else{
//不是iphoneX
}
}
}
二、原理
iphonex的适配问题:因为iphonex的全名屏幕及刘海的设计,所以为了页面内容不被传感器及外壳挡住,通常来说,页面会默认留出一个safe area,页面也只在这部分显示。因此会在两边留白,通常来讲两边直接留白并不好看,最好可以用背景色进行填充。但是更好的办法就是先设置成让页面完全填充设备,然后在根据页面设计来填充danger area。让页面进行完全填充的方案就是在mate将viewport-fit设置成cover,这时候页面会进行完全填充,如下:
对需要空出danger area的部分加个padding就行了。现在问题就变成了,我怎么知道这个手机是iphonex和我到底留多少padding。为了让开发者知道这个具体的danger area,在把view-fit设置成cover后会多出safe-area-inset-的属性,来告知safe area和可视窗口viewport顶部,右边,左边,底部的间距。所以可以用support来判定手机是否支持,支持的话就说明是带小黑条需要适配的机型。而padding的高度可以用constant(safe-area-inset-)来获取小黑条的高度。然后这里有个坑:constant() 在 iOS11.2 之后就不能使用的,而在 iOS11.2用的是另一种计算方式env,也就是说为了兼容性,这两个都要写上。
关于方案怎么选择,则完全取决于业务场景。如果说只是单纯的需要把页面内容避开安全域,那就用padding的方式加safe area的距离就行。如果需要对iphonex和其他机型做不同的样式处理可以用多媒体查询判定是不是iphonex。如果是判断端则用js判断长宽,xs、xr同理。
后记:之前一般都先讲原理在说结论,但是后来我发现其实有时候大家都是业务场景去找一个方案,有空才回去看原理,因此在问题探究这个模块我会尝试采用先结论后方案的方式。