移動端Web頁面適配淺析


title: 移動端Web頁面適配淺析
date: 2018-01-31 16:38:01
tags: 移動端 適配


移動端Web頁面適配淺析

以前對移動端Web適配的原理一頭霧水,對于幾個概念dprppiviewportdevice-width 等的概念用法邏輯總是有些迷茫。最近重新閱讀了幾篇好文章,也自己去查了一些相關的概念,對這一塊再重新加深了理解。文章力求直觀描述移動端Web頁面的適配思路,以及適配過程中有必要了解的基礎概念。部分用詞、概念及公式使用可能不妥,望指正。

移動端適配的經驗總結參考文章

從網易與淘寶的font-size思考前端設計稿與工作流-流云諸葛

移動端適配方案(上)

網易和淘寶移動WEB適配方案再分析-吳成琦

Native 適配過程

要了解移動Web端的適配思路,首先要知道終端都是如何進行適配的。

無論是iOS還是Android端,設計通常給的設計稿標注是dp或者pt

iOS 設計稿.png

為了明確dp以及pt 的概念,在這里對文章進行了一些總結,如果需要更為具體的內容,請參考如下文章:徹底理解 UI 及 Web 的尺寸單位:基本觀念-Taylor Hu

ptdp是屏幕密度無關的單位

pt(point)是iOS開發的單位,dp(density-independent pixels )是google開發的單位。兩者都是屏幕密度無關的單位,也就是和屏幕一個平方單位內實際的物理像素的個數(即屏幕密度)無關。

再形象一點,以iOS為例,假設用標準的尺子畫一個1cm1cm的矩形框,那么無論是iPhone顯示屏清晰度不同的第一代低清顯示屏,還是iPhoneX的超視網膜高清屏,框出來的屏幕面積都是1cm^2。 iOS設計pt單位就是這么一個思路,你可以把pt想象成毫米,微米等絕對長度單位,是一個與設備物理像素無關的單位。這樣一來,如果我們假設1pt = 1cm 且iPhone6設計稿中一個按鈕的寬度是10pt,那么就意味著在任何屏幕密度的iPhone屏幕上,這個按鈕都為10cm*寬。

實際蘋果公司在定義pt單位的時候,就是以第一代屏幕(iPhone3GS)為基準,第一代屏幕(iPhone3GS)的一個物理的像素點寬度為1pt ,設備像素比dpr(devicePixelRatio)為1。隨著iPhone 屏幕的升級,1pt1pt* 內的物理像素點就會增多,屏幕密度也逐漸變高,到了iPhone4 ,1pt1pt* 內就包含了4個物理像素點,dpr就為2,到了iPhone6 plus,1pt1pt* 內理論上有9個物理像素點,dpr為3(為什么是理論上有9個物理像素點,之后再分析)。從這里就可以推導出設備像素比dpr的一個直觀的概念,即$1pt = 設備像素比(dpr)*物理像素點寬$ 。

回到上面的例子,這個例子產生一個問題:假設1pt = 1cm ,iPhone6設計稿上一個按鈕的寬度是10pt,那么無論在什么屏幕上,這個按鈕都為10cm寬。這個寬度的按鈕放到iPhone6以下的手機,例如iPhone5s,iPhone4等看起來不就會過寬么?沒錯,就是會過寬!所以實際iOS工程師在適配的過程中,會根據不同iPhone物理分辨率進行換算后的邏輯分辨率進行等比例的縮放。根據表格中的邏輯分辨率,iPhone6設計稿上一個按鈕的寬度是10pt,那么如果需要適配iPhone5s,就需要根據iPhone5s邏輯分辨率寬度320及iPhone6邏輯分辨率寬度375將按鈕進行等比例的縮放。
$iPhone5s 按鈕的寬度 = iPhone6 按鈕的寬度10pt*(iPhone5s邏輯分辨率寬度320/iPhone6邏輯分辨率寬度375)$

iOS適配過程

下圖是到目前為止,所有iPhone手機屏幕的尺寸、物理分辨率以及邏輯分辨率等詳細參數的匯總:

