移動(dòng)端頁(yè)面適配 rem 與 vw
再看看15年手淘方案:Flexible + rem
Flexible 從流行到今天也有幾年了跌榔,它解救了很多同學(xué)針對(duì)于H5頁(yè)面布局的適配問(wèn)題,直到現(xiàn)在還是有很多開發(fā)者采用這套方案捶障。這套方案本質(zhì)上來(lái)說(shuō)是為了能讓頁(yè)面更好的適配各種不同的終端僧须,通過(guò)Hack手段來(lái)根據(jù)設(shè)備的dpr
值相應(yīng)改變<meta>
標(biāo)簽中viewport
的值。
Flexible 事實(shí)上做了這幾樣事情:
1 動(dòng)態(tài)改寫<meta>
標(biāo)簽
2 給<html>
元素添加 data-dpr 屬性项炼,并且動(dòng)態(tài)改寫 data-dpr 的值
3 給<html>
元素添加 font-size 屬性皆辽,并且動(dòng)態(tài)改寫 font-size 的值
4 把視覺(jué)稿中的 px 轉(zhuǎn)換成 rem
5 文字字號(hào)使用 px柑蛇,不使用 rem
其思想被總結(jié)出來(lái)有三點(diǎn):
- 根據(jù) dpr 的值來(lái)修改 viewport 實(shí)現(xiàn) 1px 的線
- 根據(jù) dpr 的值來(lái)修改 html 的font-size,從而使用 rem 實(shí)現(xiàn)等比縮放
- 使用 Hack 手段用 rem 模擬 vw 特性
Flexible 庫(kù)的 GitHub 地址驱闷,點(diǎn)擊進(jìn)入可以看見一段文字
由于 viewport 單位得到眾多瀏覽器的兼容耻台,lib-flexible 這個(gè)過(guò)渡方案已經(jīng)可以放棄使用,不管是現(xiàn)在的版本還是以前的版本空另,都存有一定的問(wèn)題盆耽。建議大家開始使用viewport來(lái)替代此方案。vw 的兼容方案可以參閱《如何在Vue項(xiàng)目中使用vw實(shí)現(xiàn)移動(dòng)端適配》一文扼菠。
作者表示vw布局方案已得到了瀏覽器的支持摄杂,不需要hack了,在 Can I Use 上也可以看到各瀏覽器的支持情況循榆。
了解 Flexible 方案可以看大漠
大神的這篇文章析恢。
早期網(wǎng)易 rem 方案
網(wǎng)易的方案是頁(yè)面上 html 的 font-size 不是預(yù)先通過(guò)媒介查詢?cè)?css 里定義好的,而是通過(guò) js 計(jì)算出來(lái)的秧饮。
視口不會(huì)改變:
<meta name="viewport" content="initial-scale=1,maximum-scale=1, minimum-scale=1">
當(dāng) deviceWidth 大于設(shè)計(jì)稿的橫向分辨率時(shí)映挂,html 的 font-size 始終等于 橫向分辨率/body 元素寬,因?yàn)楫?dāng)deviceWidth大于640時(shí)盗尸,則物理分辨率大于1280(這就看設(shè)備的devicePixelRatio這個(gè)值了)柑船,應(yīng)該去訪問(wèn)pc網(wǎng)站了。
最近看了一下網(wǎng)易的方案已經(jīng)使用 vw + rem 的方案了泼各。
純粹使用 vw 方案
無(wú)論是文本還是布局高寬鞍时、間距等都使用 vw 作為 CSS 單位。
在僅使用 vw 單位作為唯一應(yīng)用的一種 CSS 單位的這種做法時(shí):
a. 使用 SASS/LESS 的話可以函數(shù)解決 px 單位轉(zhuǎn)換為 vw 的問(wèn)題
$vw_base: 375;
@function vw($px) {
@return ($px / 375) * 100vw;
}
width: vw(40); // 使用函數(shù)設(shè)置寬度
b. 使用 styled-components 等 css-in-js 庫(kù)時(shí)扣蜻,也可定義一個(gè)函數(shù)
export function px2vw(pixels, pixelTotal = 750) {
return `${pixels / pixelTotal * 100}vw`;
};
// 使用
const Container = styled.div`
display: flex;
margin: ${px2vw(30)} ${px2vw(18)} ${px2vw(30)} ${px2vw(28)};
padding-bottom: ${px2vw(18)};
align-items: center;
`;
這樣的頁(yè)面雖然看起來(lái)適配得很好逆巍,但是你會(huì)發(fā)現(xiàn)由于它是利用視口單位實(shí)現(xiàn)的布局,依賴于視口大小而自動(dòng)縮放莽使,無(wú)論視口過(guò)大還是過(guò)小锐极,它也隨著視口過(guò)大或者過(guò)小,失去了最大最小寬度的限制吮旅。當(dāng)然如果只考慮常規(guī)移動(dòng)端需求溪烤,這個(gè)方案基本可以滿足了味咳。
vw + rem庇勃,優(yōu)化布局
這個(gè)方案如下
1 給根元素大小設(shè)置隨著視口變化而變化的 vw 單位,這樣就可以實(shí)現(xiàn)動(dòng)態(tài)改變其大小槽驶。
2 限制根元素字體大小的最大最小值责嚷,配合 body 加上最大寬度和最小寬度
3 組件及字體使用 rem 單位
這樣我們就能夠?qū)崿F(xiàn)對(duì)布局寬度的最大最小限制,并且頁(yè)面上組件及文字不會(huì)出現(xiàn)太大或太小的情況了掂铐。
代碼如下:
// 根元素大小使用 vw 單位
html {
font-size: (vw_fontsize / (vw_design / 2)) * 100vw; // vw_fontsize 可以設(shè)為75罕拂,vw_design為設(shè)計(jì)稿寬度
@media screen and (max-width: 320px) {
font-size: 64px;
}
@media screen and (min-width: 540px) {
font-size: 108px;
}
}
// body 也增加最大最小寬度限制揍异,避免組件及文字跟隨 body 變得過(guò)大過(guò)小
body {
max-width: 540px;
min-width: 320px;
}
// 定義單位轉(zhuǎn)換函數(shù)
export function px2rem(px, psd = 750) {
return `${px / psd * 10}rem`;
}
// 使用
width: px2rem(100);
參考文章: