移动端适配

一、基础概念

1. 英寸

一般用英寸描述屏幕的物理大小,如电脑显示器的17、22,手机显示器的4.8、5.7等使用的单位都是英寸。需要注意,上面的尺寸都是屏幕对角线的长度。

英寸和厘米的换算:1英寸 = 2.54 厘米

2. 分辨率

  • 2.1 像素

    像素是指由图像的小方格组成的,这些小方块都有一个明确的位置和被分配的色彩数值,小方格颜色和位置就决定该图像所呈现出来的样子。(ps上图像放大之后可以看到的像素点)

    lADPDeC2uQ_d2rbMyMzI_200_200.jpg

  • 2.2 屏幕分辨率

    屏幕分辨率指一个屏幕具体由多少个像素点组成,当然分辨率高不代表屏幕就清晰,屏幕的清晰程度还与尺寸有关。

  • 2.3 图像分辨率

    我们通常说的图片分辨率其实是指图片含有的像素数,比如一张图片的分辨率为800 x 400。这表示图片分别在垂直和水平上所具有的像素点数为800和400。
    同一尺寸的图片,分辨率越高,图片越清晰。

3. 设备独立像素

上面描述的都是物理像素,是设备上真实的物理单元。随着设备分辨率越来越高,同样大小的图片和文字,使用物理像素现实的话将会越来越小


16ac3a6576e564d5.png

乔布斯首次提出了Retina Display(视网膜屏幕)的概念,不管分辨率多高,他们所展示的界面比例都是基本类似的。
在iPhone4使用


16ac3a65a53a177e.png

的视网膜屏幕中,把2x2个像素当1个像素使用,这样让屏幕看起来更精致,但是元素的大小却不会改变

如果黑色手机使用了视网膜屏幕的技术,那么显示结果应该是下面的情况,比如列表的宽度为300个像素,那么在一条水平线上,白色手机会用300个物理像素去渲染它,而黑色手机实际上会用600个物理像素去渲染它。

我们必须用一种单位来同时告诉不同分辨率的手机,它们在界面上显示元素的大小是多少,这个单位就是设备独立像素(Device Independent Pixels)简称DIP或DP。上面我们说,列表的宽度为300个像素,实际上我们可以说:列表的宽度为300个设备独立像素。

16ac3a6609e7303b.png

打开chrome的开发者工具,我们可以模拟各个手机型号的显示情况,每种型号上面会显示一个尺寸,比如iPhone X显示的尺寸是375x812,实际iPhone X的分辨率会比这高很多,这里显示的就是设备独立像素。

  • 3.1 设备像素比
    设备像素比device pixel ratio简称dpr,即物理像素和设备独立像素的比值。

4. 视口

视口(viewport)代表当前可见的计算机图形区域。在Web浏览器术语中,通常与浏览器窗口相同,但不包括浏览器的UI, 菜单栏等——即指你正在浏览的文档的那一部分。
一般我们所说的视口共包括三种:布局视口、视觉视口和理想视口,它们在屏幕适配中起着非常重要的作用。

  • 4.1 布局视口


    16ac3a666e96ff01.png

布局视口(layout viewport):当我们以百分比来指定一个元素的大小时,它的计算值是由这个元素的包含块计算而来的。当这个元素是最顶级的元素时,它就是基于布局视口来计算的。

所以,布局视口是网页布局的基准窗口,在PC浏览器上,布局视口就等于当前浏览器的窗口大小(不包括borders 、margins、滚动条)。

在移动端,布局视口被赋予一个默认值,大部分为980px,这保证PC的网页可以在手机浏览器上呈现,但是非常小,用户可以手动对网页进行放大。

我们可以通过调用document.documentElement.clientWidth / clientHeight来获取布局视口大小。

  • 4.2 视觉视口


    16ac3a66924ef751.png

视觉视口(visual viewport):用户通过屏幕真实看到的区域。

视觉视口默认等于当前浏览器的窗口大小(包括滚动条宽度)。

当用户对浏览器进行缩放时,不会改变布局视口的大小,所以页面布局是不变的,但是缩放会改变视觉视口的大小。

例如:用户将浏览器窗口放大了200%,这时浏览器窗口中的CSS像素会随着视觉视口的放大而放大,这时一个CSS像素会跨越更多的物理像素。

所以,布局视口会限制你的CSS布局而视觉视口决定用户具体能看到什么。

