隨著這兩年蘋果堅(jiān)定不移的走劉海屏路線,Hybrid 頁(yè)面在 iPhoneX 上劉海屏的適配也是每個(gè)前端開(kāi)發(fā)的小伙伴都會(huì)碰到的問(wèn)題,今天就記錄一下我關(guān)于劉海屏適配的部分經(jīng)驗(yàn)肴盏。
對(duì)于劉海屏的適配,你的腦子里首先得有蘋果手機(jī)的 Safe Area 的概念,關(guān)于 Safe Area 網(wǎng)上的資料已經(jīng)非常多了婿滓,這里就不再贅述,更偏向?qū)崙?zhàn)一點(diǎn)粥喜。但是為了比較凸主,我這里給出一張?zhí)O果官方文檔中,iPhone8之前的常規(guī)屏幕和劉海屏 Safe Area 區(qū)域的對(duì)比圖额湘。
很明顯卿吐,在討論適配之前,我們的頁(yè)面一般有兩種分類:
- 1缩挑、H5 頁(yè)面使用原生 App 的 Navigation Bar 導(dǎo)航欄但两,此時(shí),status bar 狀態(tài)欄和導(dǎo)航欄都是原生控件供置,我們只需要專注的適配底部小黑條處的高度差異即可谨湘。
- 2、H5 頁(yè)面在 iOS 中占據(jù)全屏頁(yè)面,在這種情況下紧阔,除了要兼顧底部小黑條坊罢,我們還要處理頁(yè)面上部跟 狀態(tài)欄接觸的部分,避免內(nèi)容出現(xiàn)在狀態(tài)欄上擅耽。
env 函數(shù)
在介紹適配之前活孩,我們先說(shuō)一下適配用到的關(guān)鍵 CSS 函數(shù) —— env()
。env()
函數(shù)以類似于var
函數(shù)的方式將用戶代理定義的環(huán)境變量值插入到你的 CSS 中去乖仇。這個(gè)函數(shù)最初由 iOS 瀏覽器提供憾儒,用于允許開(kāi)發(fā)人員將其內(nèi)容放置在視口的安全區(qū)域中,該規(guī)范中定義的 safe-area-inset-*
值用于確保內(nèi)容即使在非矩形的視區(qū)中也可以完全顯示乃沙。
頁(yè)面適配
在為頁(yè)面適配劉海屏之前起趾,我們首先得在頁(yè)面的 meta 中添加一個(gè)新的值:viewport-fit=cover
<meta name="viewport" content="viewport-fit=cover">
這么設(shè)置之后,視圖端口被縮放以填充設(shè)備顯示警儒。換句話說(shuō)就是網(wǎng)頁(yè)會(huì)擴(kuò)展到整個(gè)屏幕训裆。
看一頁(yè)目前的頁(yè)面效果:
可以看到現(xiàn)在我們的測(cè)試頁(yè)面已經(jīng)鋪滿了整個(gè)屏幕。
這個(gè)時(shí)候蜀铲,我們來(lái)使用之前提到的 env 函數(shù)边琉,適配劉海屏幕。
body {
padding:
constant(safe-area-inset-top)
constant(safe-area-inset-right)
constant(safe-area-inset-bottom)
constant(safe-area-inset-left); /* 兼容 iOS < 11.2 */
padding:
env(safe-area-inset-top)
env(safe-area-inset-right)
env(safe-area-inset-bottom)
env(safe-area-inset-left); /* 兼容 iOS >= 11.2 */
}
為什么這里會(huì)使用 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.
意味著 iOS11.2 以后 constant()
不能使用变姨,所以需要向后兼容。
此時(shí)再看一下我們的頁(yè)面效果:
可以看到頁(yè)面的頂部隆夯,因?yàn)?safe-area-inset-top
避開(kāi)了狀態(tài)欄钳恕,而底部因?yàn)?safe-area-inset-bottom
避開(kāi)了小黑條,完美的顯示在了 Safe Area 的區(qū)域中蹄衷。
當(dāng)你的頁(yè)面不使用原生導(dǎo)航欄鋪在整個(gè)屏幕中時(shí)忧额,這就是一個(gè)不錯(cuò)的適配方案。
而當(dāng)你使用了原生導(dǎo)航欄愧口,僅僅需要適配底部小黑條時(shí)睦番,解決方案就更簡(jiǎn)單了,簡(jiǎn)單設(shè)置 safe-area-inset-bottom
就可以:
body {
padding-bottom: constant(safe-area-inset-bottom);
padding-bottom: env(safe-area-inset-bottom);
}
處理 Fixed 和 絕對(duì)定位的情況
有時(shí)我們底部的元素是通過(guò) fixed 或者 absolute 定位放置的耍属,例如底部的按鈕托嚣、工具欄等等,對(duì)于這些元素厚骗,簡(jiǎn)單的使用 safe-area-inset-bottom
是無(wú)效的示启,但是我們可以對(duì)該元素單獨(dú)增加內(nèi)邊距的 padding 來(lái)解決。
.element {
padding-bottom: constant(safe-area-inset-bottom);
padding-bottom: env(safe-area-inset-bottom);
}
或者通過(guò)增加該元素的高度來(lái)解決
@element-height: 60px; /* 元素原始高度 */
.element {
height: calc(@element-height + constant(safe-area-inset-bottom));
height: calc(@element-height + env(safe-area-inset-bottom));
}
以及你可以通過(guò) less领舰、sass 的函數(shù)夫嗓,通過(guò)媒體查詢來(lái)準(zhǔn)確的定位到劉海屏的手機(jī)迟螺,然后寫入你希望劉海屏手機(jī)展示的任何樣式。
下面我就放一個(gè)我寫的 less 適配劉海屏的例子:
/**
* 適配 iPhoneX 及以后的劉海屏手機(jī)舍咖,可以自行編寫 rules 規(guī)則
*/
.safe-area(@rules) {
/* iphone x / xs / 11 pro*/
@media only screen and (device-width: 375px) and (device-height: 812px) and (-webkit-device-pixel-ratio: 3) { @rules(); }
/* iphone xr / 11 stackoverflow 提供判斷 */
@media only screen and (device-width: 414px) and (device-height: 896px) and (-webkit-device-pixel-ratio: 2) { @rules(); }
// 實(shí)際可用的 xr 判斷
@media only screen and (device-width: 375px) and (device-height: 812px) and (-webkit-device-pixel-ratio: 2) { @rules(); }
/* iphone xs max / 11 pro max */
@media only screen and (device-width: 414px) and (device-height: 896px) and (-webkit-device-pixel-ratio: 3) { @rules(); }
}
// 具體使用
.safe-area({
height: 100px;
padding-bottom: env(safe-area-bottom-height);
});
當(dāng)編譯后矩父,就可以根據(jù)機(jī)型完成適配。這里要注意的是排霉,實(shí)測(cè)時(shí)窍株,對(duì)于 iPhone XR 我用在 stackoverflow 上找到的 media query 條件來(lái)判斷不生效,后來(lái)經(jīng)過(guò)查找資料攻柠,我找到一個(gè)在 iPhone XR 上實(shí)際可用的條件球订,也一并放在上面的代碼中。
最后辙诞,如果這篇文章有幫助到你在適配中填坑辙售,請(qǐng)給我點(diǎn)個(gè)贊哦 ??