淺談移動端適配

前言

隨著移動端的普及,以及手機尺寸越來越多躬拢,“網(wǎng)頁內(nèi)容自適應(yīng)屏幕尺寸進行顯示的問題” 也日漸凸顯出來躲履,下面講一下常見的適配方案。

本文默認你已經(jīng)對視口聊闯、物理像素工猜、邏輯像素、設(shè)備像素比菱蔬、css像素等移動端基本概念已經(jīng)解篷帅。

1.為何要適配

一般情況下設(shè)計稿的設(shè)計師按照 375 的尺寸設(shè)計,然而汗销,在現(xiàn)在移動終端(就是手機)快速更新的時代犹褒,每個品牌的手機都有著不同的物理分辨率,這樣就會導(dǎo)致弛针,每臺設(shè)備的邏輯分辨率也不盡相同叠骑,此時 375 的設(shè)計稿,如果想要還原那基本是不可能了削茁,因為如果一個左右布局宙枷,左邊如果寫死,右邊自適應(yīng)的話茧跋,每個設(shè)備的右邊所展示的內(nèi)容大小就不盡相同慰丛,這時移動端適配就顯得尤其重要。

2.如何適配

2.1 viewport 配置

<meta name="viewport" content="width=device-width; initial-scale=1; maximum-scale=1; minimum-scale=1; user-scalable=no;">

分別含義如下:

屬性名 取值 描述
width device-width或正整數(shù) 定義視口的寬度瘾杭,單位為像素诅病,一般為device-width:表示寬度為設(shè)備屏幕的寬度
height device-height或正整數(shù) 定義視口的高度,單位為像素粥烁,一般不用寫
initial-scale [0.0-10.0] 定義初始縮放值贤笆,一般設(shè)置為1.0
minimum-scale [0.0-10.0] 定義縮小最小比例,它必須小于或等于maximum-scale設(shè)置
maximum-scale [0.0-10.0] 定義放大最大比例讨阻,它必須大于或等于minimum-scale設(shè)置
user-scalable yes / no 定義是否允許用戶手動縮放頁面芥永,默認值 yes

有幾點注意:

  • viewport 標簽只對移動端瀏覽器有效,對 PC 端瀏覽器是無效的
  • 當縮放比例為 100% 時钝吮,邏輯像素 = CSS 像素寬度 = 理想視口的寬度 = 布局視口的寬度
  • 單獨設(shè)置 initial-scale 或 width 都會有兼容性問題埋涧,所以設(shè)置布局視口為理想視口的最佳方法是同時設(shè)置這兩個屬性
  • 即使設(shè)置了 user-scalable = no,在 Android Chrome 瀏覽器中也可以強制啟用手動縮放

2.2 適配方案

2.2.1 基于flexible的rem 適配
  • rem的本質(zhì)是等比縮放奇瘦。
  • 動態(tài)設(shè)置根元素的font-size來達到我們想要的效果棘催。
  • 結(jié)合postcss-pxtorem插件將頁面單位轉(zhuǎn)換成rem

設(shè)置 rem 基準值

/*
思路:
1. 頁面初始化的時候設(shè)置一次html的字體大小
2. 監(jiān)聽設(shè)備寬度的改變和頁面刷新,獲取當前屏幕寬度链患,隨之改變html的font-size大小巧鸭。
*/

