移動端自適應方案

1.背景知識

首先是看幾篇文章,瞭解viewport scale dpr 圖片的顯示精度問題 一像素顯示問題, 縮放致使的像素適應問題 移動端的自適應問題
http://www.cnblogs.com/520yan...javascript

http://www.cnblogs.com/520yan...css

https://mp.weixin.qq.com/s?__...html

https://github.com/amfe/artic...java

一、圖片精度問題

其實圖片顯示高清的問題,最理想的方案是根據dpr去加載不一樣精度的圖片,可是通常這個工做效果不是很明顯,直接顯示精度大的圖片就能夠了,雖然在dpr是1的屏幕上會費流量、有點色差 可是徹底能夠忽略。
因此圖片這個問題還好。webpack

二、 1px顯示的問題

1px顯示的問題,利用縮放解決
通常設計給的設計稿都是針對iphone6的750px 1334px ,可是iphone6的設備獨立像素是375px667px iphone6的dpr=2git

因此若是咱們把viewport設成375px的話,就沒法顯示設計稿中1px的元素。
因此爲了顯示1px,咱們須要將viewport設成750px,而後設置scale=0.5,這樣手機屏幕仍是完整的顯示頁面,而且使得css中的px
和手機物理設備的px相同了。github

三、scale縮放致使的像素適應問題

可是scale的縮放會影響原來的像素大小,好比在scale=1時,一個元素應該是12px 可是scale=0.5時,總體頁面縮小了1倍,這個元素的大小應該是24px,才能和原來顯示同樣。web

四、利用rem解決像素適應的問題,

在dpr=2的時候設html的font-size=100px,在dpr=1的時候設置font-size=50。而後須要在不一樣dpr下顯示不一樣px的地方就能夠以rem爲單位進行設置。
那麼爲何把dpr=2的時候設置font-size=100, 由於設計稿給的是iphone6 dpr=2的狀況下的像素,因此根據設計稿換算起來比較簡單,好比設計稿中font-size: 24px。咱們能夠直接寫font-size:0.24rem。 這樣在dpr=2的時候顯示成24px 在dpr=1的時候顯示成12px。gulp

五、如何解決移動端的自適應問題

主要是移動端的屏幕尺寸比較多,如何在各類屏幕寬度下顯示的更好,更一致問題。
比較簡單的辦法就是百分比或者flex。sass

之後深刻研究下百分比和flex的使用。
好比750px,咱們能夠把全部元素flex的總和設成750px,好比左邊flex 300 右邊 flex450 就是 300比450的自適應。
百分比要注意的是他所設置的百分比 是父元素的寬度爲基礎的。

而後還要考慮的是高度的問題,高度怎麼去適應。圖片的話高度會隨着寬度等比例縮放。

用rem解決自適應的問題,是個很是精確的解決方案,可以將高度和寬度都作到隨着屏幕的寬度徹底的等比縮放,可是缺點就是開發起來效率低點。來看看如何操做。

首先仍是會根據dpr 來設置viewport的寬度和scale的縮放級別
而後設計成頁面的寬度是10rem,
1rem = 頁面寬度/10 = device-width * dpr /10;
以iphone6爲例
1rem = 375 * 2 /10 = 75px;
因此設
html {
font-size = 75px;
}
而後把html加一個屬性data-dpr = 2;

示例代碼以下:

javascript方式,經過上面的公式,計算出基準值rem,而後寫入樣式,大概以下(代碼參考自kimi的m-base模塊)
var dpr, rem, scale;
var docEl = document.documentElement;
var fontEl = document.createElement('style');
var metaEl = document.querySelector('meta[name="viewport"]');

dpr = window.devicePixelRatio || 1;
rem = docEl.clientWidth * dpr / 10;
scale = 1 / dpr;

// 設置viewport,進行縮放,達到高清效果
metaEl.setAttribute('content', 'width=' + dpr * docEl.clientWidth + ',initial-scale=' + scale + ',maximum-scale=' + scale + ', minimum-scale=' + scale + ',user-scalable=no');

// 設置data-dpr屬性,留做的css hack之用
docEl.setAttribute('data-dpr', dpr);

// 動態寫入樣式
docEl.firstElementChild.appendChild(fontEl);
fontEl.innerHTML = 'html{font-size:' + rem + 'px!important;}';

// 給js調用的,某一dpr下rem和px之間的轉換函數
window.rem2px = function(v) {
    v = parseFloat(v);
    return v * rem;
};
window.px2rem = function(v) {
    v = parseFloat(v);
    return v / rem;
};

window.dpr = dpr;
window.rem = rem;

這樣的實現,就可以徹底的將設計稿中的px對應成rem,而且可以根據屏幕的寬度進行自適應。
有兩個問題:
第一個問題是設計稿到rem的轉換下降開發效率
好比設計稿750px,1rem = 75px。 設計稿上的50px,咱們須要計算出50/75 rem
第二個問題是 rem設置成device-width的10分之一,縮放引發的字體的大小變化就不能用rem來解決了
由於咱們通常只是想在不一樣縮放下,一塊兒縮放字體,而字體不須要自適應。
字體應該是在任何屏幕上字體都應該保持一致。

先說第二個問題:
這個就能夠利用CSS實現
思路 由於已經在html上設置data=dpr

font-size: 16px;
[data-dpr="2"] input {
  font-size: 32px;
}

能夠用sass寫成一個mixin

@mixin dpr($property, $value) {
    & {
        #{$property}: $value / 2; /* no */
    }

    [data-dpr="2"] & {
        #{$property}: $value; /* no */
    }

    [data-dpr="3"] & {
        #{$property}: $value * 1.5; /* no */
    }
}

@mixin font-size($fontSize) {
    @include dpr(font-size, $fontSize);
}

這樣用的地方能夠這樣寫
@include font-size(52px);

再說第一個問題px到rem的轉換問題
淘寶的rem庫,lib-flexible
https://github.com/amfe/artic...
這篇文章裏說了幾種方法
有sublime的插件,有sass的處理函數,有gulp的插件,
咱們如今都用webpack作開發,和打包,因此用一個webpack的插件px2rem-loader
這個插件能夠實現咱們直接寫px 打包的時候自動轉換成rem
CSS的loader中加入px2rem插件

const REM_UNIT = 75;
 let px2rem = `px2rem?remUnit=${REM_UNIT}&remPrecision=8&threeVersion=true`;
  return {
    css: generateLoaders([ 'css' , px2rem]),
    postcss: generateLoaders([ 'css' , px2rem]),
    less: generateLoaders([ 'css', px2rem , 'less' ]),
    sass: generateLoaders([ 'css', px2rem , 'sass?indentedSyntax' ]),
    scss: generateLoaders([ 'css', px2rem , 'sass' ]),
    stylus: generateLoaders([ 'css', px2rem , 'stylus' ]),
    styl: generateLoaders([ 'css', px2rem, 'stylus' ])
  }
相關文章
相關標籤/搜索