引言
iPhoneX發布至今已經有將近一年的時間了,各類app都多多少少做了對iPhoneX的適配,那對於我們H5頁面該做哪方面的適配呢?
首先了解安全區域(safe area)的概念,它保證了內容在設備上的正確嵌入,不會被狀態欄、導航欄等遮擋。
Apps should adhere to the safe area and layout margins defined by UIKit, which ensure appropriate insetting based on the device and context. The safe area also prevents content from underlapping the status bar, navigation bar, toolbar, and tab bar.
-- by Apple's Human Interface Guidelines
圖1
對於h5頁面來說,通常是在瀏覽器或app的webview這樣的“容器”中打開,這些容器大都會做這樣的適配:
圖2
可以看到,這些容器都會保證頁面頂部在安全區內,而為了保證全屏體驗的效果,底部會占滿屏幕。
在不考慮橫屏瀏覽的情況下,我們只需要對底部導航做一個適配就可以啦~
如下圖所示,iPhoneX底部的危險區域高度為34pt,對應@3x頁面像素值為102px。我們可以根據這個值對底部導航做適配。
圖3
底部導航適配三法
1. js基本實現
var isIphoneX = window.devicePixelRatio && window.devicePixelRatio === 3 && window.screen.width === 375 && testUA('iPhone') if (isIphoneX) { document.body.classList.add('fix-iphonex-bottom') } function testUA (str) { return navigator.userAgent.indexOf(str) > -1 } .fix-iphonex-bottom .navi[data-v-539b7842]{ padding-bottom: 34px; }
demo:
2.js動態適配
如上圖2所示,針對有底部欄的瀏覽器,頁面滾動過程中底部欄顯示、隱藏的情況,我們可以做一個動態適配:
var isIphoneX = window.devicePixelRatio && window.devicePixelRatio === 3 && window.screen.width === 375 && testUA('iPhone') if (isIphoneX) { check() window.onscroll = throttle(check, 200) } function check () { // 處理lib-flexible放大viewport的情況 var scale = window.innerWidth / window.screen.width // 部分瀏覽器在滾動頁面時會顯示/隱藏工具欄,影響視口高度。在有底部工具欄的情況下,不做iPhoneX的fix。100為經驗值 if (window.screen.height - window.innerHeight / scale < 100) { document.body.classList.add('fix-iphonex-bottom') } else { document.body.classList.remove('fix-iphonex-bottom') } } function testUA (str) { return navigator.userAgent.indexOf(str) > -1 }
效果:
demo:
3.純css實現
In order to handle any adjustment that may be required iOS 11's version of Safari includes some constants that can be used when viewport-fit=cover is being used.
safe-area-inset-top
safe-area-inset-right
safe-area-inset-left
safe-area-inset-bottom
為了更好地適配IOS 11版本的safari提供了上面幾個變量。且當 viewport-fit=cover
時可以在css中使用。
首先設置meta標簽
-
<meta name=“viewport” content=”initial-scale=1, viewport-fit=cover”>
然后我們可以使用 constant()
(IOS 11.0-11.2)或 env()
(>IOS 11.2)來引用上面的變量
.selector{ /* 利用css fallback機制,下面的代碼可以兼容兩種版本 */ padding-top: env(safe-area-inset-top); padding-top: constant(safe-area-inset-top); }
如果需要基於這些變量計算,可以這么寫:
.selector{ --safe-area-inset-bottom: env(safe-area-inset-bottom); height: calc(80px + var(--safe-area-inset-bottom)); }
需要注意, safe-area-inset-bottom
這個變量的實際像素值是固定的(約為34px),如果我們對頁面進行了縮放,就要重新計算。比如我們的項目中使用手淘flexible布局方案,在iPhoneX上頁面的實際寬度為1125px,這時頁面底部的安全區域高度應為這個值的3倍:
.selector{ padding-bottom: calc(env(safe-area-inset-bottom) * 3); }
demo:
總結
js實現除了不夠優雅沒啥毛病,css實現因為是依賴於ios11版本的safari,有兼容性問題(測試發現內核為AppleWebkit/604.3.5的qq瀏覽器不支持,其他瀏覽器正常。具體兼容到哪個版本還未查到相關資料)
全部demo地址:https://marvinxu.github.io/demos/
References
-
iPhone X - Overview - iOS Human Interface Guidelines
-
三分鍾弄懂iPhoneX設計尺寸和適配
-
“The Notch” and CSS
-
Designing Websites for iPhone X
-
iPhone X layout features with CSS Environment variables(需翻牆)
-
CSS Round Display Level 1