// 立即執(zhí)行函數(shù)中,傳入window,doucment避免全局污染
(function flexible (window, document) {
// 為獲取HTML文檔的整個文檔元素
  var docEl = document.documentElement
//獲取設(shè)備像素比例麻捻,若像素比例為0則以1代替
  var dpr = window.devicePixelRatio || 1

  // adjust body font size 設(shè)置自適應(yīng)字體大小纲仍,覆蓋html的fontSize
  function setBodyFontSize () {
    //判斷body是否存在呀袱,存在則設(shè)置大小,不存在則監(jiān)聽DOM加載完后再遞歸調(diào)用此方法 
    if (document.body) {
      document.body.style.fontSize = (12 * dpr) + 'px'
    }
    else {
      document.addEventListener('DOMContentLoaded', setBodyFontSize)
    }
  }
  setBodyFontSize();

  // set 1rem = viewWidth / 10
  function setRemUnit () {
    //獲取屏幕寬度
    var rem = docEl.clientWidth / 10
    // var rem = 375 / 10 
    //修改html字體大小
    docEl.style.fontSize = rem + 'px'
  }

  setRemUnit()

// reset rem unit on page resize 監(jiān)聽頁面寬度改變來設(shè)置rem
  window.addEventListener('resize', setRemUnit)
  window.addEventListener('pageshow', function (e) {
    if (e.persisted) {
      setRemUnit()
    }
  })

// detect 0.5px supports 檢測支持0.5px 
  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)
    console.log(testElement.offsetHeight)
    if (testElement.offsetHeight === 1) {
      
      docEl.classList.add('hairlines')
    }
    docEl.removeChild(fakeBody)
  }
}(window, document))

核心代碼解釋:

// set 1rem = 邏輯像素(設(shè)備獨立像素) / 10
function setRemUnit () {
    var rem = docEl.clientWidth / 10
    // 375/10 = 37.5
    docEl.style.fontSize = rem + 'px'
}
setRemUnit()
  • 將html節(jié)點的font-size設(shè)置為頁面clientWidth(布局視口)的1/10郑叠,即:1rem = 布局視口的1/10夜赵,

  • 在iphone6下:docEl.clientWidth=設(shè)備獨立像素(邏輯像素)= 布局視口寬度 = 理想窗口寬度 = 375。此時:1rem = 375/10 +px = 37.5px

postcss-pxtorem將單位轉(zhuǎn)化為 rem

module.exports = {
  plugins: {
    'autoprefixer': {
      browsers: ['Android >= 4.0', 'iOS >= 7']
    },
    'postcss-pxtorem': {
        rootValue: 37.5,
        propList: ['*', '!font-size'],
        selectorBlackList: ['van-circle__layer', 'ignore'],
    }
  }
}
  • rootValue 是轉(zhuǎn)換px的基準值乡革,參考設(shè)備iPhone6寇僧,設(shè)備寬度375px。
    規(guī)則:基準值=當前設(shè)備寬度的1/10
  • 基準值設(shè)置代碼中沸版,在iPhone6設(shè)備設(shè)置的 html—>font-size 也為37.5px
  • 但是設(shè)計稿尺寸750px大小嘁傀,所以在設(shè)計稿量取的尺寸使用時候需要除以2 。

因為當年 viewport 在低版本安卓設(shè)備上還有兼容問題视粮,而 vw细办,vh 還沒能實現(xiàn)所有瀏覽器兼容,所以 flexible 方案用 rem 來模擬 vmin 來實現(xiàn)在不同設(shè)備等比縮放的“過度”方案蕾殴,建議大家使用vw來替代此方案笑撞。

2.2.2 vw,vh 適配

vh钓觉、vw 方案即將視覺視口寬度 window.innerWidth 和視覺視口高度 window.innerHeight 等分為 100 份茴肥。

vh 和 vw 方案和 rem 類似也是相當麻煩需要做單位轉(zhuǎn)化,而且 px 轉(zhuǎn)換成 vw 不一定能完全整除荡灾,因此有一定的像素差瓤狐。

不過在工程化的今天,webpack 解析 css 的時候用 postcss-loader 有個 postcss-px-to-viewport 能自動實現(xiàn) px 到 vw 的轉(zhuǎn)化批幌。

