關(guān)于自適配的rem布局

說到前端頁面的布局方案,可以從遠(yuǎn)古時代的Table布局說起,然后來到 DIV+CSS布局,之后有了Float布局,F(xiàn)lex布局,Column布局,Grid布局等等。

而另一方面,還有一些布局概念:

1. 靜態(tài)布局

直接使用px作為單位

2. 流式布局

寬度使用%百分比,高度使用px作為單位

3. 自適應(yīng)布局

創(chuàng)建多個靜態(tài)布局,每個靜態(tài)布局對應(yīng)一個屏幕分辨率范圍。使用 @media媒體查詢來切換多個布局

4. 響應(yīng)式布局

通常是糅合了流式布局+彈性布局,再搭配媒體查詢技術(shù)使用

5. 彈性布局

通常指的是rem或em布局。rem是相對于html元素的font-size大小而言的,而em是相對于其父元素(非font-size的是相對于自身的font-size)


是的也就是我們之前做的那個是半吊子的響應(yīng)式布局。

rem布局應(yīng)該是比較適配移動端的,對移動端我還所知甚少。git上看了不少demo,自己也想動手嘗試一下。

今天配合著小demo來走一遍rem布局。

我們要明確的是:rem布局的核心是設(shè)置好根html元素的font-size。

文章中提到了4種方案,其原理都是采用等比縮放的方式 —— 獲得目標(biāo)屏幕寬度和設(shè)計(jì)稿寬度的比,作為 rem 的基值(縮放系數(shù)),設(shè)置為html標(biāo)簽的字體大小。不同的只是在于性能取舍和書寫習(xí)慣。(那么這可能是一種主流寫法?)

可以看到方案(1)和方案(2)都結(jié)合了media query的寫法,令人頭禿的是media query有時候查詢的跨度較大,比如說

@meida (min-width:370px) 到@media (min-width:480px),這中間370~480就響應(yīng)同一個px,那么其實(shí)還是有差的,雖然說media query是新手入門一個比較簡單的方式,但不能永遠(yuǎn)用media query(我自認(rèn)為)。

當(dāng)如果實(shí)際運(yùn)用到頁面中的單位為px的時候,這里我們有一個簡單的數(shù)學(xué)計(jì)算:

目標(biāo)屏幕寬度/設(shè)計(jì)稿寬度=目標(biāo)px/rem2px

所以目標(biāo)px:

window.innerWidth/designWidth*rem2px+'px'

在這里,常用的designWidth==640px,而rem2px==100(意思是1rem==100px)。

當(dāng)如果實(shí)際運(yùn)用到頁面中的單位為%(百分比)時,同樣運(yùn)用這個數(shù)學(xué)計(jì)算,但需要注意的是,因?yàn)闉g覽器默認(rèn)的字體大小是16px,即defaultFontSize == 16px,所以我們根html的font-size的計(jì)算方式:

1rem=1*htmlFontSize*defaultFontSize

因?yàn)槠渲衕tmlFontSiz為百分比,乘上一個16px之后才是px。

所以就有,當(dāng)將根html的font-size設(shè)置為百分比時,font-size=:

window.innerWidth / designWidth * rem2px / 16 * 100? + '%'

但是,首先我們運(yùn)用px的時候,是不考慮瀏覽器默認(rèn)字體大小的,在運(yùn)用百分比的時候,我們直接將瀏覽器默認(rèn)字體大小定為16px的,也就是會遇到一個問題:

在有些 Android 手機(jī)上,瀏覽器或 webview 的默認(rèn)字體是隨著系統(tǒng)設(shè)置的字體改變的。這樣就會導(dǎo)致默認(rèn)字體大于或小于 16px。

在運(yùn)用px的時候,雖然我們的公式?jīng)]有提到16px這個defaultFontSize,但是實(shí)際上是運(yùn)用了的,無從改起(或者說我暫時沒想到辦法)。所以我們的想法是:運(yùn)用百分比,然后去獲取當(dāng)下的defaultFontSize。

他人文章中使用的方法

以上辦法可以嵌入在js中去使用。

現(xiàn)在我們先嘗試使用手淘的flexible.min.js插件來構(gòu)造自適應(yīng)rem布局。

flexible.js是阿里團(tuán)隊(duì)開源的一個庫。使用它輕松搞定各種不同的移動端設(shè)備兼容自適應(yīng)問題。而flexible.min.js是其精簡版。

Flexible會將視覺稿分成100份(主要為了以后能更好的兼容vh和vw),而每一份被稱為一個單位a。同時1rem單位被認(rèn)定為10a。針對我們這份視覺稿可以計(jì)算出:(設(shè)計(jì)稿為750px為例)

1a = 7.5px

1rem = 75px

那么我們這個示例的稿子就分成了10a,也就是整個寬度為10rem,<html>對應(yīng)的font-size為75px:·

這樣一來,對于視覺稿上的元素尺寸換算,只需要原始的px值除以rem基準(zhǔn)值即可。例如此例視覺稿中的圖片,其尺寸是176px * 176px,轉(zhuǎn)換成為2.346667rem * 2.346667rem。

(原始px值:176px,rem基準(zhǔn)值75,176/75==2.34666667)

也就是,flexible.js通過js來調(diào)整html的字體大小。而我們之后使用css在頁面中的制作稿則統(tǒng)一使用rem這個單位來制作。

使用的方法很簡單,將下面這段代碼復(fù)制到你的頁面的頭部的script標(biāo)簽的最前面。

//designWidth:設(shè)計(jì)稿的實(shí)際寬度值,需要根據(jù)實(shí)際設(shè)置

//maxWidth:制作稿的最大寬度值,需要根據(jù)實(shí)際設(shè)置

//這段js的最后面有兩個參數(shù)記得要設(shè)置,一個為設(shè)計(jì)稿實(shí)際寬度,一個為制作稿最大寬度,例如設(shè)計(jì)稿為750,最大寬度為750,則為(750,750)

;(function(designWidth, maxWidth) {

? ? var doc = document,

? ? win = window,

? ? docEl = doc.documentElement,

? ? remStyle = document.createElement("style"),

? ? tid;

? ? function refreshRem() {

? ? ? ? var width = docEl.getBoundingClientRect().width;

? ? ? ? maxWidth = maxWidth || 540;

? ? ? ? width>maxWidth && (width=maxWidth);

? ? ? ? var rem = width * 100 / designWidth;

? ? ? ? remStyle.innerHTML = 'html{font-size:' + rem + 'px;}';

? ? }

? ? if (docEl.firstElementChild) {

? ? ? ? docEl.firstElementChild.appendChild(remStyle);

? ? } else {

? ? ? ? var wrap = doc.createElement("div");

? ? ? ? wrap.appendChild(remStyle);

? ? ? ? doc.write(wrap.innerHTML);

? ? ? ? wrap = null;

? ? }

? ? //要等 wiewport 設(shè)置好后才能執(zhí)行 refreshRem,不然 refreshRem 會執(zhí)行2次;

? ? refreshRem();

? ? win.addEventListener("resize", function() {

? ? ? ? clearTimeout(tid); //防止執(zhí)行兩次

? ? ? ? tid = setTimeout(refreshRem, 300);

? ? }, false);

? ? win.addEventListener("pageshow", function(e) {

? ? ? ? if (e.persisted) { // 瀏覽器后退的時候重新計(jì)算

? ? ? ? ? ? clearTimeout(tid);

? ? ? ? ? ? tid = setTimeout(refreshRem, 300);

? ? ? ? }

? ? }, false);

? ? if (doc.readyState === "complete") {

? ? ? ? doc.body.style.fontSize = "16px";

? ? } else {

? ? ? ? doc.addEventListener("DOMContentLoaded", function(e) {

? ? ? ? ? ? doc.body.style.fontSize = "16px";

? ? ? ? }, false);

? ? }

})(750, 750);

