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

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

首先说问题

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

基本概念

视口 viewport前端

视窗有三个部分:vue

  • 可视视口(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。html5

物理像素 physical pixelwebpack

物理像素又叫设备像素,显示屏是由一个个物理像素点组成的,在同一个设备上,它的物理像素是固定的,这是厂商在出厂时就设置好了的,即一个设备的分辨率是固定的。单位pt。git

设备独立像素 Device Independent Pixelgithub

也叫 逻辑像素,表明能够经过程序控制使用的虚拟像素,是一个整体概念,包括了CSS像素web

css 像素编程

适用于web编程,指的是咱们在样式代码中使用到的逻辑像素,是一个抽象概念,实际并不存在。

设备像素比 device pixel ratio

设备像素比简称为dpr,其定义了物理像素和设备独立像素的对应关系。它的值能够按下面的公式计算获得:

设备像素比(dpr) = 物理像素 / 设备独立像素
复制代码

在JavaScript中,能够经过window.devicePixelRatio获取到当前设备的dpr。

这里举个 🌰 ,在iphone 4中,物理像素是640*960(关于其余iphone机型的物理像素可参考 这里)他的 dpr 为 2 ,因此他的 设备独立像素(逻辑像素)为 320x480 。

这里就比较容易理解了。咱们以前说 逻辑像素 包括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 。贴个图吧

编译后的:

结语

最后,其实还有一些问题,会有 1px 的经典问题,这里埋个伏笔吧。你们有好的方案能够提出来,我也是半路出家,因此有不一样见解的欢迎讨论。分享无罪,欢迎组队。双压,哈哈哈碎觉

相关文章
相关标签/搜索