我们可以通过调用window.innerWidth / innerHeight来获取视觉视口大小。
  • 4.3 理想视口


    16ac3a664842c93c.png

    布局视口在移动端展示的效果并不是一个理想的效果,所以理想视口(ideal viewport)就诞生了:网站页面在移动端展示的理想大小。

    如上图,我们在描述设备独立像素时曾使用过这张图,在浏览器调试移动端时页面上给定的像素大小就是理想视口大小,它的单位正是设备独立像素。

    上面在介绍CSS像素时曾经提到页面的缩放系数 = CSS像素 / 设备独立像素,实际上说页面的缩放系数 = 理想视口宽度 / 视觉视口宽度更为准确。

    所以,当页面缩放比例为100%时,CSS像素 = 设备独立像素,理想视口 = 视觉视口。
    我们可以通过调用screen.width / height来获取理想视口大小

  • 4.4 meta viewport

    meta元素表示那些不能由其它HTML元相关元素之一表示的任何元数据信息,它可以告诉浏览器如何解析页面。

    我们可以借助元素的viewport来帮助我们设置视口、缩放等,从而让移动端得到更好的展示效果。

    

二、移动端适配方案

1. flexible方案

flexible方案是阿里早期开源的一个移动端适配解决方案,引用flexible后,我们在页面上统一使用rem来布局。
它的核心代码非常简单:

// set 1rem = viewWidth / 10
function setRemUnit () {
    var rem = docEl.clientWidth / 10
    docEl.style.fontSize = rem + 'px'
}
setRemUnit();

rem 是相对于html节点的font-size来做计算的。

我们通过设置document.documentElement.style.fontSize就可以统一整个页面的布局标准。

上面的代码中,将html节点的font-size设置为页面clientWidth(布局视口)的1/10,即1rem就等于页面布局视口的1/10,这就意味着我们后面使用的rem都是按照页面比例来计算的。

这时,我们只需要将UI出的图转换为rem即可。

以iPhone6为例:布局视口为375px,则1rem = 37.5px,这时UI给定一个元素的宽为75px(设备独立像素),我们只需要将它设置为75 / 37.5 = 2rem。

当然,每个布局都要计算非常繁琐,我们可以借助PostCSS的px2rem插件来帮助我们完成这个过程。

下面的代码可以保证在页面大小变化时,布局可以自适应,当触发了window的resize和pageShow事件之后自动调整html的fontSize大小。

// reset rem unit on page resize
window.addEventListener('resize', setRemUnit)
window.addEventListener('pageshow', function (e) {
    if (e.persisted) {
      setRemUnit()
    }
})

由于viewport单位得到众多浏览器的兼容,上面这种方案现在已经被官方弃用:

lib-flexible这个过渡方案已经可以放弃使用,不管是现在的版本还是以前的版本,都存有一定的问题。建议大家开始使用viewport来替代此方案。

2. vw、vh方案

vh、vw方案即将视觉视口宽度 window.innerWidth和视觉视口高度 window.innerHeight 等分为 100 份。

  • vw(Viewport's width):1vw等于视觉视口的1%
  • vh(Viewport's height) :1vh 为视觉视口高度的1%
  • vmin : vw 和 vh 中的较小值
  • vmax : 选取 vw 和 vh 中的较大值


    16ac3a66a99430fc.png

如果视觉视口为375px,那么1vw = 3.75px,这时UI给定一个元素的宽为75px(设备独立像素),我们只需要将它设置为75 / 3.75 = 20vw

这里的比例关系我们也不用自己换算,我们可以使用PostCSS的 postcss-px-to-viewport 插件帮我们完成这个过程。写代码时,我们只需要根据UI给的设计图写px单位即可。

当然,没有一种方案是十全十美的,vw同样有一定的缺陷:

  • px转换成vw不一定能完全整除,因此有一定的像素差。
  • 比如当容器使用vw,margin采用px时,很容易造成整体宽度超过100vw,从而影响布局效果。当然我们也是可以避免的,例如使用padding代替margin,结合calc()函数使用等等...

以上内容参考:https://juejin.im/post/5cddf289f265da038f77696c

vue-cli 3.0+vw、vh实践

  • 创建项目

    vue create demo

  • 引入postcss-px-to-viewport

    npm install postcss-loader postcss-px-to-viewport --save-dev

将下面代码放在package.json里,然后重启服务即可

"postcss": {
    "plugins": {
      "autoprefixer": {},
      "postcss-px-to-viewport": {
        "viewportWidth": 750,
        "viewportHeight": 1334,
        "unitPrecision": 5,
        "viewportUnit": "vw",
        "selectorBlackList": [
          ".ignore"
        ],
        "minPixelValue": 1,
        "mediaQuery": false
      }
    }
}

你可能感兴趣的:(移动端适配)