移動端適配大致兩種,一種是百分比還有一種就是rem脱篙,這里就說說rem適配要怎么做娇钱,原理是什么。先說說為什么要做適配吧绊困。
為何要適配文搂?
眾所周知,手機屏幕的尺寸是五花八門的秤朗,像素密度也是不一樣的煤蹭。同樣是寬度5cm的屏幕,有的手機是720px取视,有的手機是1080px硝皂。
那么假設設計師有個設計稿,寬度是720px的作谭,設計稿里有張圖稽物,這張圖的寬度也是720px。如果我們直接在代碼里寫這張圖的寬度為720px折欠,那我們在720px的手機上看則是正常的贝或,這里我們用一個div做演示
但是當用戶的手機屏幕寬度有1080px的時候呢吼过?看起來就會像這樣
很顯然這跟預期的不一樣,所以我們需要div的尺寸跟隨實際屏幕的寬度進行縮放咪奖。這時盗忱,我們的rem就剛好滿足需求。
rem(font size of the root element)是指相對于根元素的字體大小的單位羊赵。簡單的說它就是一個相對單位售淡。看到rem大家一定會想起em單位慷垮,em(font size of the element)是指相對于父元素的字體大小的單位揖闸。它們之間其實很相似,只不過一個計算的規(guī)則是依賴根元素一個是依賴父元素計算料身。
簡單來說汤纸,我們設定html元素的font-size等于100px時,1rem就等于100px芹血。1 rem = 1 font-size
所以我們只需要獲取屏幕的寬度贮泞,然后根據(jù)寬度和設計稿的比例來計算html的font-size,并設置上去幔烛。
在寫代碼的時候啃擦,就用rem代替px,這樣就可以使div的尺寸根據(jù)html的font-size縮放了
如何計算font-size饿悬?
我們來做幾個設定
- 設計稿寬度為750px
- 設計稿中有一個div令蛉,寬度也是750px
- 理想狀態(tài)(實際屏幕寬度也是750px)下html的font-size是100px,即1rem=100px
那么狡恬,我們先手動寫一下理想狀態(tài)
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>rem適配</title>
</head>
<style>
body {
margin: 0;
font-size: 16px;;
}
html {
font-size: 100px;
}
</style>
<body>
<div style="width: 7.5rem;background: yellow;">
750px/100 = 7.5rem div
</div>
</body>
</html>
一定要寫body下的font-size=16px珠叔,或者你需要的,不然body元素下的文字默認大小就會繼承html下的100px弟劲,那樣的話祷安,字體就太大了。
好了兔乞,來看效果
一切正常汇鞭,我們來把屏幕像素稍微調(diào)大一點,把屏幕寬度調(diào)成900庸追。
由于我們沒有動態(tài)調(diào)節(jié)html的font-size,所以div的寬度沒有跟隨變化霍骄。那么就來計算一下。
先算出100px是設計稿的多少倍锚国,然后再乘以實際屏幕寬度腕巡,就能算出縮放后的font-size了。
100/750*900 = 120px
現(xiàn)在把120設置上去
html {
font-size: 120px;
}
搞定~
好了血筑,rem適配的基本原理你已經(jīng)知道了绘沉,我們開始編碼煎楣。
新建一個flexible.js
// designWidth:設計稿的實際寬度值,需要根據(jù)實際設置
// maxWidth:支持縮放的最大屏幕寬度值车伞,當屏幕寬度超過此值則按最大值進行計算择懂,需要根據(jù)實際設置
// 這段js的最后面有兩個參數(shù)記得要設置,一個為設計稿實際寬度另玖,一個為支持縮放的最大屏幕寬度值困曙,例如設計稿為750,最大寬度為750谦去,則為(750,750)
(function(designWidth, maxWidth) {
var doc = document
var win = window
var docEl = doc.documentElement
var remStyle = document.createElement('style') // 創(chuàng)建一個style標簽慷丽,用于寫html樣式
var tid //timeout句柄
// 計算rem的值,即1rem等于多少px
function refreshRem() {
var width = docEl.getBoundingClientRect().width // 獲取屏幕寬度
maxWidth = maxWidth || 750 // 當沒寫maxWidth時鳄哭,默認maxWidth=750
// 當屏幕寬度超過最大縮放的值要糊,則按最大值處理,不能無限縮放妆丘,那樣會變得很大锄俄,很丑
if (width > maxWidth) {
width = maxWidth
}
// 計算html的font-size
var rem = 100 / designWidth * width
remStyle.innerHTML = 'html{font-size:' + rem + 'px;}'
}
// 將style標簽插入到文檔
if (docEl.firstElementChild) {
docEl.firstElementChild.appendChild(remStyle)
} else {
var wrap = doc.createElement('div')
wrap.appendChild(remStyle)
doc.write(wrap.innerHTML)
wrap = null
}
// 要等 wiewport 設置好后才能執(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) { // 瀏覽器后退的時候重新計算
clearTimeout(tid)
tid = setTimeout(refreshRem, 300)
}
}, false)
// 設定body的默認字體大小奶赠,如果不設置,將集成html的字體大小药有,而我們設置的100毅戈,so...
if (doc.readyState === 'complete') {
doc.body.style.fontSize = '16px'
} else {
doc.addEventListener('DOMContentLoaded', function(e) {
doc.body.style.fontSize = '16px'
}, false)
}
})(750, 750)
// 這里我們輸入設計稿750px,支持的最大屏幕寬度也是750px塑猖。
可能有同學會問竹祷,為什么只有750px,現(xiàn)在手機都是1080px了羊苟。
其實瀏覽器返回給js和css的px都是抽象的,是根據(jù)真實像素和ppi計算出來的感憾,像我的小米8蜡励,1080px寬度,js獲取的屏幕寬度也只有393px
并且一定要在head元素里寫 <meta name="viewport" content="width=device-width, initial-scale=1.0">
關(guān)于viewport是啥阻桅,可以參閱 https://blog.csdn.net/lamanchas/article/details/78473249
最后凉倚,我們只需要在html中引用此文件即可,也可以用es6的方式引用
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>rem適配</title>
<script src="./flexible.js" type="text/javascript"></script>
<style>
body {
margin: 0;
}
</style>
</head>
<body>
<div style="width: 7.5rem;background: yellow;">
750px/100 = 7.5rem div
</div>
</body>
<script>
</script>
</html>