屏幕适配和像素级还原视觉稿是一个老生常谈的话题了,但是具体做到了这一点的线上项目并不多,相关技术并不复杂,只是老项目一但成形,改造成本不亚于重构整个项目。但是我们应该在新的项目中去实践这种技术,更好的还原视觉稿。
现有适配的方案
- 百分比布局 / Flex 布局
不同的屏幕宽度下布局不一致,宽屏下会布局被拉长,1px的边框使用hack的方式实现,例如:天猫 - 查询+REM
一定范围内固定的根字体大小,并不能完全适配所有手机屏幕,特别是Android手机,1px通过hack方式实现 - REM 布局
能保持布局一致,但高清适配需要结合其它方案,如:小米 - REM布局 + Flex布局 + 视口缩放
能灵活控制布局,也能高清适配,例如:手淘
其它布局方案及原理,这里不详细介绍了,如果有不明白的地方,请参考我之前写的 移动端高清屏适配方案
这里着重介绍如何应用实践 REM+视口缩放 的适配方案
高清适配
方案
手淘 Flexible.js 可伸缩布局方案
这两种方案都是动态的根据屏幕宽度和当前设置的DPR的值,设置根字体的大小。
首先给定一个rem参考值,比如100px,750的设计稿还原到iphone6下,就是缩放一倍,根字体大小为50px,但iphone6中DPR为2,为了适配高清,应将原来的750大小的页面缩放0.5倍,这样,按照根字体100px的标准切出来的图,在iphone6下就高清还原视觉稿了
为了适应不同的DPR和屏幕宽度就需要JS动态设置当前的viewport的缩放比例和根字体的大小了
PX转REM
由于我们动态的要的屏幕度设置了不同的根字体大小,并且需要界面随根字体大小而调整,所以需要将px单位转换为rem单位。
结合Webpack插件,安装 postcss-pxtorem 插件,自动转换px为rem,在webpack.config.js里新增pxtorem配置、代码如下:
const pxtorem = require('postcss-pxtorem');
webpackConfig.postcss.push(pxtorem({
rootValue: 100,
propWhiteList: [],
}));
rootValue 为初始根字体参照大小,
比如750的设计稿,rootValue 为 100px, 那么750设计稿中,30px 会被转换为 0.3rem
如果是采用上面 flexible.js 的方案,那么750设计稿的根字根会被计算为75px,使用 postcss-pxtorem时,rootValue 应该设置为 75px
当然也可以结合postcss的 px2rem 插件去做转换。
具体如何使用 flexible方案做适配,请查看大漠老师的教程使用Flexible实现手淘H5页面的终端适配
用来做适配的js必须在所有css引入之前加载
标注工具
Mark Man 部分功能收费
- 长度、坐标、矩形、颜色、文字标注
- 按Tab键自动测量
- 拖拽删除和调整
- 末尾是@2x的图自动缩小50%,以便测量
PxCool 免费且功能十分强大,智能标注绝对可以解放双手了,强烈推荐。
PxCool 除以上功能外还具有:
- 具有自动吸附
- 自动检测边距、字体类型、字体大小、颜色等等
这两个工具都是Adobe AIR程序,兼容Win与Mac平台
应用实践
第一步
在html模板的头部引用适配JS并执行
title
这里使用的是 antd mobile 的flex高清适配方案
第二步
使用px to rem 插件转换px
在 webpack.config.js 中添加插件
const pxtorem = require('postcss-pxtorem');
module.exports = {
entry: pageEntries,
output: {}
resolve:{}
....
postcss:[
autoprefixer({browsers:['last 2 versions']}),
pxtorem({
rootValue: 100,
propWhiteList: [],
})
]
...
}
第三步
使用标注工具标注,按照标注图上的实际尺寸编写CSS,构建时,webpack或gulp借助插件自动将px转为rem。
另外,关于图片的高清适配,可以根当前的dpr的值,借助七牛的图片处理能加,使用不同的后缀加载不同的图片即可。
关于REM的参考标准
根字体应该设定为多少,并没有一定的标准,设置的根字体大小只是rem的参考标准,比如我的设计稿是750的宽度,那么根字体设置为100px,1rem就为100px,10px就等于0.1rem,这样设计稿上的尺寸就算不借助于工具也能心算出来,14px = .14rem,40px = .4rem,设置为100px的好处是可以心算出rem的值同时减少小数位。