轉自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-fitmarkdown
各類 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,極可能是沒有掌握正確的姿式。
另外,發如今橫屏場景下有一個比較有趣的效果,你們能夠了解一下,但在實際業務中應該不須要作得這麼花哨: