Categories: 工作

vue/cli3.0里面把px转rem,vw,vh

浅谈移动端 css 适配解决方案 (附 Vue-cli3 中使用)

说到移动端布局,大家想到的是什么解决方案呢,百分比?rem?还是 vw/vh, 最近公司的项目牵扯到了,再加上本人之前移动端适配的做的比较少,所以在这里重点记录下这个项目的解决方案,大致参考 大漠老师 的团队的思路。

首先说问题

我们的论点,说的并不是该如何布局,该去采用哪种布局方式,而是,有时候我们会发现,当我们在适某一机型的时候,显示上没什么问题。但是一旦我换到另外一部手机,发现出现了 模糊 的情况,尤其以图片更为显著。

基本概念

视口 viewport

视窗有三个部分:

  • 可视视口(Visual viewport)。 顾名思义,就是用户可以看到的窗口,通过滚动缩放去改变可视窗口的大小,visual viewport的宽度可以通过window.innerWidth
  • 布局视口(Layout viewport)。 这里说 CSS,CSS布局(尤其是百分比宽度)是相对于布局视口计算的,布局视口比视觉视口宽得多,你可以放大缩小或者滚动可是窗口,但是布局窗口的元素大小和形状是不变的。这个layout viewport的宽度可以通过 document.documentElement.clientWidth 来获取
  • 理想视口 (ideal viewport) 。关于不同的设备ideal viewport的宽度都不同,可以到http://viewportsizes.com去查看一下,里面收集了众多设备的理想宽度。

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

VUE 中的实战方案

这里参考 大漠老师的 这篇文章 废话不多说,先列插件:

之后再 项目中的 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 。贴个图吧

编译后的:

Kai

Share
Published by
Kai

Recent Posts