再谈移动端适配

本文首发于 https://blog.lenconda.top/posts/2018/04/11/mobile_adjust_again/,转载请注明出处。

引言

移动端适配一向是很令人头大的问题,因为随着移动设备型号数量的爆发式增长,手机屏幕尺寸越来越多样化,网页内容自适应屏幕尺寸进行显示的需求也就越来越强烈。原本可能通过百分比/媒体查询等简单手段就可以常见的适配问题,但是对于页面有复杂结构或者视觉上有特殊要求的,就需要通过其他手段来解决了。

像素基础

像素

像素是一个老生常谈的问题了。不论是做前端开发还是做UI设计,都离不开这个话题。其实真要深究起来,像素是一个十分复杂的概念。追溯到上世纪6、70年代,计算机的输出设备还是点阵式打印机,如何使打印机打印出文字和图形?科学家们研究出了很多点组成的阵列,通过控制每一个点的黑白,最终组成文字和图形。现代计算机的显示器也借鉴了这个设计,发明了像素。
像素分为两种:

物理像素

又称设备像素(Device Pixel, DP),这是组成显示设备的最小单位。可以理解为显示器上的一个一个的点,这些点组成一个个阵列。因为这些点间隔太短,排布太密集,所以肉眼观察不到颗粒感,物理像素通过RGB显色系统,分别控制RGB三基色通道的明与暗,形成了各种颜色。这就是所谓的视觉欺骗效果。任何显示设备的物理像素的数量都是不变的,出厂前就已经设定好。
物理像素的单位是pt,计算公式为:

1pt = 1 / 72 inch

设备独立像素

设备独立像素(Density-independent Pixel, DIP)又称密度无关像素,可以认为是计算机坐标系统中的一个点,这个点代表一个可以由程序使用的虚拟像素。所以它是一种抽象出的逻辑像素。前端开发中用到的CSS像素(px像素及px衍生单位像素)就是一种典型的设备独立像素。这种像素有决定因素——PPI或DPI。

再谈移动端适配_第1张图片
image

PPI

PPI名为每英寸像素。它是一个表示打印图像或显示器单位面积上像素数量的指数。一般用来计量电脑显示器,电视机和手持电子设备屏幕的精细程度。通常情况下,每英寸像素值越高,屏幕能显示的图像也越精细。
我们通常可以在手机的参数列表中发现名为“屏幕尺寸”的参数,比如说5.5inch。那么这个究竟是什么概念呢?这其实是手机对角线的长度,采用英寸为单位。
PPI的计算可以采用如下公式:
[图片上传失败...(image-25ca44-1550330376113)]

其中:

dp为屏幕对角线的分辨率
wp为屏幕横向分辨率
hp为屏幕纵向分辨率
di为屏幕对角线的长度(单位为英寸)

DP-DIP关联

我们已经了解到,前端工程师口中常提到的“px、em”等单位,实际上是计算机软件系统虚拟抽象出的一种概念,但因为它们是逻辑意义上的,人们可以轻松理解,所以这种像素在前端开发和平面设计中被广泛应用。那么,物理像素又是怎么和设备独立像素联系起来的呢?于是我们引出了设备像素比(Device Pixel Ratio, DPR)的概念。DPR与DP和DIP存在如下转换关系:

设备像素比(DPR) = 物理像素(DP) / 设备独立像素(DIP)

基于以上的转换关系,通过DPR,设备独立像素便可以转换成显示设备能够读懂的物理像素,并根据编码控制物理像素点的明暗变化,从而显示图像。

视口基础(搬运)

视口的概念相当复杂,想要完全搞清楚也是不太容易的,我对这个也没有做深入的研究,所以请参阅:CSS像素、物理像素、逻辑像素、设备像素比、PPI、Viewport

移动端适配的历史

无适配

这是较早期的移动端网页的形态——几乎没有哪个网站会针对移动设备进行,除非有特殊需求或者用户跨平台范围特别广的。在我的印象中,我读初中的时候(2013年左右),连百度都没有移动端适配,还要手动缩放。为了验证这个说法,特意去https://archive.org上选取了2013年7月31日百度新闻的截图:

再谈移动端适配_第2张图片
image

ViewPort缩放

以最小的iPhone 4/5的宽度(320px)为基准,还原视觉稿。

 
  
再谈移动端适配_第3张图片
image

除Opera Mini全版本和IE低版本不支持之外,其他的浏览器基本上都已经支持vw了。

实现

兼容性不至于特别差,因此我们可以进行下一步的实现。

根据Flexible的实现原理,我们类比出直接使用CSS对根元素样式进行修改:

html {
  font-size: 10vw !important;
}

这样一来,htmlfont-size的值就变成视口宽度的10%,达到了和Flexible相同的效果。但是,我发现如果使用宽屏移动设备(例如iPad、Nexus平板等平板设备)时,Web组件将会变的很大很大,并不是很美观。于是,我发现Flexible在视口宽度大于等于540px时,基础字体大小将会保持54px。于是,在CSS中添加一个媒体查询:

@media (min-width: 540px) {
  html {
    font-size: 54px !important; /*no*/ /*这个no注释主要是为了防止px2rem将px转换成rem*/
  }
}

在查询到的视口宽度大于540px时,htmlfont-size将被固定为54px。接下来的步骤,就和淘宝Flexible的操作一模一样了。

另外,根据bug测试的结果来看,当flexible.css结合normalize.css使用时,buttontextareainput等元素的字体大小可能超大,这是因为在normalize.css的第258行将font-size的值设成了100%从而导致问题的发生。

针对这个bug,我建议在flexible.css末尾加上这段代码:

button,
input,
optgroup,
select,
textarea {
  *font-size: 100%;
}

注意:如果要结合normalize.css使用,normalize.css必须在flexible.css之前引入

至此,这个方案已经被完整实现了,暂且称它为flexible.css。完整代码如下:

flexible.css

html {
  font-size: 10vw !important;
}
@media (min-width: 540px) {
  html {
    font-size: 54px !important; /*no*/
  }
}
button,
input,
optgroup,
select,
textarea {
  font-size: initial;
  *font-size: 100%;
}

使用时,最好在较前的代码中引入。

VW适配

这种适配方法和REM适配类似,值是将CSS中的所有px单位转换成vw单位,从而达到移动端适配的目的。这个适配方法我还没有作过详细的研究,在这篇文章中就不详细描述了。参考文章:如何在Vue项目中使用vw实现移动端适配

参考

[1]. 使用Flexible实现手淘H5页面的终端适配
[2]. 移动端前端适配方案对比
[3]. 移动端适配方案(上)
[4]. 简单粗暴的移动端适配方案 - REM
[5]. 移动端Web页面适配方案
[6]. 动态rem解决移动前端适配
[7]. Can I USE
[8]. CSS的值和单位 - 学习 Web 开发 | MDN
[9]. CSS像素、物理像素、逻辑像素、设备像素比、PPI、Viewport

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