说到移动端布局,大家想到的是什么解决方案呢,百分比?rem?还是 vw/vh, 最近公司的项目牵扯到了,再加上本人之前移动端适配的做的比较少,所以在这里重点记录下这个项目的解决方案,大致参考 大漠老师 的团队的思路。
我们的论点,说的并不是该如何布局,该去采用哪种布局方式,而是,有时候我们会发现,当我们在适某一机型的时候,显示上没什么问题。但是一旦我换到另外一部手机,发现出现了 模糊 的情况,尤其以图片更为显著。
视口 viewport
视窗有三个部分:
ppk大神对于移动设备上的viewport有着非常多的研究(第一篇,第二篇,第三篇),有兴趣的同学可以去看一下,本文中有很多数据和观点也是出自那里。ppk认为,移动设备上有三个viewport。
物理像素 physical pixel
物理像素又叫设备像素,显示屏是由一个个物理像素点组成的,在同一个设备上,它的物理像素是固定的,这是厂商在出厂时就设置好了的,即一个设备的分辨率是固定的。单位pt。
设备独立像素 Device Independent Pixel
也叫 逻辑像素,代表可以通过程序控制使用的虚拟像素,是一个总体概念,包括了CSS像素
css 像素
适用于web编程,指的是我们在样式代码中使用到的逻辑像素,是一个抽象概念,实际并不存在。
设备像素比 device pixel ratio
设备像素比简称为dpr,其定义了物理像素和设备独立像素的对应关系。它的值可以按下面的公式计算得到:
设备像素比(dpr) = 物理像素 / 设备独立像素
复制代码
在JavaScript中,可以通过window.devicePixelRatio获取到当前设备的dpr。
这里举个 🌰 ,在iphone 4中,物理像素是640*960(关于其他iphone机型的物理像素可参考 这里)他的 dpr 为 2 ,所以他的 设备独立像素(逻辑像素)为 320×480 。
这里就比较容易理解了。我们之前说 逻辑像素 包括css像素,所以 css 在 iPhone4 中 1px 对应的 物理像素为 2个物理像素
为什么在 pc 中不存在布局的这些东西,其实也是存在的,我们把类似 PC 这种屏幕 叫 普通屏 因为他其实是 1px 为 对应 1个物理像素。而这种 一个逻辑像素 不对应 一个物理像素 的 屏幕就叫做 Retina屏 可以看这张图:
普通屏
Retina 屏
再来两个更直观的:
所以我们大概了解问题的答案了:
理论上来说,1个位图像素对应1个物理像素,才能等到完美清晰的展示。
rem + 缩放比例
rem 这个点就不多说了。 meta 标签大家应该都会很熟悉
<meta name = "viewport" content ="width=device-width, initial-scale=1.0">
复制代码
initial-scale 这个很有意思是就是说缩放的比例。我突然想叫他 黄金 1:1
原理其实也很简单,这里摆一张图:
所以 2 倍屏幕 的 initial-scale 是 0.5 ,3倍屏幕的 initial-scale 是 0.3333 ,对应的 rem 放大相应的倍数,就可以达到 黄金 1:1 的高清 状态了。
著名的例子有: Flexible的布局方案
vw 的横空出世
为了解决这类问题,原生的CSS,就可以做到 这种 缩放比例的控制—–vw。
我们来看为什么 :
vw是基于Viewport视窗的长度单位,这里的视窗(Viewport)指的就是浏览器可视化的区域,而这个可视区域。之前的 rem 缩放 其实就是问了解决 ideal viewport 和 dpr 做的 hack, 因此有了 vw 我们就可以 干掉 那些 dpr 判断的缩放了。 比如设计稿的宽度为 750px; 那么 100vw = 750px,即1vw = 7.5px。那么我们可以根据设计图上的像素换算成 vm 布局就可以了。这时候大家会说怎么会这么麻烦。。。算了算了,等下别跑,我们还有webpack ,我们还有loader,还有 。。。postcss
这里参考 大漠老师的 这篇文章 废话不多说,先列插件:
之后再 项目中的 package.json 中添加 下列配置
"postcss": {
"plugins": {
"autoprefixer": {},
"postcss-import": {},
"postcss-url": {},
"postcss-aspect-ratio-mini": {},
"postcss-cssnext": {},
"postcss-px-to-viewport": {
"viewportWidth": "750", //视窗的宽度,对应的是我们设计稿的宽度,一般是750
"unitPrecision": "3",//指定`px`转换为视窗单位值的小数位数(很多时候无法整除)
"viewportUnit": "vw", //指定需要转换成的视窗单位,建议使用vw
"selectorBlackList": [ //指定不转换为视窗单位的类,可以自定义,可以无限添加,建议定义一至两个通用的类名
".ignore",
".hairlines"
],
"minPixelValue": 1, // 小于或等于`1px`不转换为视窗单位
"mediaQuery": false// 允许在媒体查询中转换`px`
},
"cssnano": {
"preset": "advanced",
"autoprefixer": false,
"postcss-zindex": false //只要启用了这个插件,z-index的值就会重置为1,一定关闭
}
}
},
复制代码
然后就可以开心的写代码了。比如设计稿给定多少像素就写多少。postcss 会自动帮你计算 应当转换为 多少 vw 。贴个图吧
编译后的: