1. 程式人生 > >移動端適配方案

移動端適配方案

dev rem 單位 長度 tco create 正常的 edi alt

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方面兼容性的處理。事實上頁面的布局總是令人蛋疼的。但技術是不斷革新的,我們可以隨著保持對新技術的關註,嘗試這些新特性運用到實際項目中,只有這樣,我們解決問題的方案才會越來越完善。

移動端適配方案