【技術】移動端適配 px2rem/px2vw 的原理與實現

簡介

【目標】:前端開發移動端及H5時候,不須要再關心移動設備的大小,只須要按照固定設計稿的px值佈局!
【基礎】javascript

  1. dpr(設備像素比)
    css的像素px不等於設備像素/分辨率/各類值,css的px能夠簡單理解爲虛擬像素,與設備無關,css的px須要乘dpr計算爲設備像素;
  2. css3 的 rem,
    即「root em」,是相對於根元素<html>的font-size來作計算;
    配合js根據設備的dpr設置html的font-size=「XX」來實現等比縮放
  3. 基於 viewport 的長度單位:
    vw:即Viewport's width,1vw等於window.innerWidth的1%,因此窗口寬度是100vm
    vh:和vw相似,即Viewport's height,1vh等於window.innerHeihgt的1%
    vmin:vmin的值是當前vw和vh中較小的值
    vmax:vmax的值是當前vw和vh中較大的值

實現

整體來講是將px經過預約義的配置,根據不一樣的dpr計算爲rem/vw,來實現不一樣屏幕大小的響應式伸縮css

1. px 轉 rem

css3的rem是基於根元素的字體大小計算的尺寸單位,因此經過改變html的font-size來實現rem的響應式佈局,例如使用css媒體查詢:html

html{font-size:10px}
@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}}

但不一樣分辨率的屏幕計算轉換太複雜,媒體查詢不能兼顧全部的尺寸,因此能夠經過JS計算。先貼代碼:前端

var deviceWidth=document.documentElement.clientWidth;
document.documentElement.style.fontSize =deviceWidth / bodyRemWidth + 'px';

例如設計稿基於iphone5的320px,deviceWidth爲320px,根元素的font-size基於100px,那body的width能夠寫爲3.2em;
當適配640px的屏幕時,deviceWidth爲640px,bodyRemWidth爲3.2rem,此時根元素的font-size計算爲200px;
deviceWidth就是viewport設置中的deviceWidth,viewport視圖提供佈局的窗口,包括移動端的顯示/縮放比例等設置;
須要設置mate的viewport使得顯示時的頁面寬度等於設備邏輯像素大小,移動端經常使用代碼:vue

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

deviceWidth=設備邏輯像素/(dpr * scale);
dpr爲固定值,高清屏通常爲dpr=2,因此scale=1/dpr,js動態設置scale:html5

var scale = 1 / devicePixelRatio;
document.querySelector('meta[name="viewport"]')
    .setAttribute('content','initial-scale=' + scale + ', 
    maximum-scale=' + scale + ', 
    minimum-scale=' + scale + ', 
    user-scalable=no');

2. 進階:px 轉 vw

方式簡而言之就是,基於css3中Viewport相關vw、vh、vmin和vmax單位,將寬高的px計算爲vw/vh,而vmax/vmin老是指向那個最大/最小的屏幕長度java

var vw = window.innerWidth; 
var vh = window.innerHeight;

例如對於320px的設計稿,屏幕總長一直是100vw,因此比率是3.2,那css代碼須要將全部--px/3.2獲得**vm,
這樣很麻煩,因此使用postcss-px-to-viewport實現編譯時候的自動計算,還要配合postcss-write-svg,postcss-aspect-ratio-mini等插件解決Retina,1px等問題react

3. 再進階:兼容 vw

目前應用比較廣的是px2rem,隨着瀏覽器對viewport的支持,但將來趨勢是px2vm,用vm代替rem,但要兼容就大亂燉啥都要,,,
不少技術站都提供了兼容插件,好比postcss-cssnext, postcss-viewport-units, viewport-units-buggyfill。
不一樣的前端框架vue/react,配合webpack/grund等打包工具,能夠更高效的使用這些插件,完成移動端適配的配置工做。
【傳送門】
Amfe阿里前端團隊一直都對這方面的技術作了很是好的研究,還提供了開源的代碼:https://github.com/amfe/lib-f...
大漠寫的很是詳細的博客:使用Flexible實現手淘H5頁面的終端適配,還有進一步講vw的:再聊移動端頁面的適配如何在Vue項目中使用vw實現移動端適配。向大牛獻上一份膝蓋~~~webpack

4. 推薦插件

主要的插件都是基於PostCss的,千萬不要去百度PostCss,要否則從當前坑還沒爬出來,又會發現另外一個坑,,,css3

  1. px2rem或postcss-px2rem:將css中px編譯爲rem,配合js根據不一樣的dpr,修改meta的viewport值和html的font-size
  2. postcss-px-to-viewport:將css中px編譯爲vm
  3. postcss-aspect-ratio-mini:用來處理元素容器寬高比,針對img、vedio和iframe實現更好的長寬比
  4. postcss-write-svg:解決1px問題(移動端css裏面寫了1px, 實際看起來比1px粗),自動生成border-image或者background-image的圖片
  5. viewport-units-buggyfill:實現各個瀏覽器viewport的兼容
  6. postcss-viewport-units:給CSS的屬性添加content的屬性,配合viewport-units-buggyfill庫給vw、vh、vmin和vmax作適配的

加油吧~少年~

相關文章
相關標籤/搜索