{
    loader: 'postcss-loader',
    options: {
        plugins: ()=>[
            require('autoprefixer')({
                browsers: ['last 5 versions']
            }),
            require('postcss-px-to-viewport')({
                viewportWidth: 375, //視口寬度(數(shù)字)
                viewportHeight: 1334, //視口高度(數(shù)字)
                unitPrecision: 3, //設(shè)置的保留小數(shù)位數(shù)(數(shù)字)
                viewportUnit: 'vw', //設(shè)置要轉(zhuǎn)換的單位(字符串)
                selectorBlackList: ['.ignore', '.hairlines'], //不需要進行轉(zhuǎn)換的類名(數(shù)組)
                minPixelValue: 1, //設(shè)置要替換的最小像素值(數(shù)字)
                mediaQuery: false//允許在媒體查詢中轉(zhuǎn)換px(true/false)
            })
        ]
}
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末芬首,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子逼裆,更是在濱河造成了極大的恐慌,老刑警劉巖赦政,帶你破解...
    沈念sama閱讀 218,858評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件胜宇,死亡現(xiàn)場離奇詭異,居然都是意外死亡恢着,警方通過查閱死者的電腦和手機桐愉,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,372評論 3 395
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來掰派,“玉大人从诲,你說我怎么就攤上這事∶蚁郏” “怎么了系洛?”我有些...
    開封第一講書人閱讀 165,282評論 0 356
  • 文/不壞的土叔 我叫張陵俊性,是天一觀的道長。 經(jīng)常有香客問我描扯,道長定页,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,842評論 1 295
  • 正文 為了忘掉前任绽诚,我火速辦了婚禮典徊,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘恩够。我一直安慰自己卒落,他們只是感情好,可當我...
    茶點故事閱讀 67,857評論 6 392
  • 文/花漫 我一把揭開白布蜂桶。 她就那樣靜靜地躺著儡毕,像睡著了一般。 火紅的嫁衣襯著肌膚如雪屎飘。 梳的紋絲不亂的頭發(fā)上妥曲,一...
    開封第一講書人閱讀 51,679評論 1 305
  • 那天,我揣著相機與錄音钦购,去河邊找鬼檐盟。 笑死,一個胖子當著我的面吹牛押桃,可吹牛的內(nèi)容都是我干的葵萎。 我是一名探鬼主播,決...
    沈念sama閱讀 40,406評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼唱凯,長吁一口氣:“原來是場噩夢啊……” “哼羡忘!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起磕昼,我...
    開封第一講書人閱讀 39,311評論 0 276
  • 序言:老撾萬榮一對情侶失蹤卷雕,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后票从,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體漫雕,經(jīng)...
    沈念sama閱讀 45,767評論 1 315
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,945評論 3 336
  • 正文 我和宋清朗相戀三年峰鄙,在試婚紗的時候發(fā)現(xiàn)自己被綠了浸间。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 40,090評論 1 350
  • 序言:一個原本活蹦亂跳的男人離奇死亡吟榴,死狀恐怖魁蒜,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤兜看,帶...
    沈念sama閱讀 35,785評論 5 346
  • 正文 年R本政府宣布,位于F島的核電站铣减,受9級特大地震影響她君,放射性物質(zhì)發(fā)生泄漏葫哗。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,420評論 3 331
  • 文/蒙蒙 一劣针、第九天 我趴在偏房一處隱蔽的房頂上張望校镐。 院中可真熱鬧捺典,春花似錦、人聲如沸襟己。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,988評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至贮预,卻和暖如春贝室,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背仿吞。 一陣腳步聲響...
    開封第一講書人閱讀 33,101評論 1 271
  • 我被黑心中介騙來泰國打工滑频, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人唤冈。 一個月前我還...
    沈念sama閱讀 48,298評論 3 372
  • 正文 我出身青樓峡迷,卻偏偏與公主長得像,于是被迫代替她去往敵國和親你虹。 傳聞我的和親對象是個殘疾皇子凉当,可洞房花燭夜當晚...
    茶點故事閱讀 45,033評論 2 355

推薦閱讀更多精彩內(nèi)容