移動端適配

Alan丶發表於2019-03-19

前言:這周工作碰到了移動端1px的問題。以前一直寫樣式也沒有特別注意著一點。還有就是rem的原理。這些其實就是比較常見的移動端適配問題。現階段比較主流的適配方案有二種。一種是flexible + rem,另一種是vw

下面我們來看一下具體情況

1、基本概念

在瞭解具體方案原理前,我們先來看一下一些基本概念:

1.1、物理畫素(physical pixel)

物理畫素又被稱為裝置畫素,他是顯示裝置中一個最微小的物理部件。每個畫素可以根據作業系統設定自己的顏色和亮度。

1.2、裝置獨立畫素(density-independent pixel)

裝置獨立畫素也稱為密度無關畫素,可以認為是計算機座標系統中的一個點,這個點代表一個可以由程式使用的虛擬畫素(比如說CSS畫素),然後由相關係統轉換為物理畫素。(老早在沒有 retina 屏之前,裝置獨立畫素與物理畫素是相等的)

1.3、CSS畫素

CSS畫素是一個抽像的單位,主要使用在瀏覽器上,用來精確度量Web頁面上的內容。一般情況之下,CSS畫素稱為與裝置無關的畫素(device-independent pixel),簡稱DIPs。

1.4、裝置畫素比(device pixel ratio)

裝置畫素比簡稱為dpr,其定義了物理畫素和裝置獨立畫素的對應關係。它的值可以按下面的公式計算得到:

裝置畫素比 = 物理畫素 / 裝置獨立畫素
複製程式碼

JavaScript中,可以通過window.devicePixelRatio獲取到當前裝置的dpr。而在CSS中,可以通過-webkit-device-pixel-ratio-webkit-min-device-pixel-ratio-webkit-max-device-pixel-ratio進行媒體查詢,對不同dpr的裝置,做一些樣式適配(這裡只針對webkit核心的瀏覽器和webview) 因此在iphone 6、7、8 的 dpr 為 2的裝置中,一個裝置獨立畫素便為 4 個物理畫素,因此在 css 上設定的 1px 在其螢幕上佔據的是 2個物理畫素,0.5px 對應的才是其所能展示的最小單位。

1.5、rem

簡單的理解,rem就是相對於根元素<html>font-size來做計算。而我們的方案中使用rem單位,是能輕易的根據<html>ont-size計算出元素的盒模型大小。而這個特色對我們來說是特別的有益處。

2、flexible實現方案

瞭解了前面一些相關概念之後,接下來我們來看實際解決方案。淘寶有一個名叫lib-flexible的庫,而這個庫就是用來解決H5頁面終端適配的。 我們把螢幕分成10等分,那麼

  • 物理畫素為 750 = 375 * 2,那麼 10rem = 750px,1rem = 75px;
  • 物理畫素為 1125 = 375 * 3,那麼 10rem = 1125px,1rem = 112.5px ;
  • 物理畫素為 1242 = 414 * 3, 那麼 10rem = 1242px,1rem = 124.2px;
function refreshRem(){
        var width = docEl.getBoundingClientRect().width;
        if (width / dpr > 540) {
            width = 540 * dpr;
        }
        var rem = width / 10;
        docEl.style.fontSize = rem + 'px';
        flexible.rem = win.rem = rem;
    }
複製程式碼

2.1、1px的物理畫素的解決方案

由此我們得到一個1px畫素的解決方案。viewport 的 initial-scale 具有縮放頁面的效果。對於 dpr=2 的螢幕,1px壓縮一半便可與1px的裝置畫素比匹配,這就可以通過將縮放比 initial-scale 設定為 0.5=1/2 而實現。以此類推 dpr=3的螢幕可以將 initial-scale設定為 0.33=1/3 來實現。

<meta name="viewport" content="width=device-width, initial-scale=0.5, maximum-scale=0.5">
複製程式碼
if (!metaEl) {
        metaEl = doc.createElement('meta');
        metaEl.setAttribute('name', 'viewport');
        metaEl.setAttribute('content', 'initial-scale=' + scale + ', maximum-scale=' + scale + ', minimum-scale=' + scale + ', user-scalable=no');
        if (docEl.firstElementChild) {
            docEl.firstElementChild.appendChild(metaEl);
        } else {
            var wrap = doc.createElement('div');
            wrap.appendChild(metaEl);
            doc.write(wrap.innerHTML);
        }
    }
複製程式碼

3、視口單位適配方案

將視口寬度 window.innerWidth 和視口高度 window.innerHeight 等分為 100 份,且將這裡的視口理解成 idealviewport 更為貼切,並不會隨著 viewport 的不同設定而改變。

  • 1、vw : 1vw 為視口寬度的 1%
  • 2、vh : 1vh 為視口高度的 1%
  • 3、vmin : vw 和 vh 中的較小值
  • 4、vmax : 選取 vw 和 vh 中的較大值

如果設計稿為 750px,那麼 1vw = 7.5px,100vw = 750px。其實設計稿按照設麼都沒多大關係,最終轉化過來的都是相對單位,上面講的 rem 也是對它的模擬。

跟之前一樣的痛點,我們仍然需要花費大量不必要的計算時間去把標註圖中的px轉換為vw,有沒有類似於postcss-px2rem的工具呢?很榮幸能再次站在巨人的肩膀上,已經有大神寫了了類似的PostCss外掛 postcss-px-to-viewport

自己學習時的一點小總結,如有問題,歡迎指正。

參看資料 www.w3cplus.com/mobile/lib-…

相關文章