移動端安全區域適配方案

南玖發表於2024-04-16

前言

什麼是安全區域?

自從蘋果推出了驚豔的iPhone X,智慧手機界就正式步入了全面屏的新紀元。然而,這一革新也帶來了一個特別的問題——那就是螢幕頂部的“劉海”和底部的“黑條”區域。這些區域猶如手機的“神秘面紗”,遮擋了一部分螢幕,給開發者帶來了新的挑戰。

Android似乎對iPhone的設計情有獨鍾,紛紛效仿這種全面屏的潮流。於是,越來越多的Android手機也開始有了這個安全區域的概念。

在這個背景下,移動端安全區域適配變得尤為重要。開發者們需要巧妙地調整應用的佈局和介面,確保內容不會被這些特殊區域遮擋,同時保持應用的美觀和易用性。

安全區域(safe area)

安全區域定義為檢視中未被導航欄、選項卡欄、工具欄或檢視控制器可能提供的其他檢視覆蓋的區域。

如上圖所示,安全區域為中間藍色部分,也就是說我們在頁面佈局時應該保證頁面內容在藍色安全區域內。

所以對於這類機型,你如果不特殊處理,那麼它將會是這樣的:

這樣就會導致底部輸入框的互動受影響

網頁佈局方式(viewport-fit)

在處理安全區域之前,我們需要先來了解viewport-fit屬性,這是解決問題的關鍵。

iOS帶來問題的同時也帶來了解決問題的方法,為了適配 iPhoneX等全面屏機型 對現有 viewport meta 標籤進行了擴充套件,用於設定視覺視口的大小來控制裁剪區域。

用法

<meta name="viewport" content="width=device-width,initial-scale=1, user-scalable=0, viewport-fit=cover">

屬性值

該屬性包含三個值:

  • auto:該值不會影響初始佈局視口,並且整個網頁都是可見的。 UA 在視口之外繪製的內容是未定義的。它可以是畫布的背景顏色,或者 UA 認為合適的任何其他顏色。(預設值,與contain表現一致)
  • contain:初始佈局視口和視覺視口設定為裝置螢幕中內接的最大矩形。 UA 在視口之外繪製的內容是未定義的。它可以是畫布的背景顏色,或者 UA 認為合適的任何其他顏色。
  • cover:初始佈局視口和視覺視口設定為裝置物理螢幕的外接矩形。

區別

在非矩形顯示器上(比如手錶)設定視口邊界框的大小時,我們必須考慮以下因素:

  • 由於視口邊界框的面積大於顯示器的面積而導致的剪下區域
  • 視口邊界框與顯示區域之間的間隙

contain

當使用viewport-fit: contain時,初始視口將應用於顯示器的最大內接矩形。

cover

當使用viewport-fit: cover時,初始視口將應用於顯示器的外接矩形。

env

為了解決安全區域問題,iOS 11 新增了一個新的 CSS 函式env()和四個預定義的環境變數

  • safe-area-inset-left:安全區域距離左邊邊界距離

  • safe-area-inset-right:安全區域距離右邊邊界距離

  • safe-area-inset-top:安全區域距離頂部邊界距離

  • safe-area-inset-bottom:安全區域距離底部邊界距離

iOS 11 中提供的 env() 函式名為 constant()。從 Safari 技術預覽版 41 和 iOS 11.2 beta 開始,constant() 已被刪除並替換為 env()。如有必要,您可以使用 CSS 後備機制來支援這兩個版本,但以後應該更喜歡使用 env()。 —— 來自webkit文件

上面的意思是從iOS12開始不再支援使用constant函式,所以為了相容處理,我們應該這樣寫:

body {
  padding-bottom: constant(safe-area-inset-bottom); /* 相容 iOS < 11.2 */
  padding-bottom: env(safe-area-inset-bottom); /* 相容 iOS >= 11.2 */
}

使用該函式的前提是必須設定meta標籤viewport-fit=cover ,並且對於不支援 env() 的瀏覽器,瀏覽器將會忽略它。

適配安全區域

第一步:

修改頁面佈局方式

<meta name="viewport" content="width=device-width,initial-scale=1, user-scalable=0, viewport-fit=cover">

第二步:

底部適配

.keyboard_foot {
    padding-bottom: constant(safe-area-inset-bottom);
    padding-bottom: env(safe-area-inset-bottom);
}

這樣安全區域問題就解決了!

相關文章