移動端適配方案

Flexible適配方案
最先的文章,是15年阿里手淘團隊的移動端適配方案。
設計師常選擇iPhone6做爲基準設計尺寸,交付給前端的設計尺寸是按750px * 1334px爲準(高度會隨着內容多少而改變)。
前端開發人員經過一套適配規則自動適配到其餘的尺寸。
先了解一些基本概念
 
視窗viewport
 
簡單理解,viewport是嚴格等於瀏覽器的窗口,在桌面瀏覽器中,viewport就是瀏覽器窗口的寬度高度。
可是在移動端的viewport太窄,爲了能更好的爲css佈局服務,因此提供了兩個viewport:虛擬的viewportvisualviewport和佈局的viewportlayoutviewport(瞭解這兩種viewport概念的能夠 查看這裏)
設備像素比(device pixel ratio)
設備像素比簡稱爲dpr,其定義了物理像素和設備獨立像素的對應關係。
設備像素比 = 物理像素 / 設備獨立像素

 

在JavaScript中,能夠經過`window.devicePixelRatio`獲取到當前設備的dpr。而在CSS中,能夠經過`-webkit-device-pixel-ratio`,`-webkit-min-device-pixel-ratio`和 `-webkit-max-device-pixel-ratio`進行媒體查詢,對不一樣dpr的設備,作一些樣式適配(這裏只針對webkit內核的瀏覽器和webview)
在不一樣的屏幕上,CSS像素所呈現的物理尺寸是一致的,而不一樣的是CSS像素所對應的物理像素具數是不一致的。在普通屏幕下1個CSS像素對應1個物理像素,而在Retina屏幕下,1個CSS像素對應的倒是4個物理像素。
因此在移動端除了佈局的適配外,還須要考慮到圖片的顯示質量,這就是咱們所說的2倍圖或者3倍圖
 
meta標籤
viewport的meta標籤,主要是用來告訴瀏覽器如何規範渲染web頁面,在開發移動端頁面,咱們須要設置meta標籤爲:
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">

  

css單位rem
 
font size of the root element.  來自w3c規範
簡單的理解,rem就是相對於根元素<html>的font-size來作計算。而咱們的方案中使用rem單位,是能輕易的根據<html>的font-size計算出元素的盒模型大小。
實現方案
 
手淘團隊根據以上的概念,出了一套針對移動端的適配方案`amfe-flexible`庫。
使用方法
前提是須要設置頁面的viewport
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, minimum-scale=1, user-scalable=no">
而後引入功能文件
# 阿里CDN引入
<script src="http://g.tbcdn.cn/mtb/lib-flexible/0.3.4/??flexible_css.js,flexible.js"></script>
 
# 下載對應的文件,直接在頁面中引入。
 
# 固然也能夠 npm i -S amfe-flexible
須要注意的一點那就是:在Flexible中,只對iOS設備進行dpr的判斷,對於Android系列,始終認爲其dpr爲1。
lexible實際上就是能過JS來動態改寫meta標籤,相似這樣:
# 動態改寫<meta>標籤# 
給<html>元素添加data-dpr屬性,而且動態改寫data-dpr的值#
給<html>元素添加font-size屬性,而且動態改寫font-size的值
  var metaEl = doc.createElement('meta');
  var scale = isRetina ? 0.5:1;metaEl.setAttribute('name', 'viewport');
  metaEl.setAttribute('content', 'initial-scale=' + scale + ', maximum-scale=' + scale + ', minimum-scale=' + scale + ', user-scalable=no');
  if (docEl.firstElementChild) {    
     document.documentElement.firstElementChild.appendChild(metaEl);
  } else {    
  var wrap = doc.createElement('div');    
  wrap.appendChild(metaEl);   
  documen.write(wrap.innerHTML);
}

  

接下來要作的事情就是`px`->`rem`
1.能夠經過在編輯器中安裝插件實現單位的換算
2.能夠經過配置postCSS進行自動的單位轉換,還按照正常的px進行佈局,代碼執行後會自動轉成對應的rem數值。(具體的配置方法,須要看另外的關於postCSS的文章(待完善))
這套方案,在實際構建M站的過程當中,我遇到的一個問題是,1px的border沒法正常顯示,目前網上沒有一個很完美的解決方案,更多提到的是轉爲svg的方式實現。
 
不一樣的終端,咱們面對的屏幕分辨率、DPR、1px、2x圖等一系列的問題。那麼這個佈局方案也是針對性的解決這些問題,只不過解決這些問題再也不是使用Hack手段來處理,而是直接使用原生的CSS技術來處理的。
vw是基於viewport視窗的長度單位。指的是瀏覽器可視化的區域,也就是window.innerWidth/window.innerHeight的大小。
 
