移动端开发不可避免的一个点就是适配问题,因为机型繁多,屏幕尺寸大不相同,以及retina屏幕致使一套固定的样式布局没法知足全部的屏幕需求,所以须要解决各类屏幕的适配问题,让页面在全部手机上看起来都合适美观。
到目前为止,在适配问题上经历了几个阶段:css
后面会针对rem适配具体说明html
物理像素
又叫设备像素,一个物理像素是屏幕上的最小显示单元,每一个像素都有本身的显示颜色和亮度,例如,屏幕上显示的一张100px*100px的图片,其实是由不少个拥有颜色和亮度的像素点组成。前端
设备独立像素
又叫作密度无关像素、逻辑像素,是由程序能够控制的虚拟像素,咱们样式中的css像素也是逻辑像素的一种。系统会将逻辑像素转化为设备像素展现。html5
设备像素比
物理像素与设备像素之间的关系就是设备像素比,dpr = 物理像素/设备独立像素。
能够经过 window.devicePixelRatio 获取设备像素比。react
即便知道了基本概念,可能也仍是不清楚他们之间到底有什么关系?有怎样的表现?如下经过简单的例子来进行理解。webpack
上图是屏幕尺寸相同,dpr分别为1和2的展现效果,最直观的视觉效果就是左侧dpr=1的显示比较模糊粗糙,右侧dpr=2的更加清晰细致,产生区别的缘由不是由于右侧的图案比左侧的大,而是在尺寸相同的状况下右侧屏幕为retina屏幕,dpr=2,这意味着,当展现一个100px*100px大小的图案时,dpr=1的屏幕上在100px*100px的区域内显示了100*100个物理像素点,用一个物理像素显示1个逻辑(css)像素,可是在dpr=2的屏幕上却展现了100*100*4个像素点,用4个物理像素展现1个逻辑(css)像素,因此图案更加清晰细腻。以下图所示:git
也能够简单的理解为,在尺寸相同,密度不一样的屏幕上展现同等大小的内容,那么密度大的就要用更多的像素去展现。这里的密度指单位面积内的像素点个数,像素点越多,分辨率越大,越清晰。github
目前流行的移动端适配方案分别为蚂蚁金服的ant-design-mobile中的高清适配方案和淘宝的flexible,可是两种方案的原理是同样的,viewport+rem,这里主要记录两种方案的使用方式,原理在下面分析。web
阿里蚂蚁金服的react组件库,在antd mobile中提供移动端高清适配方案,简单介绍下使用使用方式,在建立项目并安装antd-mobile后npm
1.安装依赖
npm install --save-dev babel-plugin-import less less-loader
2.修改webpack配置
修改配置支持按需引入,加载antd-mobile的less文件
增长配置,解析编译less,引入主题配置,这里的theme是package.json中的配置项
package.json中增长theme设置项,theme能够定制组件皮肤颜色,高清方案hd需为2px,具体参数参看antd-mobile官网,这里也有使用方式
3.px转rem
antd里px转rem方便快捷的方式是经过依赖postcss-plugin-px2rem,配置后在开发中能够直接写px单位,编译后生成px单位。
安装依赖:
npm install postcss-plugin-px2rem postcss-loader --save-dev
对.css文件作解析编译配置,增长postcss-loader配置,postcss-loader的options里增长postcss-plugin-px2rem相关配置,以下图,具体使用根据本身工程配置方式作变通:
rootValue默认设置100,即1rem = 100px;
1.引入flexible.js文件
flexible.js能够下载到本地工程引入,也能够引cdn上的远程文件,该文件执行会自动生成<meta name='viewport'> 标签,不须要手动写
2.开发使用
因为会自动生成meta标签,并自动设置html标签的font-size属性,因此只须要按照设计稿写rem单位的css便可。默认iphone6 1rem = 75px,其计算方式是1rem=document.documentElement.clientWidth*dpr/100 = 375*2/100=75px
无轮以上那种方式,在开发模式上能够用同一种,以iphone6为标准,UI出750*1334(高度不固定)的设计稿,前端开发元素大小同设计图。
px转rem有几种比较好用的方式
一、不用sass,less,直接在写css的过程当中自行计算rem,麻烦耗时而且开工做量大,若是之后改变rem对px的开发标准,那么所有须要从新计算。
二、 使用sass开发,且不用构建工具,那么可使用sass的混合宏、函数计算rem;也能够IDE安装转换插件。sass函数以下:
// px rem转换函数 @function px2rem($px, $base-font-size: 75px) { @if (unitless($px)) { @warn "Assuming #{$px} to be in pixels, attempting to convert it into pixels for you"; @return px2rem($px + 0px); } @else if (unit($px) == rem) { @return $px; } @return ($px / $base-font-size) * 1rem; }
三、 使用构建工具,能够npm安装px2rem插件
antd推荐:https://github.com/ant-tool/p...
flexible推荐:https://github.com/songsiqi/p...
移动端适配的根本在于rem+viewport
css单位由px转向rem
这里暂时不考虑retina屏幕问题,下面解析
这里说一下px、em、rem单位的区别:
1px = 1px
1em = 父元素的font-size
1rem = html标签的font-size
因为rem单位的特性,使得以rem做为单位的元素在大小等属性上具备相对性,以元素的width,height为例,根元素的font-size越大,那么元素的宽高越大,反之越小。这就意味着当咱们以iphone6为基础作rem布局:
iphone6
html: font-size = 100px div: width = 1rem = 100px height = 1rem = 100px
在 iphone6 plus 上的显示会以下,因为plus屏幕较大,html的fontSize属性等比例变大,元素尺寸一样会相应变大,这样就能够达到根据屏幕尺寸不一样,页面元素作等比例缩放,达到基本的适配目的。
html标签的fontSize的值可在页面加载的时候经过js进行计算,动态设置设置,计算方式为:
fontSize = 当前屏幕宽度/基础设备宽度*基础设备上约定的html标签fontSize
iphone6 plus
screenWidth: 414px html: font-size = 414/375*100px = 110.4px div: width = 1rem = 110.4px height = 1rem = 110.4px
以上根据屏幕尺寸计算html的fontSize值的方式可以实现的是页面在iphone6(开发基础稿)的基础上根据屏幕宽度进行简单的等比例缩放,可是却没法解决retina屏幕的问题,若是开发中以iphone6为基础,那么考虑到其dpr=2的问题,应该用宽度为750px的设计稿做为开发稿。
根据dpr作页面缩放
上面主要解释rem的适配原理,如今来解释dpr的问题。
若是忽略了dpr的不一样,会有什么样的问题呢?
最主要的问题就是展现一样的大小的内容,在dpr越大的屏幕上页面元素内容会越虚,尤为是图片和1px border的问题。
缘由是上面提到的dpr越大,一个逻辑像素对应的物理像素就越多,图片也会越清除细腻,反之越粗糙模糊。之因此会虚是由于展现100px*100px的图片,dpr=1的屏幕一个物理像素展现一个逻辑像素;dpr=2的屏幕四个物理像素展现1个逻辑像素,四个物理像素如何展现一个逻辑像素呢,系统在计算的时候,会把一个逻辑像素补充为4个色值,透明度等近似的逻辑像素点,这样图片展现就会显得虚。
1.antd iphone6 1rem = 100px 6p 1rem=150rem 设置width:7.5rem,6上宽度100%,6p上没法显示宽度100%,