移動(dòng)端適配方案有哪幾種?

前端開發(fā)中最重要的一塊需求就是移動(dòng)端適配。雖然我們課程明確的區(qū)分各種移動(dòng)端適配方案,但依然有很多同學(xué)搞不清楚移動(dòng)端等比適配和響應(yīng)式,這里對(duì)移動(dòng)端主流適配方案給大家做一個(gè)分析。
移動(dòng)端適配是指同一個(gè)頁(yè)面可以在不同的移動(dòng)端設(shè)備上都有合理的布局。主流的實(shí)現(xiàn)方案有兩種:
響應(yīng)式布局,通過@media實(shí)現(xiàn)一套html配合多套css實(shí)現(xiàn)適配;
通過rem或者vw,vh等實(shí)現(xiàn)不同的設(shè)備俺照相同的比例適配;
這里給大家列舉幾個(gè)例子:
小米移動(dòng)端商城,很明顯是采用了rem等比適配的方案。

不凡官網(wǎng),采用了@media媒體監(jiān)聽實(shí)現(xiàn)適配。

王者榮耀,同時(shí)采用了媒體監(jiān)聽和rem等比適配。

vh,vm 暫時(shí)沒找到。
實(shí)現(xiàn)原理
首先需要了解一個(gè)概念:viewport 視口(mdn)。如果要實(shí)現(xiàn)瀏覽器適配移動(dòng)端,首先我們要統(tǒng)一標(biāo)準(zhǔn)視口。在html的head中添加以下代碼:
<meta name="viewport" content="width=device-width,initial-scale=1, maximum-scale=1, user-scalable=no">
第一種:rem實(shí)現(xiàn)原理
rem是一個(gè)倍數(shù)單位,它是基于html的font-size的倍數(shù)。只要我們?cè)诓煌脑O(shè)備上設(shè)置一個(gè)合適的初始值,當(dāng)設(shè)備發(fā)生變化font-size就會(huì)自動(dòng)等比適配大小,從而在不同的設(shè)備上表現(xiàn)統(tǒng)一。
比如說:移動(dòng)端設(shè)計(jì)稿一般會(huì)以750px進(jìn)行交付,而手機(jī)實(shí)際像素可能是375px。那么一般我們會(huì)以設(shè)備寬度的1/10作為初試html的font-size大小,當(dāng)然這個(gè)值是動(dòng)態(tài)的,在不同設(shè)備上得到的值不同。
比如有的設(shè)備寬度是375px,那么html初始font-size就是37.5px,如果設(shè)備寬度是300px,那么font-size就是30px。 因?yàn)閮?nèi)容都是rem基于font-size的倍數(shù),所以不同寬度的設(shè)備上都是等比顯示的。
注意:這個(gè)font-size基數(shù)到底是不是設(shè)備的1/10是沒有統(tǒng)一論調(diào)的,你可以用1/n任意定義。關(guān)鍵是理解rem適配的原理是元素等比縮放。
參照具體代碼:
<!DOCTYPE html>
<!-- 0. 注意:font-size是動(dòng)態(tài)設(shè)置,寬度為屏幕1/10 -->
<html>
<head>
? <meta charset="UTF-8">
? <meta http-equiv="X-UA-Compatible" content="IE=edge">
? <!-- 1. 標(biāo)準(zhǔn)視口,禁止縮放,初始縮放為1 -->
? <meta name="viewport" content="width=device-width,initial-scale=1, maximum-scale=1, user-scalable=no">
? <title>移動(dòng)視口</title>
? <style>
? ? *{
? ? ? margin: 0;
? ? ? padding: 0;
? ? }
? ? .box{
? ? ? /* 4. 如果原稿寬度是750px,而且在750寬度的設(shè)備上開發(fā)。則375px應(yīng)該還是375px。?
? ? ? 基礎(chǔ)font-size為75px,則這里換算成rem應(yīng)該是5rem */
? ? ? /*
? ? ? 想必你不一定能理解。試想如果在375寬度的設(shè)備上開發(fā)。這里的5rem是不是應(yīng)該為37.5的5倍?
? ? ? ? 37.5*5=187.5剛好為375的1/2呢?
? ? ? */
? ? ? width: 5rem;
? ? ? height: 5rem;
? ? ? background-color: green;
? ? }
? </style>
</head>
<body>
? <!-- 2. 假設(shè)一個(gè)750px寬度的設(shè)計(jì)稿,給了一個(gè)375px的元素塊。 -->
? <!-- 我們的實(shí)現(xiàn)應(yīng)該是一個(gè)盒子在不同寬度的設(shè)備上都應(yīng)該表現(xiàn)一致(占比屏幕寬度的1/2)。
? 因?yàn)槠聊粚挾炔灰欢?,通過px顯然無法實(shí)現(xiàn),那么我們就需要使用rem來做等比縮放。 -->
? <!-- 一個(gè)簡(jiǎn)單的例子: -->
? <div></div>
? <script>
? ? // 3. 這里通過js監(jiān)聽屏幕尺寸 設(shè)置html的font-size
? ? function setView(){
? ? ? document.documentElement.style.fontSize = screen.width/10 + 'px';
? ? }?
? ? setView();
? ? // 這里是為什么?你自己想一想
? ? window.onresize = setView;
? </script>
</body>
</html>
至于px如何轉(zhuǎn)換為rem,在vscode中可以搜索相關(guān)插件。

