最近抽空看了看移動端適配的一些文章,也結(jié)合自己的經(jīng)驗做一下總結(jié)以及對比。
那么,開始正題,首先說說到目前位置出現(xiàn)的一些關(guān)于移動端適配的技術(shù)方案:
- 通過媒體查詢的方式即
CSS3的meida queries - 以天貓首頁為代表的
flex彈性布局 - 以淘寶首頁為代表的
rem+viewport縮放 -
rem方式
Meida Queries
meida queries 的方式可以說是我早期采用的布局方式,它主要是通過查詢設(shè)備的寬度來執(zhí)行不同的 css 代碼,最終達(dá)到界面的配置。核心語法是:
@media screen and (max-width: 600px) { /*當(dāng)屏幕尺寸小于600px時,應(yīng)用下面的CSS樣式*/
/*你的css代碼*/
}

優(yōu)點
-
media query可以做到設(shè)備像素比的判斷,方法簡單,成本低,特別是對移動和PC維護(hù)同一套代碼的時候。目前像Bootstrap等框架使用這種方式布局 - 圖片便于修改,只需修改css文件
- 調(diào)整屏幕寬度的時候不用刷新頁面即可響應(yīng)式展示
缺點
- 代碼量比較大,維護(hù)不方便
- 為了兼顧大屏幕或高清設(shè)備,會造成其他設(shè)備資源浪費,特別是加載圖片資源
- 為了兼顧移動端和PC端各自響應(yīng)式的展示效果,難免會損失各自特有的交互方式
Flex 彈性布局
以天貓的實現(xiàn)方式進(jìn)行說明:
它的viewport是固定的:<meta name="viewport" content="width=device-width,initial-scale=1,maximum-scale=1,user-scalable=no">

高度定死,寬度自適應(yīng),元素都采用px做單位。
隨著屏幕寬度變化,頁面也會跟著變化,效果就和PC頁面的流體布局差不多,在哪個寬度需要調(diào)整的時候使用響應(yīng)式布局調(diào)調(diào)就行(比如網(wǎng)易新聞),這樣就實現(xiàn)了『適配』。DEMO>>
<span id = "1">rem+viewport 縮放</span>
這也是淘寶使用的方案,根據(jù)屏幕寬度設(shè)定 rem 值,需要適配的元素都使用 rem 為單位,不需要適配的元素還是使用 px 為單位。
實現(xiàn)原理
根據(jù)rem將頁面放大dpr倍, 然后viewport設(shè)置為1/dpr.
- 如iphone6 plus的dpr為3, 則頁面整體放大3倍, 1px(css單位)在plus下默認(rèn)為3px(物理像素)
- 然后
viewport設(shè)置為1/3, 這樣頁面整體縮回原始大小. 從而實現(xiàn)高清。


這樣整個網(wǎng)頁在設(shè)備內(nèi)顯示時的頁面寬度就會等于設(shè)備邏輯像素大小,也就是device-width。這個device-width的計算公式為:
設(shè)備的物理分辨率/(devicePixelRatio * scale),在scale為1的情況下,device-width = 設(shè)備的物理分辨率/devicePixelRatio 。
具體請查看 https://github.com/amfe/lib-flexible 或 https://www.npmjs.com/package/anima-hd.
rem 實現(xiàn)
說說我司【魅族】移動端的實現(xiàn)方式,viewport也是固定的:<meta name="viewport" content="width=device-width,initial-scale=1,maximum-scale=1,user-scalable=no">。
通過以下代碼來控制rem基準(zhǔn)值(設(shè)計稿以720px寬度量取實際尺寸)
!function (d) {
var c = d.document;
var a = c.documentElement;
var b = d.devicePixelRatio;
var f;
function e() {
var h = a.getBoundingClientRect().width, g;
if (b === 1) {
h = 720
}
if(h>720) h = 720;//設(shè)置基準(zhǔn)值的極限值
g = h / 7.2;
a.style.fontSize = g + "px"
}
if (b > 2) {
b = 3
} else {
if (b > 1) {
b = 2
} else {
b = 1
}
}
a.setAttribute("data-dpr", b);
d.addEventListener("resize", function () {
clearTimeout(f);
f = setTimeout(e, 200)
}, false);
e()
}(window);
css通過sass預(yù)編譯,設(shè)置量取的px值轉(zhuǎn)化rem的變量$px: (1/100)+rem;;

1像素邊框高清
淘寶實現(xiàn)方式
上面說到的淘寶的實現(xiàn)方式即rem+viewport 縮放來實現(xiàn)。
transform: scale(0.5)
CSS代碼:
div{
width: 1px;
height: 100%;
display: block;
border-left: 1px solid #e5e5e5;
-webkit-transform: scaleX(.5);
transform: scaleX(.5);
}
缺點:
- 圓角無法實現(xiàn),實現(xiàn)4條邊框比較麻煩,并且只能單獨實現(xiàn),如果嵌套,會對包含的效果產(chǎn)生不想要的效果,所以此方案配合:after和before獨立使用較多。
box-shadow
實現(xiàn)方法:
利用CSS對陰影處理的方式實現(xiàn)0.5px的效果。
-webkit-box-shadow:0 1px 1px -1px rgba(0, 0, 0, 0.5);
優(yōu)點:
基本所有場景都能滿足,包含圓角的button,單條,多條線。
缺點:
- 顏色不好處理, 黑色
rgba(0,0,0,1)最深的情況了。有陰影出現(xiàn),不好用。 - 大量使用
box-shadow可能會導(dǎo)致性能瓶頸。 - 四條邊框?qū)崿F(xiàn)效果不理想。
圖片實現(xiàn)
使用 background-image 實現(xiàn)1px有兩種方式: 漸變 linear-gradient 或直接使用圖片(base64)。
漸變 linear-gradient (50%有顏色,50%透明)
單條線:
div {
height: 1px;
background-image: -webkit-linear-gradient(top,transparent 50%,#000 50%);
background-position: top left;
background-repeat: no-repeat
background-size: 100% 1px;
}
多條線:
div {
background-image:-webkit-linear-gradient(top, transparent 50%, #000 50%),-webkit-linear-gradient(bottom, transparent 50%, #000 50%),-webkit-linear-gradient(left, transparent 50%, #000 50%),-webkit-linear-gradient(right, transparent 50%, #000 50%);
background-size: 100% 1px,100% 1px,1px 100%,1px 100%;
background-repeat: no-repeat;
background-position: top left, bottom left, left top, right top;
}
優(yōu)點:
- 可以設(shè)置單條,多條邊框
- 可以設(shè)置顏色
缺點:
- 大量使用漸變可能導(dǎo)致性能瓶頸
- 代碼量大
- 多背景圖片有兼容性問題