前言

作為一名前端碼農(「工程師」這個稱號太高大上,我還用不起。)如果不會移動端適配就別說自己是搞前端的。畢竟 PC 獨霸天下的時代已經過去了,現在移動端這股浪潮誰也阻止不了。話不多說,下面是我個人總結的一些移動端適配的方法。

百分比

百分比布局是比較早的適配方式,因為 CSS2.0 時代就已經支持這個方法。其作用可以使頁面隨著屏幕寬度(或者瀏覽器寬度)改變而自適應。使用時要註意高度設置百分比時,要求其父類元素有明確高度

例如:

1
2
3
4
5
6
7
8
9
<html style="height: 100%;">
<body style="height: 100%;">
<div style="height: 100%; width:100%; bacground-color: #b71c1c;">
<!-- html標簽高度等於瀏覽器當前高度乘100% -->
<!-- body標簽高度等於html標簽前高度乘100% -->
<!-- div標簽高度等於body標簽前高度乘100% -->
</div>
</body>
</html>

rem

rem(root em)是一個新單位其大小等於 html 標簽的字體大小。除了 IE8 及更早版本外所有瀏覽器均已支持 rem。

例如:

1
2
3
html {
font-size: 16px; /* 此時1rem等於16px */
}

因此只要讓 html 標簽字體大小隨著屏幕大小改變而改變,那麽頁面中使用 rem 設置寬高的盒子也會隨著屏幕大小改變而改變。
常用的的方法有兩種。

Media Queries 法

利用媒體查詢,根據屏幕大小動態設置 html 標簽的字體大小(缺點是只能查詢一些常規的屏幕,無法適配所有屏幕。)。

例如:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
html {
font-size: 10px;
}
@media screen and (min-width: 321px) and (max-width: 375px) {
html {
font-size: 11px;
}
}
@media screen and (min-width: 376px) and (max-width: 414px) {
html {
font-size: 12px;
}
}
@media screen and (min-width: 415px) and (max-width: 639px) {
html {
font-size: 15px;
}
}
@media screen and (min-width: 640px) and (max-width: 719px) {
html {
font-size: 20px;
}
}
@media screen and (min-width: 720px) and (max-width: 749px) {
html {
font-size: 22.5px;
}
}
@media screen and (min-width: 750px) and (max-width: 799px) {
html {
font-size: 23.5px;
}
}
@media screen and (min-width: 800px) {
html {
font-size: 25px;
}
}

腳本動態更新法

利用 JS,當屏幕大小改變時動態設置 html 標簽字體大小。

例如:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
;((doc, win) => {
let docElement = doc.documentElement,
resizeEvent =
'orientationchange' in window ? 'orientationchange' : 'resize',
recalc = () => {
let clientWidth = docElement.clientWidth /* clientWidth為屏幕的寬度 */
if (!clientWidth) return
docElement.style.fontSize = 20 * (clientWidth / 375) + 'px'
}

recalc()

if (!doc.addEventListener) return
win.addEventListener(resizeEvent, recalc, false)
})(document, window)

由於提供的設計稿基本都是以 iphone6/7/8(物理像素寬度 750px,邏輯像素寬度 375px,dpr 為 2。)為參考的,所以計算 rem 時除以 375。

註意:此段代碼必須放在 head 標簽中,而且必須放在所有 css 代碼之前。如果頁面一開始渲染沒有首先執行此段代碼,則後續會按照 html 標簽默認字體大小進行渲染。而且在渲染完成後執行此段代碼會引起回流,造成頁面卡頓閃屏現象。

lib-flexible

由於 viewport 單位得到眾多瀏覽器的兼容,lib-flexible 這個過渡方案已經可以放棄使用,不管是現在的版本還是以前的版本,都存有一定的問題。

源碼:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
;(function flexible(window, document) {
var docEl = document.documentElement
var dpr = window.devicePixelRatio || 1

function setBodyFontSize() {
if (document.body) {
document.body.style.fontSize = 12 * dpr + 'px'
} else {
document.addEventListener('DOMContentLoaded', setBodyFontSize)
}
}

setBodyFontSize()

function setRemUnit() {
var rem = docEl.clientWidth / 10
docEl.style.fontSize = rem + 'px'
}

setRemUnit()

window.addEventListener('resize', setRemUnit)

window.addEventListener('pageshow', function (e) {
if (e.persisted) {
setRemUnit()
}
})

if (dpr >= 2) {
var fakeBody = document.createElement('body')
var testElement = document.createElement('div')
testElement.style.border = '.5px solid transparent'
fakeBody.appendChild(testElement)
docEl.appendChild(fakeBody)

if (testElement.offsetHeight === 1) {
docEl.classList.add('hairlines')
}
docEl.removeChild(fakeBody)
}
})(window, document)

Flex Box

直接看阮一峰老師的吧:
Flex 布局教程:語法篇
Flex 布局教程:實例篇
Flexbox 布局的最簡單表單

移動端適配(下)