1vw = window.innerWidth 的 1%

目前出視覺設計稿,咱們都是使用750px寬度的,從上面的原理來看,那麼100vw = 750px,即1vw = 7.5px。那麼咱們能夠根據設計圖上的px值直接轉換成對應的vw值。
這裏固然咱們也去能夠手動去轉化單位,可是咱們能夠在項目的配置項中添加`postCSS`相關的配置,能夠爲咱們自動去轉化。咱們也只須要按照設計稿給的px去進行佈局便可。
下面介紹在`grunt`上配置`postCSS`
 
安裝postCSS插件
 
# grunt
npm install grunt-postcss --save-dev
 
#webpack
npm install postcss-loader --save-dev
 
grunt中配置
 
在`gruntfile.js`中配置,經過`grunt.loadNpmTasks()`函數加載`grunt-postcss`插件
module.exports = function(grunt) {
    grunt.initConfig({
        postcss:{
            options:{
                //  配置postCSS所需插件
                processors:[
                    //  這是postCSS插件
                    //  自動添加前綴
                    require('autoprefixer'),
                    //  適配方案
                    require('postcss-px-to-viewport')({
                      viewportWidth: 750,
                        viewportHeight: 1670,
                        unitPrecision: 5,
                        viewportUnit: 'vw',
                        selectorBlackList: [],
                        minPixelValue: 1,
                        mediaQuery: false
                    })
                ]
            },
            dist:{
                //  設置CSS的源文件和postCSS編譯後的CSS文件
                src: 'src/style.css',   //  源文件
                dest: 'dest/style.css'  //  輸出文件
            }
        }
    });
    grunt.loadNpmTasks('grunt-postcss');
}

  

webpack中配置
 
配置webpack.config.js(即你的基本公用配置中)
 
module: {
  loaders: [
    {
      test: /\.css$/,
      // 若是使用了 ExtractTextPlugin
      loader: ExtractTextPlugin.extract('style', 'css!postcss')
      // 不然
      // loader: "style-loader!css-loader!postcss-loader"
    }
  ]
},
//  固然,你也能夠在根目錄下設置.postcssrc.js中添加對postCSS的配置,會自動識別。
postcss: function () {
    return [ // 裏面是咱們要用的插件
    //  自動添加前綴
    require('autoprefixer'),
    //  適配方案
    require('postcss-px-to-viewport')({
        viewportWidth: 750,
        viewportHeight: 1670,
        unitPrecision: 5,
        viewportUnit: 'vw',
        selectorBlackList: [],
        minPixelValue: 1,
        mediaQuery: false
    })
    ];
}

  

注意的是,配置postCSS插件的時候,須要提早安裝依賴。 點擊這裏。看看postCSS的強大之處吧。
針對第二套適配方案,`vw`已經普遍被移動端瀏覽器良好的支持了。因此幾乎是沒有什麼問題.
現有項目中的適配方案
現有的項目採用的適配方案,其實和第一種的原理是同樣的。
//  動態計算px的大小,好比設計稿的尺寸寬是750px
(function(dew){
    var winW = document.documentElement.clientWidth;
    var ratio = winW/desW;
    document.documentElement.style.fontSize = ratio * 100 + 'px';
})(750);
//在css中對根字體大小進行設置:
 
// html,body{
//     font-size:100px;
// }
// 這樣咱們在對UI給的尺寸直接除以100,就是對應的rem單位了。

  

固然,px和rem之間的轉換,能夠經過編輯器本身的插件,也能夠去配置postCSS去自動轉換。
 
總結
PostCSS是一種工具,一款已成長爲像Sass和LESS同樣主流的處理器,這一切都歸功於它的強大、速度和易用性。
 將 PostCSS 視爲後處理器,或者將其視做是預處理器的相反處理,都是一種誤導;PostCSS 有能力應對各類不一樣的使用場景,既能夠處理已經被預處理器編譯過的代碼,也能夠處理純粹的 CSS 代碼;它能夠在開發者的開發工做流中處理更多的任務
postCSS其實算不上什麼適配方案,1和3兩套方案的本質是同樣的。至於第2種適配方案,本質就是把咱們常常用的rem變成了vw視窗單位。
對於postCSS,這個東西帶給了我不少新的關於web自動化流程的設計感想。他能夠實現不少咱們針對CSS方面兼容性的處理。事實上頁面的佈局老是使人蛋疼的。但技術是不斷革新的,咱們能夠隨着保持對新技術的關注,嘗試這些新特性運用到實際項目中,只有這樣,咱們解決問題的方案纔會愈來愈完善。
相關文章
相關標籤/搜索