移動(dòng)端適配我們需要做哪些事情? 一個(gè)最佳實(shí)踐除了設(shè)置 viewport
和 rem
基準(zhǔn)值吨拗,隨著iPhone手機(jī)的不斷升級(jí)蚪腐,我們不得不正視以下2個(gè)問(wèn)題:
- 安全區(qū)域適配
- 識(shí)別劉海屏
關(guān)于viewpoint-fit
在切入正題之前涛目,我們先展開介紹一下viewpoint-fit
骇钦,它的作用是用于設(shè)置可視區(qū)域的尺寸韧涨,屬性如下:
PropName | Description |
---|---|
Name | viewport-fit |
For | @viewpoint |
Value | auto | contaion | cover |
Initial | auto |
Percentages | N/A |
Computed value | as specified |
最初的布局視窗是通過(guò)物理設(shè)備的屏幕進(jìn)行計(jì)算劲室,如下圖所示:
圓形的屏幕上上顯示的頁(yè)面的一部分库糠,目前是圓的但視窗是長(zhǎng)方形的伙狐。因此,根據(jù)窗口的大小涮毫,頁(yè)面的某些部分可以省略。viewport-fit
可以通過(guò)設(shè)置可視區(qū)域的大小來(lái)控制被省略的區(qū)域贷屎。
-
auto
:當(dāng)設(shè)置成auto
時(shí)罢防,不會(huì)影響初始布局視口,并且整個(gè)網(wǎng)頁(yè)都是可見的唉侄。 UA在視口外部繪制的內(nèi)容未定義咒吐。 它可能是畫布的背景顏色,也可能是UA認(rèn)為合適的任何其他顏色属划。 -
contain
:當(dāng)設(shè)置成contain
時(shí)恬叹,初始布局視口和可視視口設(shè)置為最大矩形,該矩形內(nèi)接在設(shè)備的顯示中同眯。 UA在視口外部繪制的內(nèi)容未定義绽昼。 它可能是畫布的背景顏色,也可能是UA認(rèn)為合適的任何其他顏色须蜗。 -
cover
:當(dāng)設(shè)置成cover
時(shí)硅确,初始布局視口和可視視口設(shè)置為設(shè)備物理屏幕的外接矩形。
注意:當(dāng)設(shè)置成
contain
時(shí)明肮,border-boundary: display
和shape-inside: display
無(wú)效菱农。
在非矩形顯示器上設(shè)置視口邊界框的大小時(shí),我們必須考慮以下因素:
- 由于視口邊界框的區(qū)域大于顯示區(qū)域而導(dǎo)致的剪切區(qū)域
- 視口的邊界框與顯示區(qū)域之間的間隙
開發(fā)者可以決定哪個(gè)因素比另一個(gè)更重要柿估。 如果必須保證網(wǎng)頁(yè)的任何部分都不被隱藏循未,則避免剪切比在視口的邊界框和屏幕邊界之間留有間隙更重要。 如果開發(fā)者不希望網(wǎng)頁(yè)因可讀性而變小秫舌,那么最好將viewport-fit
設(shè)置為cover
并在考慮剪裁部分的情況下實(shí)現(xiàn)頁(yè)面的妖。
示例演示
為了方便理解,下面是針對(duì) contain
和 cover
的示例代碼和效果圖
當(dāng)使用contain
時(shí)足陨,初始視口將應(yīng)用于顯示的最大內(nèi)接矩形:
@viewport (viewport-fit: contain) {
/* CSS for the rectangular design */
}
當(dāng)使用cover
時(shí)羔味,初始視口應(yīng)用于顯示的外接矩形:
@viewport {
viewport-fit: cover;
}
@media (shape: round){
/* styles for the round design */
}
@media (shape: rect){
/* styles for the rectangular design */
}
安全區(qū)域適配
根據(jù)上文所述,為了安全區(qū)域不影響頁(yè)面渲染钠右,我們可以使用viewport-fit
等于cover
來(lái)來(lái)解決:
<meta name="viewport" content="width=device-width, initial-scale=1.0, viewport-fit=cover" />
識(shí)別劉海屏
ios識(shí)別劉海屏比較容易,我們可以通過(guò)計(jì)算屏幕的寬度和高度來(lái)快速識(shí)別忘蟹。首先我們羅列一下iPhone現(xiàn)有機(jī)型的屏幕尺寸:
Device | 豎屏尺寸 | 橫屏尺寸 | 縮放比例 |
---|---|---|---|
iPhone XS Max | 1242px * 2688px | 2688px * 1242px | x3 |
iPhone XS | 1125px * 2436px | 2436px * 1125px | x3 |
iPhone XR | 828px * 1792px | 1792px * 828px | x2 |
iPhone X | 1125px * 2436px | 2436px * 1125px | x3 |
iPhone 8 Plus | 1242px * 2208px | 2208px * 1242px | x3 |
iPhone 8 | 750px * 1334px | 1334px * 750px | x2 |
iPhone 7 Plus | 1242px * 2208px | 2208px * 1242px | x3 |
iPhone 7 | 750px * 1334px | 1334px * 750px | x2 |
iPhone 6s Plus | 1242px * 2208px | 2208px * 1242px | x3 |
iPhone 6s | 750px * 1334px | 1334px * 750px | x2 |
iPhone SE | 640px * 1136px | 1136px * 640px | x2 |
其中 iPhone XS Max飒房、iPhone XS、iPhone XR媚值、iPhone X 需要適配劉海屏狠毯,而這4類屏幕在真機(jī)或模擬器里表現(xiàn)出來(lái)的screen尺寸是有一個(gè)共性的:
screen.width === 375 && screen.height === 812
或
screen.width === 414 && screen.height === 896
完整的代碼如下:
function deviceDetection() {
const ua = navigator.userAgent
let osVersion = ''
let device = ''
try {
if (/android/i.test(ua)) {
device = 'android'
osVersion = ua.match(/Android\s+([\d.]+)/i)[0].replace('Android ', '')
} else if (/ipad|iphone|ipod/i.test(ua)) {
device = 'ios'
osVersion = ua.match(/OS\s+([\d_]+)/i)[0].replace(/_/g, '.').replace('OS ', '')
}
} catch (err) {
/* istanbul ignore next line */
console.error(err)
}
return { osVersion, device }
}
// 判斷是否為劉海屏
export function isFringe() {
const { device } = deviceDetection()
const { screen } = global
return device === 'ios' &&
((screen.width === 375 && screen.height === 812) || (screen.width === 414 && screen.height === 896))
}
此外,Android端雖然劉海屏機(jī)型較為雜多褥芒,但我們習(xí)慣容器上會(huì)把狀態(tài)欄的高度和劉海對(duì)齊嚼松,從而不影響內(nèi)容的展示
參考
本文由博客一文多發(fā)平臺(tái) OpenWrite 發(fā)布嫡良!