設備 屏幕尺寸 分辨率(pt) Reader 分辨率(px) ppi
iPhone 3GS 3.5吋 320x480 @1x 320x480 163
iPhone 4/4s 3.5吋 320x480 @2x 640x960 330
iPhone 5/5s/5c 4.0吋 320x568 @2x 640x1136 326
iPhone 6 4.7吋 375x667 @2x 750x1334 326
iPhone 6Plus 5.5吋 414x736 @3x 1080x1920 401
iPhone 6s 4.7吋 375x667 @2x 750x1334 326
iPhone 6sPlus 5.5吋 414x736 @3x 1080x1920 401
iPhone 7 4.7吋 375x667 @2x 750x1334 326
iPhone 7Plus 5.5吋 414x736 @3x 1080x1920 401
iPhone 8 4.7吋 375x667 @2x 750x1334 326
iPhone 8Plus 5.5吋 414x736 @3x 1080x1920 401
iPhone X 5.8吋 375x812 @3x 1125 x 2436 458

我們會發現@1x屏幕到@2x 屏幕是完全滿足1pt1pt* 范圍內從包含1個物理像素點到包含了4個物理像素點的轉換的,例如iPhone3GS到iPhone4、iPhone6、iPhone7、iPhone8;然而,iPhone6Plus、iPhone6sPlus、iPhone7Plus及iPhone8Plus似乎并不滿足1pt1pt* 范圍內從包含1個物理像素點到包含了9個物理像素點的轉換。

參考godlaugh的回答 ,在這里將原理進行簡單描述,我們以iPhone6Plus為例子進行深度的分析。

設備 屏幕尺寸 分辨率(pt) Reader 分辨率(px) ppi dpi
iPhone 6 4.7吋 375x667 @2x 750x1334 326 163
iPhone 6Plus 5.5吋 414x736 @3x 1080x1920 401 154
iPhone 6Plus(a) 5.5吋 414x736 @3x 1242x2208 461 154
iPhone 6Plus(b) 5.5吋 360x640 @3x 1080x1920 401 134
iPhone 6Plus(c) 5.5吋 540x960 @2x 1080x1920 401 200
iPhone 6Plus(d) 6.7吋 540x960 @2x 1080x1920 326 163

iOS設計pt單位是從兩個角度進行考慮:

  1. 整個屏幕可現實的內容多少
  2. 界面UI元素可點擊的物理區域大小

先理清ppidpi定義的區別

ppi : pixels per inch;

dpi : dots per inch,dot是指一個邏輯point。

再詳細分析:

  1. iPhone 6Plus(b)方案:

    保持iphone 6Plus 現有物理分辨率1080 * 1920 不變,dpr為3。此時邏輯分辨率將縮小到360 * 640,邏輯分辨率的長寬都比iphone6 的邏輯分辨率小。

    優點: iphone 6Plus(b)的屏幕密度更大,更為精細

    缺點:實際可顯示的內容卻少于iphone6。

    舉例:iphone6 一行顯示25個字符,iphone 6Plus(b) 僅能顯示24個字符。

    ?

  2. iPhone 6Plus(c)方案:

    保持iphone 6Plus 現有物理分辨率1080 * 1920 不變,dpr為2。此時邏輯分辨率將擴大到540 * 960 。在這種情況下,似乎應該選用iPhone 6Plus(d)方案,但是如果選用 iPhone 6Plus(d),在保持長寬比為16 : 9的比例下,iPhone 6Plus(d)屏幕將達不可思議的6.7吋,因此,該方案不可行。

    實際蘋果公司是根據市場需求,先確定plus手機的屏幕尺寸5.5吋,長寬比為16 : 9;再這個前提下,使用iPhone 6Plus(c)的方案(@2x)無可避免地需要相對iphone6 縮小每一個物理像素的大小。

    優點: iphone 6Plus(c)的屏幕密度更大,實際可顯示的內容多于iphone6。

    缺點:所有UI元素的尺寸在屏幕上的實際物理面積一下就變小了。

    舉例:比如標簽欄或導航欄按鈕的物理高度只有原來的 81.5% (163/200),點擊面積就只有iPhone 6的 0.815*0.815=66.4%。

  3. iPhone 6Plus(a) 方案:

    該方案物理像素做到1242x2208,那么在5.5吋屏幕下ppi將達到461。

    優點: iphone 6Plus(a)的屏幕密度更大,實際可顯示的內容多于iphone6。

    缺點:1)內存消耗巨大;

    ? 2)電池消耗巨大;

    ? 3)要做到 461ppi ,當前工藝可能存在一定難度

    舉例: iphoneX 就在真正意義上做到@3x的顯示屏。

    ?

  4. iPhone 6Plus 方案:

    蘋果公司最終過渡選擇了iphone 6Plus方案估計是因為在5.5吋屏幕大小要求以及ppi小于461的前提下,只能選用該方案。也就是說,理論意義上 iphone 6Plus 并不是一個@3x屏幕,而是一個@2.46x(401/326*2) 左右的屏幕。這個倍數對于切圖造成了極大的困難,所以蘋果為方便開發者用的是@3x的素材,然后再縮放到@2.46x上,實際上是縮放到2.46/3=83%。
    ?

Android適配過程

和iOS 一樣,Google 也制定了一套密度等級規范屏幕參數,其中xxxhdpi屏幕就是我們所說的4K。

密度類型 代表的分辨率(px) dpi Reader
中密度(mdpi) 320x480 160 @1x
高密度(hdpi) 480x800 240 @1.5x
超高密度(xhdpi) 720x1280 320 @2x
超超高密度(xxhdpi) 1080x1920 480 @3x
超超高密度(xxxhdpi) 2160×3840 640 @4x

根據iOS設計pt的思路,Google將mdpi的熒幕設置為基準點, mdpi熒幕上一個物理像素點的寬即為1dp。對于dp的理解以及屏幕尺寸參數之間的換算完全可以參考上一節原理。

這里需要說明:iOS工程師在布局過程中經常會使用絕對布局,因為iphone的型號和屏幕數量都極為有限。但是Android工程師在適配的過程中,由于屏幕的種類實在太多,就不能使用絕對布局了,而是改用其他布局方式,例如相對布局等。

舉例來說,設計師給xhdpi屏幕設計稿一個按鈕10dp寬,居中;那么Android工程師僅僅只需要關注這個10dp寬的按鈕,距離屏幕邊界的寬度,通過這樣的方式去適配所有的屏幕。

移動端Web適配過程

上一章節我們詳述了客戶端屏幕參數的含義及設計的思路,在這一節,我們需要詳述移動端的適配過程。

很多文章對視口(viewport)這個概念的闡述都僅限于定義,幸而發現一篇好文章:

像素與瀏覽器視口的細節—ACGTOFE

文章本身直觀的解釋了各個視口的定義及其關系。本文基于該文章進行了總結,并添加演示代碼,力求更簡潔明了的表述視口(viewport)的概念及關系。

像素

和native適配一樣,iOS有pt單位,Android使用dp單位,對于前端開發人員來說,CSS pixel 的含義和pt以及dp是一樣的,具體定義可參考<length>

也就是說,在普通屏幕上,開發PC端網頁設定固定寬度為1000px,在retina屏幕的macbook pro上網頁的寬度也是1000px。

對于retina 化前端網頁,可參考http://mir.aculo.us/2012/06/26/flowchart-how-to-retinafy-your-website/

視口

在討論移動端適配的過程中,我們要明確視口的定義及其之間的關系:布局視口可視視口

以PC端瀏覽網頁為例。

在瀏覽過程中會產生兩個視口:可視視口(visual viewport)布局視口(layout viewport)

在100%顯示比例下,

可視視口(visual viewport)通俗地說,就是用戶瀏覽網頁時瀏覽器框出來的區域。

布局視口(layout viewport)通俗地說,就是用戶瀏覽的網頁寬高包含的區域。

黑線框出的區域就是可視視口(visual viewport),而網頁本身明顯更長于可視視口(visual viewport),所以網頁所在的寬高包含的區域就是布局視口(layout viewport)

瀏覽器可視視口.png

那這兩個視口之間有什么關系呢,我們嘗試做一個試驗。

首先確定縮放比例為100%,可以看見google搜索的按鈕高度為36px

縮放比例為100%下的input.png

當縮放比例擴大到200%時,可以看見同一個搜索的按鈕高度仍舊為36px

縮放比例為200%下的input.png

通過兩張圖直觀的對比總結三點:

  1. 縮放比例的改變給用戶直觀的放大縮小的效果;
  2. input元素樣式上高度并不會隨著縮放比例的變化而變化;
    3.** 縮放比例改變了CSS 像素與設備物理像素之間的比例關系**;

