兼容iphone x劉海的正確姿式

轉自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


這樣只是解決了底部鬍子的問題,咱們試着橫屏看看:
這裏有個很明顯的問題:頁面左邊的文字被劉海遮擋。

在 safari 往上段滑動一小段距離,能夠看到當 safari 的底部操做欄出現後,頁面依然會保留着距底部的 34px 空白。

這些處理若是在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

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

關於 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( ) 能夠獲取到非安全邊距,再結合 paddingmargin 來控制頁面元素避開非安全區域。 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( )。

實踐一波

1、設置網頁在可視區域的佈局方式

新增 viweport-fit 屬性,使得頁面內容徹底覆蓋整個窗口:

<meta name="viewport" content="width=device-width,initial-scale=1.0,viewport-fit=cover">
複製代碼

2、讓主體內容控制在安全區域內

假設咱們的底部按鈕高度是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 設備中也能夠達到兼容的目的。

目前到這,在橫屏場景下左側的內容就不會被劉海遮擋住了:

3、底部按鈕的處理

首先給底部按鈕一個外層容器 .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;
}
複製代碼

看看效果:


在 safari 中,頁面往上稍滑動一點,出現 safari 的操做欄後,底部按鈕依然會緊貼着操做欄,很是有靈性:

處理起來一切都顯得 簡潔優雅細膩。

最後

若是兼容劉海和鬍子須要滿地找邏輯像素,滿地找新 iphone,極可能是沒有掌握正確的姿式。
另外,發如今橫屏場景下有一個比較有趣的效果,你們能夠了解一下,但在實際業務中應該不須要作得這麼花哨:


藉助CSS Shapes實現元素滾動自動環繞iPhone X的劉海
相關文章
相關標籤/搜索