聊一聊移动端适配

6,314 阅读6分钟

这是我参与8月更文挑战的第17天,活动详情查看:8月更文挑战

一、引言

用户选择大屏幕有两个几个出发点,有些人想要更大的字体,更大的图片;有些人想要更多的内容,并不想要更大的图标;有些人想要个镜子….

充分了解各种设备,我们会知道不同尺寸的屏幕本身就有各自的定位,像ipad类的大屏设备本身相比较iphone5就应该具有更大的视野,而不是粗暴的让用户去感受老人机的体验。

但由于设计及开发资源的紧张,现阶段只能将一套设计稿应用在多尺寸设备上,因此我们需要考虑在保持一套设计稿的方案下如何使展示更加合理。

二、基本单位

对于移动端开发而言,为了做到页面高清的效果,视觉稿的规范往往会遵循以下两点:

  1. 首先,选取一款手机的屏幕宽高作为基准(以前是iphone4的320×480,现在更多的是iphone6的375×667)。
  2. 对于retina屏幕(如: dpr=2),为了达到高清效果,视觉稿的画布大小会是基准的2倍,也就是说像素点个数是原来的4倍(对iphone6而言:原先的375×667,就会变成750×1334)。

物理像素(physical pixel)

一个物理像素是显示器(手机屏幕)上最小的物理显示单元,在操作系统的调度下,每一个设备像素都有自己的颜色值和亮度值。

设备独立像素(density-independent pixel)

设备独立像素(也叫密度无关像素),可以认为是计算机坐标系统中得一个点,这个点代表一个可以由程序使用的虚拟像素(比如: css像素),然后由相关系统转换为物理像素。

所以说,物理像素和设备独立像素之间存在着一定的对应关系,这就是接下来要说的设备像素比。

DPR 设备像素比(device pixel ratio )

设备像素比 = 物理像素 / 设备独立像素; // 在某一方向上,x方向或者y方向 可以在JS中 window.devicePixelRatio获取到当前设备的dpr

三、常见的布局类型

rem 布局

原理: 根据手机的屏幕尺寸 和dpr,动态修改html的基准值(font-size)

公式: rem = document.documentElement.clientWidth * dpr / 100

注释: 乘以dpr,是因为页面有可能为了实现1px border页面会缩放(scale) 1/dpr 倍(如果没有,dpr=1)

假设我们将屏幕宽度平均分成100份,每一份的宽度用per表示,per = 屏幕宽度 / 100,如果将per作为单位,per前面的数值就代表屏幕宽度的百分比

p {width: 50per;} /* 屏幕宽度的50% */

如果想要页面元素随着屏幕宽度等比变化,我们需要上面的per单位,如果子元素设置rem单位的属性,通过更改html元素的字体大小,就可以让子元素实际大小发生变化

html {font-size: 16px}
p {width: 2rem} /* 32px*/
 
html {font-size: 32px}
p {width: 2rem} /*64px*/

如果让html元素字体的大小,恒等于屏幕宽度的1/100,那1rem和1per就等价了

html {fons-size: 元素宽度 / 100}
p {width: 50rem} /* 50rem = 50per = 屏幕宽度的50% */

实际应用

rem作用于非根元素时,相对于根元素字体大小;rem作用于根元素字体大小时,相对于其初始字体大小

可以看出 rem 取值分为两种情况,设置在根元素时和非根元素时,举个例子:

/* 作用于根元素,相对于原始大小(16px),所以html的font-size为32px*/
html {font-size: 2rem}
 
/* 作用于非根元素,相对于根元素字体大小,所以为64px */
p {font-size: 2rem}

举个例子:

设计稿宽度设计搞中元素宽度
320px50px
480px75px
640px100px

元素在设计稿中占比:100 / 640 = 75 / 480 = 50 / 320 = 15.625

下面的表格是元素在不同屏幕宽度下的计算值

页面宽度html字体大小(1rem)p元素宽度
320px320/100=3.2px15.625*3.2=50px
480px480/100=4.8px15.625*4.8=75px
640px640/100=6.4px15.625*6.4=100px

开发时使用px进行开发,项目在css生效前将px都换算为 rem。

vw

vw/vh是基于 Viewport 视窗的长度单位window.innerWidth/window.innerHeight 在CSS Values and Units Module Level 3中和Viewport相关的单位有四个,分别为vwvhvminvmax

  • vw:是Viewport’s width的简写, 1vw等于window.innerWidth的1%
  • vh:和vw类似,是Viewport’s height的简写,1vh等于window.innerHeihgt的1%\
  • vmin:vmin的值是当前vw和vh中较小的值
  • vmax:vmax的值是当前vw和vh中较大的值

image.png 可以看到vw其实是实现了1vw = 1per,比起rem需要计算html的基准值,vw无疑更加方便。

/* rem方案 */
html {fons-size: width / 100}
p {width: 15.625rem}
 
/* vw方案 */
p {width: 15.625vw}

Q:vw如此方便,是不是就比rem更好,可以完全取代rem了呢?

A:当然不是。

vw也有缺点。

  • vw换算有时并不精确,较小的像素不好适配,就像我们可以用较小值精确地表示较大值,用较大值表示较小值就可能存在数位换算等问题而无法精确表示。
  • vw的兼容性不如rem
  • 使用弹性布局时,vw无法限制最大宽度。rem可以通过控制HTML基准值,来实现最大宽度的限制。

Q:rem就如此完美吗?

A:rem也并不是万能的

  • rem的制作成本更大,需要使用额外的插件去实现。
  • 字体不能用rem,字体大小和字体宽度不成线性关系,所有字体大小不能使用rem,由于设置了根元素字体的大小,会影响所有没有设置字体的元素,因此需要设置所有需要字体控制的元素。
  • 从用户体验上来看,文字阅读的舒适度跟媒体介质大小是没关系的。

四、适配方案

方案一: rem/vw

适用场景:

  • 对视觉组件种类较多,视觉设计对元素位置的相对关系依赖较强的移动端页面:vw/rem

示例:

  • 饿了么(h5.ele.me/msite/)
  • 对viewport进行了缩放
  • html元素的font-size依然由px指定
  • 具体元素的布局上使用vw + rem fallbak的形式
  • 没有限制布局宽度
  • css构建过程需要插件支持

方案二: flex + px + 百分比

适用场景:

  • 追求阅读体验的场景,如列表页。

示例:

  • 知乎(www.zhihu.com/)
  • 追求阅读体验的场景,使用px布局。
  • 腾讯(xw.qq.com/)
  • 首页主要内容是新闻,为了更好的阅读体验,使用px布局。

点赞支持、手留余香、与有荣焉,动动你发财的小手哟,感谢各位大佬能留下您的足迹。

往期精彩推荐

前端性能优化实战

聊聊让人头疼的正则表达式

获取文件blob流地址实现下载功能

Git 相关推荐

通俗易懂的 Git 入门

git 实现自动推送

我在工作中是如何使用 git 的

面试相关推荐

前端万字面经——基础篇

前端万字面积——进阶篇

更多精彩详见:个人主页