其中最后的兩個參數(shù)是可以設(shè)置的,第一個參數(shù)是設(shè)計(jì)稿的寬度,一般設(shè)計(jì)稿有640,或者是750,你可以根據(jù)實(shí)際調(diào)整。第二個參數(shù)則是設(shè)置制作稿的最大寬度,超過750,則以750為最大限制。

或者可以直接使用以下html模板(沒截全,看清楚script放在哪個位置,寫什么就好。)


html模板一部分

之后再在我們編寫css的時候,統(tǒng)一使用rem作為單位來編寫。

【這里要尤其注意的是,flexible.min.js版本與手淘版本的計(jì)算rem的方法不同,該代碼版本使用的是1rem=100px的換算。·

該版本使用的是1rem=100px的換算。該版本使用的是1rem=100px的換算。該版本使用的是1rem=100px的換算。該版本使用的是1rem=100px的換算。?

假如你有一個塊是.box{width:120px;height:80px;} 轉(zhuǎn)為rem則為.box{width:1.2rem; height:.8rem;},這樣編寫。

當(dāng)然,我們用vue的時候不用這么繁瑣。

用vue的時候,用npm先install一下flexible包,然后引入,再設(shè)置下,完事。

1.npm下載

npm i lib-flexible --save

2.main.js引入

import 'lib-flexible/flexible.js'

通過要以上兩步,就完成了在vue項(xiàng)目使用lib-flexible來解決移動端適配了。

lib-flexible會自動在html的head中添加一個meta name="viewport"的標(biāo)簽,同時會自動設(shè)置html的font-size為屏幕寬度除以10,也就是1rem等于html根節(jié)點(diǎn)的font-size。假如設(shè)計(jì)稿的寬度是750px,此時1rem應(yīng)該等于75px。假如量的某個元素的寬度是150px,那么在css里面定義這個元素的寬度就是 width: 2rem。

3.這里需要注意幾點(diǎn):

(1)檢查一下html文件的head中,如果有 meta name="viewport"標(biāo)簽,需要將他注釋掉,因?yàn)槿绻羞@個標(biāo)簽的話,lib-flexible就會默認(rèn)使用這個標(biāo)簽。而我們要使用lib-flexible自己生成的 meta name="viewport"來達(dá)到高清適配的效果。

(2)因?yàn)閔tml的font-size是根據(jù)屏幕寬度除以10計(jì)算出來的,所以我們需要設(shè)置頁面的最大寬度是10rem。


接下來就可以愉快地用rem寫css了。

藍(lán)鵝,一個個去除rem基準(zhǔn)值(這個版本里是100),除到頭禿。所以我們可以使用px2rem-loader自動將css中的px轉(zhuǎn)成rem~~~

所以我們使用 webpack 的 px2rem-loader,自動將px轉(zhuǎn)換為rem

這里我們參考了這篇文章,步驟基本相同,達(dá)到的效果沒毛病。

vue.js移動端配置flexible.js

1.安裝

npm install px2rem-loader --save-dev

2.配置

找到 build/utils.js文件,在utils.js中添加如下配置:


找到generateLoaders方法,在函數(shù)里如下配置:

重啟后,你的項(xiàng)目寫的px全變成了rem,所以你的px按照設(shè)計(jì)稿來寫就行。

————————————————————————————————————————

Sass預(yù)處理語言可以通過函數(shù)將px轉(zhuǎn)換成rem,這樣我們編寫css的時候只需要用設(shè)計(jì)稿的px就行。

根據(jù)rem的原理,設(shè)定了HTML根元素的font-size值,只需要相應(yīng)的像素值除以font-size值即可。利用SCSS提供的@function寫出這個函數(shù)

@functionpxTorem($pixels){?

?@return$pixels / $font_size+rem;}

然后我們寫scss的時候這樣寫:(這里隨便舉例,實(shí)際上寫設(shè)計(jì)稿px)

div{

width:rem(100px);

height:rem(100px);}

編譯后,就會自然變成下面這樣:

div{

width:6.25rem;

height:6.25rem; }

let'all,基本上rem自適應(yīng)布局就是這么回事~(入門級別的寫法,求高手)

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

友情鏈接更多精彩內(nèi)容