通過我們對可視視口(visual viewport)以及布局視口(layout viewport)的直觀理解,我們可以得出的一點就是,縮放比例不會改變布局視口的寬度,那么縮放比例到底是不是通過改變可視視口(visual viewport)來實現放大和縮小的效果的呢?答案是肯定的。

可視視口(visual viewport)的寬度可以通過如下代碼獲得

window.innerWidth

首先,最大化情況下,縮放比例為100%,可視視口寬度為1920px

max縮放比例100%下可視視口的寬度.png

其次,最大化情況下,縮放比例為200%,可視視口寬度為960px

max縮放比例200%下可視視口的寬度.png

然后,最大化情況下,縮放比例為50%,可視視口寬度為3840px

max縮放比例50%下可視視口的寬度.png

最后,非最大化情況下,縮放比例為100%,可視視口寬度為942px

非全屏縮放比例為100%可視視口的寬度.png

通過這組對比,我們可以得出可視視口兩個非常重要的特點
? **1. 可視視口收到縮放比例的影響 **

? 瀏覽器窗口相同的情況下,縮放比例越大,可視視口寬度越小;縮放比例越小,可視視口寬度越大。

? 2. 可視視口與瀏覽器窗口的大小有關

? 縮放比例相同的情況下,瀏覽器窗口越大,可視視口寬度越大;瀏覽器窗口越小,可視視口寬度越小。

移動端訪問網頁時的視口

移動端訪問頁面的情況會相對復雜一些,我們來進行逐步的分解。

如果我們不做任何meta設置,使用移動端訪問一個正常的頁面,將會出現頁面被縮小,以至于文字無法閱讀。這種狀態,就好像拿著一個手機屏幕大小的框,然后為了能夠將一個桌面端寬度的網頁全部放到框里,于是框到網頁距離被擴大,導致了頁面縮小的情況。另外,可以發現原始狀態iphone6訪問頁面,html文檔的寬度是980px,ipad pro 訪問頁面,html文檔的寬度是1024px

原始狀態下的移動端訪問.png

通過<meta name="viewport" content="width=400"> 將布局寬度設置成400px以后,我們看到頁面被放大了,文字也能看的清楚了。

設置meta viewport標簽后的移動端頁面.png

通過上述實驗說明了移動端訪問網頁的時候,布局視口(layout viewport)實際存在。且有以下幾個特點:

  1. 衡量單位: CSS px。
  2. 默認值: 寬度有默認值,由手機瀏覽器定義。一般是768px ~ 1024px之間,常見默認值為980px。
  3. 移動端設置:可以通過metaviewport 標簽中width設定;例如 <meta name="viewport" content="width=400">
  4. 縮放,滑動頁面,翻轉手機屏幕等均不影響布局視口。
  5. 使用媒體查詢時 max-width 和 min-width 的值指的也是布局視口的寬。

獲取布局視口寬度的js

document.documentElement.clientWidth

將上文可視視口(visual viewport)進行總結。有以下幾個特點:

  1. 衡量單位: CSS px。

  2. 默認值 : 無。

  3. 受到屏幕寬度以及縮放大小的影響。

    用戶手動縮放和在 meta標簽中設置 initial-scale 的值都會改變可視視口的尺寸; 縮放比例也有默認的值,沒有設置 initial-scale 時,瀏覽器會取適當的縮放比例使布局視口正好鋪滿屏幕即有 布局視口尺寸 = 可視視口尺寸

    縮放比例是根據下面提到的理想視口而言的 ,$縮放比例 = 理想視口尺寸 / 可視視口尺寸$

獲取可視視口寬度的js

window.innerWidth

通過對native適配過程的論述,我們已經知道無論是iOS系統手機還是Android系統手機,都會存在一個邏輯分辨率,而邏輯分辨率組成的視口就是理想視口(ideal viewport),有以下幾個特點:

  1. device-width指的就是理想視口的寬度,例如<meta name="viewport" content="width=device-width">

  2. 理想視口尺寸不能設定也不能改變,它只與設備物理像素、dpr、以及瀏覽器相關。

    $設備像素比(dpr) = 物理像素數 / 理想視口尺寸$

獲取理想視口寬度的js

