转自IMWeb社区,做者:zzbozheng,原文连接css
9月13日凌晨终于等来了万众瞩目的苹果新品发布会,相信不少小伙伴们都期待新 iphone 能够剪掉刘海胡子,但万万没想到的是等来了三款不一样的尺寸的 iphone x ,个人天,等了这么久你给我看这个?码农慌得一批满地找新 iphone 的逻辑像素,而后想着怎么兼容这刘海和胡子。html
其实对于 web 前端来讲,刘海在绝大多数的场景下是能够不用处理的,由于 safari 或客户端(微信,手Q等)的 statusBar 已经替咱们抹平了顶部刘海,咱们只须要关心底部的那条黑色的胡子,由于若是页面底部有按钮的话,就会被胡子给挡住,以往咱们兼容过 iphone x 的下巴,但如今回想起来不是正确的作法。咱们以前是这么处理的:
首先在 <html>
中加入对应的 className:has-bottombar
前端
<html class="has-bottombar">
<head></head>
<body></body>
</html>
复制代码
再配上对应的 css:ios
@media only screen and (-webkit-device-pixel-ratio: 3) and (device-height: 812px) and (device-width: 375px) {
.has-bottombar {
height: 100%;
-moz-box-sizing: border-box;
box-sizing: border-box;
padding-bottom: 34px;
}
.has-bottombar:after {
content: '';
z-index: 9999;
position: fixed;
left: 0;
bottom: 0;
width: 100%;
height: 34px;
background: #fff;
}
}
复制代码
这里的处理方法是使用了媒体查询 media query 按照 iphone x 的尺寸(375px * 812px)作特殊处理,主要作两件事情:
一、给 html 底部预留 34px 的间距,让页面里面的内容距底部保持 34px 的间距,从而避开了胡子的遮挡。
二、建立一个 after
伪类经过设置 position: fixed
定位到页面底部,并设置成白色,这一处理主要是遮挡住页面背景色。
效果以下图:
web
这些处理若是在9月13日以前是问题不大的,但在 9月13日 以后前端开发的同窗头就大了,由于新的三款 iphone 尺寸都不同(逻辑像素 xr: 375 * 812; xs: 414 * 896; xs max: 414 * 896;)因而,开始奔命于修改 media query。。。若是明年又多几个尺寸那就会是没完没了的改改改。浏览器
在 ios 11 中咱们可使用 viewport-fit=cover
+ safe-area-inset-*
。
那么是否是 ios11 如下就用不了这些了呢?是的,但你见过 iphone x+ 有 ios 11如下的吗? 因此咱们能够愉快的搞下去。安全
开始以前咱们先了解什么是 safe area,简单的来讲就是除了刘海和胡子之外的区域为安全区域:
bash
viewport-fit 有3个值:
contain: 可视窗口彻底包含网页内容(左图)
cover:网页内容彻底覆盖可视窗口(右图)
auto:默认值,跟 contain 表现一致
微信
如何决定 viewport-fit 值?咱们要考虑一些问题:
一、在非矩形显示器上设置 viewport 边界时,Viewport边界框(Viewport Bounding Box)的面积大于显示区域,致使了剪切区域
二、若是要保证Web页面的任何部分都没有隐藏,不想让Web页面在可读性上变得很小,那么最好将viewport-fit设置为cover,并在考虑剪切部分时实显示页面。
三、还有另外一个考虑是,当咱们设置 viewport-fit:contain,也就是默认的时候时,设置 safe-area-inset-* 等 css 属性时不起做用的。 点击这里了解更多关于 viewport-fitapp
各类 iphone x 都是不规则形状,咱们如何控制页面元素到安全区域呢?apple 把安全区域的位置经过 css 属性提供给了开发者,它们能够经过CSS的constant( )函数来完成:
constant(safe-area-inset-top)
:在Viewport顶部的安全区域内设置量(CSS像素)
constant(safe-area-inset-bottom)
:在Viewport底部的安全区域内设置量(CSS像素)
constant(safe-area-inset-left)
:在Viewport左边的安全区域内设置量(CSS像素)
constant(safe-area-inset-right)
:在Viewport右边的安全区域内设置量(CSS像素)
简单来讲咱们能够经过 constant( )
能够获取到非安全边距,再结合 padding
或 margin
来控制页面元素避开非安全区域。 Webkit在iOS11中新增CSS Functions: env( )替代constant( ),文档中推荐使用env( ),而 constant( ) 从Safari Techology Preview 41 和iOS11.2 Beta开始会被弃用。在不支持env( )的浏览器中,会自动忽略这同样式规则,不影响网页正常的渲染。为了达到最大兼容目的,咱们能够 constant( ) 和 env( ) 同时使用。
.yourFooterClass {
padding-bottom: constant(safe-area-inset-bottom); /* iOS 11.0 */
padding-bottom: env(safe-area-inset-bottom); /* iOS 11.2 */
}
复制代码
本文为了简洁只写 env( )。
新增 viweport-fit 属性,使得页面内容彻底覆盖整个窗口:
<meta name="viewport" content="width=device-width,initial-scale=1.0,viewport-fit=cover">
复制代码
假设咱们的底部按钮高度是50px:
body {
padding-top: env(safe-area-inset-top);
padding-right: env(safe-area-inset-right);
padding-bottom: 50px; /* 兼容不支持 env( ) 的设备 */
padding-bottom: calc(env(safe-area-inset-bottom) + 50px); /* 在 iphone x + 中本句才会生效 */
padding-left: env(safe-area-inset-left);
}
复制代码
有两个关键点:
一、写在前面的 padding-bottom: 50px
为了兼容没有底部胡子的设备,让主体内容偏移出底部按钮的高度,避免按钮遮挡内容。
二、padding-bottom: calc(env(safe-area-inset-bottom) + 50px);
计算 底部非安全区域距离
与 底部按钮高度
之和 来作为 padding-bottom
值,若是设备支持 env,那么 calc 会计算出一个合法的值,本句的优先级则最高,会覆盖前面的 padding-bottom: 50px
。不然 calc 会计算出一个不合法的值,则本句声明不会生效。这样在不支持 env 设备中也能够达到兼容的目的。
目前到这,在横屏场景下左侧的内容就不会被刘海遮挡住了:
首先给底部按钮一个外层容器 .btn-container
,设置样式时其中有几点比较关键:
一、设置padding-bottom: env(safe-area-inset-bottom);
增长一个 padding 值,让底部向外扩展一个非安全区域的距离。
二、设置background: #FFF
让整个 .btn-container
背景为白色(包括刚新增的 padding-bottom 的区域)这样就能够遮挡住了底部内容。
三、设置 box-sizing: content-box;
,由于在一般状况下 css 在 reset 阶段通常都设置了 * {box-sizing: border-box;}
这样一来设置 padding 就不能向外扩展距离了,因此在这里咱们要把他改回 content-box
。
.btn-container {
box-sizing: content-box;
height: 50px;
line-height: 50px;
color: #fff;
position: fixed;
bottom: 0;
left: 0;
right: 0;
text-align: center;
background: #FFF;
padding-bottom: env(safe-area-inset-bottom);
}
.btn {
width: 100%;
height: 50px;
line-height: 50px;
background-color: #00c340;
border: none;
}
复制代码
看看效果:
若是兼容刘海和胡子须要满地找逻辑像素,满地找新 iphone,极可能是没有掌握正确的姿式。
另外,发如今横屏场景下有一个比较有趣的效果,你们能够了解一下,但在实际业务中应该不须要作得这么花哨: