在 ios 11 中我們可以使用 viewport-fit=cover + safe-area-inset-*。
那么是不是 ios11 以下就用不了這些了呢?是的,但你見過 iphone x+ 有 ios 11以下的嗎? 所以我們可以愉快的搞下去。
開始之前我們先了解什么是 safe area,簡單的來說就是除了劉海和胡子以外的區域為安全區域:
關於 viewport-fit
viewport-fit 有3個值:
contain: 可視窗口完全包含網頁內容(左圖)
cover:網頁內容完全覆蓋可視窗口(右圖)
auto:默認值,跟 contain 表現一致
如何決定 viewport-fit 值?我們要考慮一些問題:
1、在非矩形顯示器上設置 viewport 邊界時,Viewport邊界框(Viewport Bounding Box)的面積大於顯示區域,導致了剪切區域
2、如果要保證Web頁面的任何部分都沒有隱藏,不想讓Web頁面在可讀性上變得很小,那么最好將viewport-fit設置為cover,並在考慮剪切部分時實顯示頁面。
3、還有另一個考慮是,當我們設置 viewport-fit:contain,也就是默認的時候時,設置 safe-area-inset-* 等 css 屬性時不起作用的。 點擊這里了解更多關於 viewport-fit
關於 safe-area-inset-*
各種 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);
}
有兩個關鍵點:
1、寫在前面的 padding-bottom: 50px 為了兼容沒有底部胡子的設備,讓主體內容偏移出底部按鈕的高度,避免按鈕遮擋內容。
2、padding-bottom: calc(env(safe-area-inset-bottom) + 50px); 計算 底部非安全區域距離 與 底部按鈕高度 之和 來做為 padding-bottom 值,如果設備支持 env,那么 calc 會計算出一個合法的值,本句的優先級則最高,會覆蓋前面的 padding-bottom: 50px。否則 calc 會計算出一個不合法的值,則本句聲明不會生效。這樣在不支持 env 設備中也可以達到兼容的目的。
目前到這,在橫屏場景下左側的內容就不會被劉海遮擋住了
三、底部按鈕的處理
首先給底部按鈕一個外層容器 .btn-container ,設置樣式時其中有幾點比較關鍵:
1、設置padding-bottom: env(safe-area-inset-bottom);增加一個 padding 值,讓底部向外擴展一個非安全區域的距離。
2、設置background: #FFF 讓整個 .btn-container 背景為白色(包括剛新增的 padding-bottom 的區域)這樣就可以遮擋住了底部內容。
3、設置 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; }
在 safari 中,頁面往上稍滑動一點,出現 safari 的操作欄后,底部按鈕依然會緊貼着操作欄,非常有靈性:
處理起來一切都顯得 簡潔優雅細膩。
