天天看點

layui移動端适配_移動端适配

layui移動端适配_移動端适配

前言

原文 && 個人首頁

知乎&&知乎專欄

背景

随着移動端的普及,以及手機尺寸越來越多,這就衍生了衆多的适配方案,以下挑一些常見的适配方案進行探讨。

本文預設讀者已經對視口、實體像素、邏輯像素、css像素等移動端基本概念已經了解了。

px + viewport适配

這種适配方案原理比較簡單:實際上就是通過動态設定

meta

标簽的viewport讓css中的1px等于裝置的1px。

js僞代碼:

const scale = 1 / devicePixelRatio

head.appendChild(`<meta name='viewport' content='width=device-width, initial-scale=${scale}, maximum-scale=${scale}, minimum-scale=${scale}, user-scalable='no'>`)

body.setAttribute('data-dpr', devicePixelRatio)
           

css僞代碼

[data-dpr='3'] {
    property: value * 3
    ...
}

[data-dpr='2'] {
    property: value * 2
    ...
}
           

大家可以用不同手機進入這裡,或者用浏覽器模拟。

優點

:簡單易于了解

缺點

:不能涵蓋所有dpr的機型,即使能,也會造成代碼臃腫。

rem布局

首先我們需要知道

  1. rem

    的大小是基于頁面根元素的

    font-size

  2. rem

    的本質是等比縮放。

例如:根元素的

font-size: 16px

則,

1rem

就等于

16px

;根元素的

font-size:32px

則,

1rem

就等于

32px

可以到這裡來意會一下

rem

的本質是縮放

這麼一來,我們就可以利用這個特性動态設定根元素的

font-size

來達到我們想要的效果。

基于設計圖的rem布局

通常我們拿到的設計圖寬度的是750也就是基于iphone6/7/8的設計圖,我們如果要想讓1px像素等于設計圖的1px該怎麼做呢?

其實很簡單,直接讓根元素的

font-size: 0.5px

即可(因為是2倍圖,1px等于2實際像素,是以為

0.5px

)。

那麼問題來了:設計圖一定會是750的,可是市面上機型那麼多,螢幕不一定是750啊,怎麼辦?

layui移動端适配_移動端适配

前面我說過,

rem的本質是等比縮放

,讓大于750或者小于750螢幕的手機等比縮放不就完事了?

js僞代碼:

html.fontSize = clientWidth / 750
           

你以為這就完事了?其實事情并沒有那麼簡單。

layui移動端适配_移動端适配

别忘了,平時我們開發都是在chrome下開發的。chrome并不支援

font-size

小于12的字型,那怎麼辦呢?

還能怎麼辦,為了友善計算,讓

font-size

大于12呗,在以上基礎上将結果放大100倍,然後寫樣式的時候再除以100:

layui移動端适配_移動端适配

js僞代碼:

html.fontSize = clientWidth / 750 * 100
           

樣式:

.element {
    width: 0.1rem; /* 實際到6/7/8上就是10px */
}
           

基于螢幕百分比的rem布局

假設一個頁面有100份,每一份的寬度用

x

表示,則

x=螢幕寬度(即clientWidth)/100

,如果

font-size: x

,那我們不就實作了

1rem === 1%

螢幕寬度了嗎?

可是現實是殘酷的,平時我們開發的時候寫樣式可不是按照螢幕寬度的百分之幾來寫的,而是根據設計給的标注來寫的,而且設計通常給的設計圖寬度是

750

的,那麼如何轉換呢?

其實可以換種思維:如果得到這個元素的寬度占頁面寬度的百分之幾不就完事了嗎?

是以,

實際的rem = 元素标注長度 / 設計圖寬度(這裡是750) * 100

當然,這個轉換過程可以讓postcss去幫我們轉換。

rem布局的優缺點

優點:

易于了解,且相容性好,能夠很好地解決适配問題。

缺點:
  1. 需要用js額外設定字型大小,強制設定根元素的字型大小,剝奪了使用者的自由
  2. 在webview中,部分機型下使用者設定系統預設字型大小會造成布局錯亂

小程式的黑魔法rpx布局

做過小程式的都知道,小程式有個

wxss

,這玩意有個rpx的機關,官方文檔是這麼介紹他的:

可以根據螢幕寬度進行自适應。規定螢幕寬為750rpx。如在 iPhone6 上,螢幕寬度為375px,共有750個實體像素,則750rpx = 375px = 750實體像素,1rpx = 0.5px = 1實體像素

再看到下面那個轉換表時我瞬間就不淡定了:

layui移動端适配_移動端适配

既是根據螢幕寬度自适應的又和上一章講到的:基于設計圖的rem布局的換算結果一樣的,那它内部的實作原理其實和基于設計圖的rem布局的原理差不多。

隻不過小程式内部處理了一下,讓rpx直接能夠根據螢幕寬度自适應,而不是像rem那樣依賴于根元素的

font-size

vw布局

上一章基于螢幕百分比的rem布局小節中提到的

x

代表1份螢幕的寬度,在css中剛好有個機關代表這個

x

,即vw,至于vw是啥這裡就不多說了,都9012年了,竟然還不知道vw是什麼,傳送門。

那麼問題來了,平時我們拿到的設計圖都是基于

px

标記的,怎麼将

px

轉為

vw

呢?

emmm,這裡有個專門的插件專門做這件事postcss-px-to-viewport

其代碼中有這麼一句:

toFixed((pixels / viewportSize * 100), opts.unitPrecision)
           

是不是和我們上面所說的

實際的rem = 元素标注長度 / 設計圖寬度(這裡是750) * 100

很像?

這個插件會解析我們的css檔案,将

px

轉換為

vw

,至于為什麼要這麼轉化,上面已經說過了,這裡就不再贅述。

vw

完美地避開了

rem

的缺點,還繼承了

rem

的優點,然而

vw

并不是完美的,由于

px

vw

是經過js計算的,多少都會優些精度損失,不過這是個小問題,不會丢失多少精度,除非你對精度要求特别高。

參考

Rem布局的原了解析

rem, vw, 還是…? 各憑本事的移動端适配方案