第二種: 媒體監(jiān)聽
媒體監(jiān)聽通過@media實(shí)現(xiàn)。注意:媒體監(jiān)聽不是等比縮放!??!是同一塊內(nèi)容在不同設(shè)備上有合理的表現(xiàn)。
比如在PC端一行能同時(shí)展示4個(gè)元素塊,而在移動(dòng)端只能一行展示1個(gè)或者2個(gè)元素塊(要不看不清)。
那么就可以通過監(jiān)聽媒體寬度,給元素設(shè)置不同的寬度,從而有合理的表現(xiàn)。
代碼參考:
<!DOCTYPE html>
<html>
<head>
? <meta charset="UTF-8">
? <meta http-equiv="X-UA-Compatible" content="IE=edge">
? <!-- 1. 標(biāo)準(zhǔn)視口,禁止縮放,初始縮放為1 -->
? <meta name="viewport" content="width=device-width,initial-scale=1, maximum-scale=1, user-scalable=no">
? <title>媒體監(jiān)聽適配</title>
? <style>
? ? *{
? ? ? margin: 0;
? ? ? padding: 0;
? ? }
? ? ul{
? ? ? list-style: none;
? ? }
? ? .header{
? ? ? width: 100%;
? ? ? height: 100px;
? ? ? background-color: pink;
? ? }
? ? .header .header-c{
? ? ? width: 1200px;
? ? ? height: 100px;
? ? ? background-color: green;
? ? ? margin: 0 auto;
? ? }
? ? .header .nav{
? ? ? /* width: xx */
? ? ? height: 100%;
? ? }
? ? .header .nav .nav-item{
? ? ? float: left;
? ? ? width: 100px;
? ? ? height: 100%;
? ? ? line-height: 100px;
? ? ? text-align: center;
? ? ? cursor: pointer;
? ? }
? ? /* 3. 針對(duì)適配的設(shè)備重新寫一套樣式 */
? ? @media screen and (max-width: 750px){
? ? ? .header{
? ? ? ? position: relative;
? ? ? ? height: 40px;
? ? ? }
? ? ? .header .header-c{
? ? ? ? width: 100%;
? ? ? }
? ? ? .header .nav{
? ? ? ? position: absolute;
? ? ? ? width: 100%;
? ? ? ? left: 0;
? ? ? ? top: 40px;
? ? ? }
? ? ? .header .nav .nav-item{
? ? ? ? float: none;
? ? ? ? width: 100%;
? ? ? ? height: 40px;
? ? ? ? background-color: pink;
? ? ? ? border-bottom: 1px solid gray;
? ? ? ? line-height: 40px;
? ? ? }
? ? }
? </style>
</head>
<body>
? <!-- 2. 要明確媒體監(jiān)聽實(shí)現(xiàn)的不是等比縮放!?。《峭粋€(gè)內(nèi)容在不同設(shè)備上都有合理的表現(xiàn)。 -->
? <!-- 比如一個(gè)導(dǎo)航 -->
? <div>
? ? <div>
? ? ? <ul>
? ? ? ? <li>首頁(yè)</li>
? ? ? ? <li>分類</li>
? ? ? ? <li>發(fā)現(xiàn)</li>
? ? ? ? <li>我的</li>
? ? ? </ul>
? ? </div>
? </div>
</body>
</html>
第三種: vw/vh方案
vw 是相對(duì)單位,1vw 表示屏幕寬度的 1%。需要縮放的元素采用vw,不需要的采用px。
具體實(shí)現(xiàn)方法與rem類似,至于轉(zhuǎn)換問題也可以參考rem的插件形式。
各種方案對(duì)比
rem方案:
原理不好理解^_^
從px到rem的轉(zhuǎn)換需要使用工具
靈活可控,幾乎完美復(fù)刻設(shè)計(jì)稿
可能大量出現(xiàn)小數(shù)點(diǎn),由于換算有些許誤差(極?。?/p>
適合具有完全移動(dòng)端設(shè)計(jì)稿的項(xiàng)目
media媒體監(jiān)聽方案:
沒有學(xué)習(xí)成本
如何適配需要重新定義,可能設(shè)計(jì)稿都不會(huì)體現(xiàn)
復(fù)雜的組件很難有完美的呈現(xiàn)
適合只有PC端設(shè)計(jì)稿,又需要兼容移動(dòng)端的需求
綜合方案:
可以同時(shí)使用media和rem
實(shí)現(xiàn)更大的自由度和更完美的呈現(xiàn)
實(shí)現(xiàn)復(fù)雜,顆粒度不好把控
這里總結(jié)了兩種常用的移動(dòng)端適配方案。其實(shí)后來的微信小程序css單位rpx,換算方法為1px=2rpx,應(yīng)該和rem的適配方案原理大致相同。