前言
iPhoneX 取消了物理按鍵,改成底部小黑條,這一改動導致網頁出現了比較尷尬的屏幕適配問題。對於網頁而言,頂部(劉海部位)的適配問題瀏覽器已經做了處理,所以我們只需要關注底部與小黑條的適配問題即可(即常見的吸底導航、返回頂部等各種相對底部 fixed 定位的元素)。
筆者通過查閱了一些官方文檔,以及結合實際項目中的一些處理經驗,整理了一套簡單的適配方案分享給大家,希望對大家有所幫助,以下是處理前后效果圖:
適配之前需要了解的幾個新知識
安全區域
安全區域指的是一個可視窗口范圍,處於安全區域的內容不受圓角(corners)、齊劉海(sensor housing)、小黑條(Home Indicator)影響,如下圖藍色區域:
也就是說,我們要做好適配,必須保證頁面可視、可操作區域是在安全區域內。
viewport-fit
iOS11 新增特性,蘋果公司為了適配 iPhoneX 對現有 viewport meta 標簽的一個擴展,用於設置網頁在可視窗口的布局方式,可設置三個值:
- contain: 可視窗口完全包含網頁內容(左圖)
- cover:網頁內容完全覆蓋可視窗口(右圖)
- auto:默認值,跟 contain 表現一致
注意:網頁默認不添加擴展的表現是 viewport-fit=contain,需要適配 iPhoneX 必須設置 viewport-fit=cover,這是適配的關鍵步驟。
env() 和 constant()
iOS11 新增特性,Webkit 的一個 CSS 函數,用於設定安全區域與邊界的距離,有四個預定義的變量:
- safe-area-inset-left:安全區域距離左邊邊界距離
- safe-area-inset-right:安全區域距離右邊邊界距離
- safe-area-inset-top:安全區域距離頂部邊界距離
- safe-area-inset-bottom:安全區域距離底部邊界距離
這里我們只需要關注 safe-area-inset-bottom 這個變量,因為它對應的就是小黑條的高度(橫豎屏時值不一樣)。
注意:當 viewport-fit=contain 時 env() 是不起作用的,必須要配合 viewport-fit=cover 使用。對於不支持env() 的瀏覽器,瀏覽器將會忽略它。
在這之前,筆者使用的是 constant(),后來,官方文檔加了這么一段注釋(坑):
The env() function shipped in iOS 11 with the name constant(). Beginning with Safari Technology Preview 41 and the iOS 11.2 beta, constant() has been removed and replaced with env(). You can use the CSS fallback mechanism to support both versions, if necessary, but should prefer env() going forward.
這就意味着,之前使用的 constant() 在 iOS11.2 之后就不能使用的,但我們還是需要做向后兼容,像這樣:
1
2
|
padding-bottom: constant(safe-area-inset-bottom); /* 兼容 iOS < 11.2 */
padding-bottom: env(safe-area-inset-bottom); /* 兼容 iOS >= 11.2 */
|
注意:env() 跟 constant() 需要同時存在,而且順序不能換。
如何適配
了解了以上所說的幾個知識點,接下來我們適配的思路就很清晰了。
第一步:設置網頁在可視窗口的布局方式
新增 viweport-fit 屬性,使得頁面內容完全覆蓋整個窗口:
1
|
<meta name="viewport" content="width=device-width, viewport-fit=cover">
|
前面也有提到過,只有設置了 viewport-fit=cover,才能使用 env()。
第二步:頁面主體內容限定在安全區域內
這一步根據實際頁面場景選擇,如果不設置這個值,可能存在小黑條遮擋頁面最底部內容的情況。
1
2
3
4
|
body {
padding-bottom: constant(safe-area-inset-bottom);
padding-bottom: env(safe-area-inset-bottom);
}
|
第三步:fixed 元素的適配
類型一:fixed 完全吸底元素(bottom = 0),比如下圖這兩種情況:
可以通過加內邊距 padding 擴展高度:
1
2
3
4
|
{
padding-bottom: constant(safe-area-inset-bottom);
padding-bottom: env(safe-area-inset-bottom);
}
|
或者通過計算函數 calc 覆蓋原來高度:
1
2
3
4
|
{
height: calc(60px(假設值) + constant(safe-area-inset-bottom));
height: calc(60px(假設值) + env(safe-area-inset-bottom));
}
|
注意,這個方案需要吸底條必須是有背景色的,因為擴展的部分背景是跟隨外容器的,否則出現鏤空情況。
還有一種方案就是,可以通過新增一個新的元素(空的顏色塊,主要用於小黑條高度的占位),然后吸底元素可以不改變高度只需要調整位置,像這樣:
1
2
3
4
|
{
margin-bottom: constant(safe-area-inset-bottom);
margin-bottom: env(safe-area-inset-bottom);
}
|
空的顏色塊:
1
2
3
4
5
6
7
8
|
{
position: fixed;
bottom: 0;
width: 100%;
height: constant(safe-area-inset-bottom);
height: env(safe-area-inset-bottom);
background-color: #fff;
}
|
類型二:fixed 非完全吸底元素(bottom ≠ 0),比如 “返回頂部”、“側邊廣告” 等
像這種只是位置需要對應向上調整,可以僅通過外邊距 margin 來處理:
1
2
3
4
|
{
margin-bottom: constant(safe-area-inset-bottom);
margin-bottom: env(safe-area-inset-bottom);
}
|
你也可以使用 @supports 隔離兼容樣式
寫到這里,我們常見的兩種類型的 fixed 元素適配方案已經了解了吧。如果我們只希望 iPhoneX 才需要新增適配樣式,我們可以配合 @supports 來隔離兼容樣式,當然這個處理對頁面展示實際不會有任何影響:
1
2
3
4
5
6
|
@supports (bottom: constant(safe-area-inset-bottom)) or (bottom: env(safe-area-inset-bottom)) {
div {
margin-bottom: constant(safe-area-inset-bottom);
margin-bottom: env(safe-area-inset-bottom);
}
}
|
轉自https://www.jonhuu.com/sample-post/386.html
喜歡這篇文章?歡迎打賞~~