首先是看几篇文章,了解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显示的问题,利用缩放解决
通常设计给的设计稿都是针对iphone6的750px 1334px ,可是iphone6的设备独立像素是375px667px iphone6的dpr=2git
因此若是咱们把viewport设成375px的话,就没法显示设计稿中1px的元素。
因此为了显示1px,咱们须要将viewport设成750px,而后设置scale=0.5,这样手机屏幕仍是完整的显示页面,而且使得css中的px
和手机物理设备的px相同了。github
可是scale的缩放会影响原来的像素大小,好比在scale=1时,一个元素应该是12px 可是scale=0.5时,总体页面缩小了1倍,这个元素的大小应该是24px,才能和原来显示同样。web
在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' ]) }