移動端適配總結

在 web 的世界裏,無線和 PC 的響應式適配實際上是兩個世界……javascript

1. 視口 viewport

1.1 viewport 基礎

viewport 解釋爲中文就是‘視口’的意思,也就是瀏覽器中用於顯示網頁的區域。在 PC 端,其大小也就是瀏覽器可視區域的大小,因此咱們也不會太關注此概念;而在移動端,絕大多數狀況下 viewport 都大於瀏覽器可視區,保證 PC 頁面在移動瀏覽器上面的可視性。爲提高可視性體驗,針對移動端有了對 viewport 的深刻研究。css

1.2 viewport 詳解

在移動端有三種類型的 viewport: layoutviewport、visualviewport、idealviewport。具體解釋以下:html

  • layoutviewport: 大於實際屏幕, 元素的寬度繼承於 layoutviewport,用於保證網站的外觀特性與桌面瀏覽器同樣。layoutviewport 到底多寬,每一個瀏覽器不一樣。iPhone 的 safari 爲 980px,經過 document.documentElement.clientWidth 獲取。
  • visualviewport: 當前顯示在屏幕上的頁面,即瀏覽器可視區域的寬度。
  • idealviewport: 爲瀏覽器定義的可完美適配移動端的理想 viewport,固定不變,能夠認爲是設備視口寬度。好比 iphone 7 爲 375px, iphone 7p 爲 414px。

1.3 viewport 設置

咱們經過對幾種 viewport 設置能夠對網頁的展現進行有效的控制,在移動端咱們常常會在 head 標籤中看到這段代碼:html5

<meta name='viewport' content='width=device-width,initial-scale=1,user-scale=no' />
複製代碼

經過對 meta 標籤三個 viewport 的設置,最終使頁面完美展現。下面詳細的闡釋其具體含義:java

  • width 設置的是 layoutviewport 的寬度
  • initial-scale 設置頁面的初始縮放值,而且這個初始縮放值是相對於 idealviewport 縮放的,最終獲得的結果不只會決定 visualviewport,還會影響到 layoutviewport
  • user-scalable 是否容許用戶進行縮放的設置

對上面的說明經過公式推導進行進一步的解釋:web

// 設定兩個變量: 
viewport_1 = width;  
viewport_2 = idealviewport / initial-scale;

// 則: 
layoutviewport = max{viewport_1, viewport_2};  
visualviewport = viewport_2;
複製代碼

只要 layoutviewport === visualviewport,頁面下面不會出現滾動條,默認只是把頁面放大或縮小。瀏覽器

1.4 viewport 舉例

如下是經過改變 meta viewport 的幾個參數的值來算取不一樣的 viewport:app

width initial-scale layoutviewport visualviewport idealviewport 是否滾動
- - 980px 980px 375px
device-width 1 375px 375px 375px
device-width 2 375px 188px 375px
device-width 0.5 750px 750px 375px
480px 1 480px 375px 375px
480px 2 480px 188px 375px
480px 0.5 750px 750px 375px

以上是針對 iphone 6/7/8 的測試數據,且不管怎麼設置 viewport 都具備臨界值,即:75 <= layoutviewport <= 10000,75 <= visualviewport <= 1500。iphone

1.5 爲何要設置 viewport

viewport 的設置不會對 PC 頁面產生影響,但對於移動頁面卻很重要。下面咱們舉例來講明:ide

  1. 媒體查詢 @media 響應式佈局中,會根據媒體查詢功能來適配多端佈局,必須對 viewport 進行設置,不然根據查詢到的尺寸沒法正確匹配視覺寬度而致使佈局混亂。如不設置 viewport 參數,多說移動端媒體查詢的結果將是 980px 這個節點佈局的參數,而非咱們一般設置的 768px 範圍內的這個佈局參數
  2. 因爲目前多數手機的 dpr 都再也不是 1,爲了產出高保真頁面,咱們通常會給出 750px 的設計稿,那麼就須要經過設置 viewport 的參數來進行總體換算,而不是在每次設置尺寸時進行長度的換算。

2. 設備像素比 dpr 與 1px 物理像素

2.1 物理像素(physical pixel)

手機屏幕上顯示的最小單元,該最小單元具備顏色及亮度的屬性可供設置,iphone六、七、8 爲:750 * 1334,iphone6+、7+、8+ 爲 1242 * 2208

2.2 設備獨立像素(density-indenpendent pixel)

此爲邏輯像素,計算機設備中的一個點,css 中設置的像素指的就是該像素。老早在沒有 retina 屏以前,設備獨立像素與物理像素是相等的。

2.3 設備像素比(device pixel ratio)

設備像素比(dpr) = 物理像素/設備獨立像素。如 iphone 六、七、8 的 dpr 爲 2,那麼一個設備獨立像素便爲 4 個物理像素,所以在 css 上設置的 1px 在其屏幕上佔據的是 2個物理像素,0.5px 對應的纔是其所能展現的最小單位。這就是 1px 在 retina 屏上變粗的緣由,目前有不少辦法來解決這一問題。

