移动端自适应方案

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' ])
  }
相关文章
相关标签/搜索