screen.width

獲取設備dpr的js

window.devicePixelRatio

那么上述三種視口之間的轉換就有一定的規律

  1. 將 meta 標簽中的 width 設為 device-width 同時禁用手動縮放

    <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=no"/>

    可以使$ 布局視口尺寸 = 可視視口尺寸 = 理想視口尺寸$,此時 設備像素比 = 物理像素數 / 理想視口尺寸 = 物理像素數 / 布局視口尺寸,對iphone5,一個CSS像素對應4個物理像素。

  2. 為 initial-scale 設置任意合法的值同時禁用手動縮放就可以使布局視口尺寸 = 可視視口尺寸

  3. 將 initial-scale 設置為 1 也可以使 布局視口尺寸 = 可視視口尺寸 = 理想視口尺寸

移動端Web適配方案

無論網易的移動Web適配方案,還是手淘的移動Web適配方案均采用rem 作為布局的單位。

rem(font size of the root element),指相對于根元素的字體大小的單位。

rem單位出現前的移動Web適配方案

rem單位出現以前,假設需求是適配iPhone4(320px),iPhone6(375px),iPhone6 Plus(414px),且用戶瀏覽網頁的時候,文字大小、圖片、按鈕大小都是適宜的:

(1) iPhone4的時候,希望網頁的內容文字大小12px=12*(320/320)px,按鈕的大小是240px。

(2)iphone6的時候,希望網頁的內容文字大小14px=12*(375/320)px,按鈕的大小是280px,等比縮放。

(3)iphone6 Plus的時候,希望網頁的內容文字大小15.5px=12*(414/320)px,按鈕的大小是310px,等比縮 放。

那么將采用以下的方案適配:

iphone 4 下

<meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0 />

iPhone6 調整縮放比例, initial-scale=375/320 =1.18

<meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.18 />

iphone 6Plus 再調整縮放比例,initial-scale=414/320 =1.30

<meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.30 />

隨著initial-scale的變大,網頁被拉伸的越來越厲害,那么,大屏的移動端顯示圖片、文字等會出現不同程度的模糊。

網易移動Web適配方案

  1. 設置理想視口=可視視口=布局視口

    <meta name="viewport" content="initial-scale=1,maximum-scale=1, minimum-scale=1">
    
  2. 如何計算得出html的font-size

    iphone6 的設計稿寬度為750px,100是期望換算比。即設計稿100px對應css 1rem;

    $設計稿可視視口寬度=750px/100$,所以$1rem =可視視口寬度/(100/750) $;

    可視視口寬度可以通過js 獲取:

    window.innerWidth
    

    html的font-size

    document.documentElement.style.fontSize = window.innerWidth / 7.5 + 'px';
    

手淘移動Web適配方案

  1. 手淘flexible方案只對iOS設備進行dpr的判斷,對于Android系列,都始終認為dpr為1。

  2. 取 dpr 的倒數作為縮放比例,對 iOS 設備 dpr = window.devicePixelRatio ,其他設備認為 dpr 為 1
    對 iOS 設備,令上面提到的公式 縮放比例 = 理想視口尺寸 / 可視視口尺寸,設備像素比 = 物理像素數 / 理想視口尺寸 中 設備縮放比 = 1 / 縮放比例 可以推出 可視視口尺寸 = 物理像素數,同時由于沒有設置 meta 標簽的 width 值,有 布局視口尺寸 = 可視視口尺寸 = 物理像素數,這意味著布局視口中的像素單位是和物理像素一一對應的,css單位中1px嚴格等于一個物理像素。

    對非 iOS 設備,將 dpr 設為 1,縮放比例也為 1,和網易新聞的方案相同。

  3. 對于描述性文本,則根據data-dpr進行區分,使用px作為單位。

另外手淘方案已經進行了更新,請戳這里

?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 227,818評論 6 531
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 98,185評論 3 414
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 175,656評論 0 373
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 62,647評論 1 309
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,446評論 6 405
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 54,951評論 1 321
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,041評論 3 440
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,189評論 0 287
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 48,718評論 1 333
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,602評論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 42,800評論 1 369
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,316評論 5 358
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,045評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,419評論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,671評論 1 281
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,420評論 3 390
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 47,755評論 2 371

推薦閱讀更多精彩內容