屏幕快照 2018-10-22 下午4.25.50.png | left | 173x165

2.4 1px的物理像素的解決方案

從第一部分的討論可知 viewport 的 initial-scale 具備縮放頁面的效果。對於 dpr=2 的屏幕,1px壓縮一半即可與1px的設備像素比匹配,這就能夠經過將縮放比 initial-scale 設置爲 0.5=1/2 而實現。以此類推 dpr=3的屏幕能夠將 initial-scale設置爲 0.33=1/3 來實現。

3. 設備像素比 dpr 與 rem 的適配方案

結合 二、3 部分能夠實現 1px 的物理像素這一最小屏幕單位,那在此基礎上如可以讓設計一般提供的 750px 設計稿來完美的適配到多種機型上,使用 rem 是一種解決方式。

3.1 rem 如何設置

rem 是相對於根元素 html 的 font-size 來作計算。一般在頁面初始化時加載時經過對document.documentElement.style.fontSize 設置來實現。

3.2 rem 適配規則

經過對 initial-scale = 1/dpr 的設置,已將對屏幕的描述從物理像素轉化到了物理像素上了,這將是後續推導的基礎,且設計稿爲 750px。

  1. 物理像素爲 750 = 375 * 2,若屏幕等分爲 10 份,那麼 1rem = 75px,10rem = 750px;
  2. 物理像素爲 1125 = 375 * 3,若屏幕等分爲 10 份,那麼 1rem = 112.5px, 10rem = 1125px;
  3. 物理像素爲 1242 = 414 * 3, 若屏幕等分爲 10 份,那麼 1rem = 124.2px, 10rem = 1242px;

所以可推導出 rem 的設定方式:

document.documentElement.style.fontSize = document.documentElement.clientWidth / 10 + 'px';
複製代碼

下面咱們將 750px 下,1rem 表明的像素值用 baseFont 表示,則在 baseFont = 75 的狀況下,是分紅 10 等份的。所以能夠將上面的公式通用話一些:

document.documentElement.style.fontSize = document.documentElement.clientWidth / ( 750 / 75 ) + 'px';
複製代碼

總體設置可參考以下代碼:

(function (baseFontSize) {
    const _baseFontSize = baseFontSize || 75;
    const ua = navigator.userAgent;
    const matches = ua.match(/Android[\S\s]+AppleWebkit\/(\d{3})/i);
    const isIos = navigator.appVersion.match(/(iphone|ipad|ipod)/gi);
    const dpr = window.devicePixelRatio || 1;
    if (!isIos && !(matches && matches[1] > 534)) {
        // 若是非iOS, 非Android4.3以上, dpr設爲1;
        dpr = 1;
    }
    const scale = 1 / dpr;
    const metaEl = document.querySelector('meta[name="viewport"]');
    if (!metaEl) {
        metaEl = document.createElement('meta');
        metaEl.setAttribute('name', 'viewport');
        window.document.head.appendChild(metaEl);
    }
    metaEl.setAttribute('content', 'width=device-width,user-scalable=no,initial-scale=' + scale + ',maximum-scale=' + scale + ',minimum-scale=' + scale);

    document.documentElement.style.fontSize = document.documentElement.clientWidth / (750 / _baseFontSize) + 'px';
})();
複製代碼

同時爲了書寫方即可以直接經過 px 佈局,而後在打包時利用 pxtorem 庫轉化爲基於 rem 的佈局。

4. 視口單位適配方案

將視口寬度 window.innerWidth 和視口高度 window.innerHeight 等分爲 100 份,且將這裏的視口理解成 idealviewport 更爲貼切,並不會隨着 viewport 的不一樣設置而改變。

  • vw : 1vw 爲視口寬度的 1%
  • vh : 1vh 爲視口高度的 1%
  • vmin : vw 和 vh 中的較小值
  • vmax : 選取 vw 和 vh 中的較大值

若是設計稿爲 750px,那麼 1vw = 7.5px,100vw = 750px。其實設計稿按照設麼都沒多大關係,最終轉化過來的都是相對單位,上面講的 rem 也是對它的模擬。這裏的比例關係也推薦不要本身換算,使用 pxtoviewport 的庫就能夠幫咱們轉換。固然每種方案都會有其弊端,這裏就不展開討論。

總結

在移動端開發中,理解視口對適配相當重要。所以本文先從視口展開討論,從而引出 1px、rem 及 vw/vh 這些和適配相關的主要話題。下面提供的參考文章會在某些點上更加細化,以供參考。

參考文章

www.quirksmode.org/mobile/view…

www.w3cplus.com/mobile/lib-…

www.w3cplus.com/css/vw-for-…

image | left
相關文章
相關標籤/搜索