前端面試之移動端適配篇

關於像素,括號中爲別名

設備像素(物理像素)

DP(Device Pixel),顯示屏上的像素點,出廠即確定。

設備無關像素(設備獨立像素)

DIP(Device Independent Pixel),縮放比爲1時,設備獨立像素也等於CSS像素(邏輯像素)。我們通過CSS和javascript代碼設置的像素都是邏輯像素。在CSS規範中,長度單位可以分爲兩類,絕對(absolute)單位以及相對(relative)單位,px是一個相對單位,相對的是設備像素(device pixel)。顯示器上的小色框就是像素。

設備無關像素與CSS像素之間的關係 —— 頁面縮放比

頁面縮放比 = CSS像素/設備無關像素

設備像素與設備無關像素之間的關係 —— DPR

一般情況下,

設備像素比DPR = 設備像素/設備無關像素(在某一方向上,x方向或者y方向)

縮放比爲1時, 設備無關像素等於CSS像素,因此

設備像素比DPR = 設備像素/CSS像素(在某一方向上,x方向或者y方向)

縮放比爲1時,iphone4下dpr=2,iphone6 plus及以後dpr=3。
以iphone6爲例,iphone6的CSS像素爲375px*677px,DPR是2,所以其設備像素爲750px*1354px(x和y方向都乘了2)。

設備像素與CSS像素之間的關係

在PC端,CSS的1px往往等於一個設備像素。而在移動端,在不同的設備或不同的環境中,css中的1px所代表的設備物理像素是不同的。以iPhone爲例,iPhone4之前的手機,屏幕像素密度都較低,CSS的1px等於一個設備像素。但從iPhone4開始,喬布斯提出了Retina視網膜屏的概念。此時一個CSS像素等於(dpr*頁面縮放比)個設備像素。

獲取DPR的方法

  1. js獲取:window.devicePixelRatio

    打開控制檯,輸入window.devicePixelRatio。就可以看到當前設備的DPR。切換手機視圖,再次輸入,可以看到模擬的手機視圖的DPR。
    在這裏插入圖片描述
    上圖中,第一個是PC端dpr,第二個是iPhoneX的dpr。

  2. css媒體查詢:min-device-pixel-ratio

關於視口

這部分內容中的圖借用一下思否中的一篇文章:關於移動端適配,你必須知道的

佈局視口(layout viewport)

佈局視口就是DOM的寬度。各瀏覽器默認的 layout viewport寬度一般都是800,980,1024等值。

在這裏插入圖片描述

js獲取

document.documentElement.clientWidth

document.documentElement.clientHeight

視覺視口(visual viewport)

視覺視口是可見視口,在PC端,瀏覽器窗口可以調整,視覺窗口等於整個瀏覽器的寬度,而在移動端,瀏覽器不能縮放,因此視覺視口即爲屏幕的寬度。

在這裏插入圖片描述

js獲取

window. innerWidth

window.innerHeight

理想視口(ideal viewport)

理想視口的概念常用於移動端,使用戶不需要縮放,也不需要出現橫向滾動條,便可以正常看到網站的所有內容。

理想視口下,佈局視口寬度 = 視覺視口寬度 = 設備寬度

由此也可以得到,

當前縮放值 = ideal viewport寬度  / visual viewport寬度

js獲取

screen.width

screen.height

設置理想視口

<meta name="viewport" content="width=device-width; initial-scale=1;">

關於initial-scale的默認值,安卓設備上沒有明確的定義。在iphone和ipad上,無論你給viewport設的寬度是多少,如果沒有指定默認的縮放值,則iphone和ipad會自動計算這個縮放值,以達到當前頁面不會出現橫向滾動條(或者說viewport的寬度就是屏幕的寬度)的目的。

比如在iPhone5下,不設置任何的viewport meta標籤時,layout viewport的默認寬度爲980px,但瀏覽器的visual viewport寬度爲320px,因此initial-scale = 320/890,約爲0.327。

移動端適配解決方案

1. viewport(scale=1/dpr)

<meta name="viewport" content="width=device-width; initial-scale=1; maximum-scale=1; minimum-scale=1; user-scalable=no;">

各個屬性的含義:

device-width等於理想視口的寬度,設置width=device-width就相當於讓佈局視口等於理想視口。

initial-scale = 理想視口寬度 / 視覺視口寬度,設置initial-scale=1就相當於讓視覺視口等於理想視口。

這時,1個CSS像素就等於1個設備獨立像素,而且我們也是基於理想視口來進行佈局的,所以呈現出來的頁面佈局在各種設備上都能大致相似。

2. rem

rem是css3新增的一個相對單位。rem爲相對HTML根元素的大小,除了IE8及更早的版本外,其他瀏覽器都支持rem。

阿里早期開源了一個移動端適配解決方案 —— flexible。通過這種方案,我們在頁面上統一使用rem佈局。

核心代碼:

// set 1rem = viewWidth / 10
function setRemUnit () {
    var rem = docEl.clientWidth / 10
    docEl.style.fontSize = rem + 'px'
}
setRemUnit();

上面的代碼中,將html節點的font-size設置爲頁面clientWidth(佈局視口)的1/10,即1rem就等於頁面佈局視口的1/10,這就意味着我們後面使用的rem都是按照頁面比例來計算的。

這樣我們只需要將設計稿的px轉成對應的rem即可。

在viewport和vw、vh存在兼容性問題的時候,阿里提出了這種解決方案。但是這種方案實際上是根據屏幕大小百分百還原設計稿,也就是說在屏幕大的設備上看到的元素會大一些,但是這個顯然不符合我們的需求。用戶使用更大的屏幕並不是爲了看到更大的字,而更多地是爲了看到更多的內容。

因此,這種方案最後被淘汰掉。

3. vm/vh

vh、vw方案即將視覺視口寬度 window.innerWidth 和視覺視口高度 window.innerHeight 等分爲 100 份。

這種方案和上面的方案解決問題的思路一樣。這個是需要將設計稿的px轉成對應的vw,當然這種比例關係我們不用手動計算,webpack解析css時有個postcss-px-to-viewport插件,可以實現px到vw的自動轉化。

這種方案同樣存在上面提到的無法看更多內容的問題。另外,px轉換成vw不一定能完全整除,因此有一定的像素差。

4. flex

關於flex彈性佈局的用法可以參考阮一峯老師的這篇文章Flex 佈局教程:語法篇。在更大的屏幕上,flex佈局可以完美地爲用戶呈現更多內容。

移動端適配整體流程

  1. 在 head 設置 width=device-width 的 viewport‘
  2. 在 css 中使用 px
  3. 在適當的場景使用 flex 佈局,或者配合 vw 進行自適應
  4. 在跨設備類型的時候(pc <-> 手機 <-> 平板)使用媒體查詢
  5. 在跨設備類型如果交互差異太大的情況,考慮分開項目開發

1px問題及解決方案

1px問題

這裏的1像素指的是CSS像素。因此我們可以發現,在寫1px的時候,在不同dpr的物理設備上映射的設備像素是不同的。dpr爲2時,映射的像素爲2px;dpr3時就映射成3px。這樣的話,如果在屏幕尺寸比較大的設備上(準確來說時設備像素比較大),1px渲染出來就樣子就會有些粗。

解決方案

利用媒體查詢 + css3的transform

利用媒體查詢區分二倍屏和三倍屏,利用transform:scale(xx)對高度進行縮放。代碼如下:

/*二倍屏*/
@media only screen and (-webkit-min-device-pixel-ratio: 2.0) {
    .my-border::after {
        transform: scaleY(0.5);
        webkit-transform: scaleY(0.5);
    }
}
/*三倍屏*/
@media only screen and (-webkit-min-device-pixel-ratio: 3.0) {
    .my-border::after {
        transform: scaleY(0.33);
        webkit-transform: scaleY(0.33);
    }
}

小數寫px(如0.5px)

IOS8下已經支持帶小數的px值,安卓與低版本IOS不適用。另外,各個瀏覽器對小數px的實現方式也不相同。

小知識

瀏覽器默認字體爲16px

瀏覽器最小字號12px

p代表的是縱向的像素數,1080p是指縱向有1080個像素

k代表的是橫向的像素數,2k屏是指橫向超過2048個像素的屏

參考鏈接

https://juejin.im/post/5e6caf55e51d4526ff026a71

https://segmentfault.com/a/1190000019207842#item-7-22

http://html-js.com/article/MobileWeb

https://www.jianshu.com/p/b13d811a6a76

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章