聊一聊移动端适配
一、引言
用户选择大屏幕有两个几个出发点,有些人想要更大的字体,更大的图片;有些人想要更多的内容,并不想要更大的图标;有些人想要个镜子….
充分了解各种设备,我们会知道不同尺寸的屏幕本身就有各自的定位,像ipad类的大屏设备本身相比较iphone5就应该具有更大的视野,而不是粗暴的让用户去感受老人机的体验。
但由于设计及开发资源的紧张,现阶段只能将一套设计稿应用在多尺寸设备上,因此我们需要考虑在保持一套设计稿的方案下如何使展示更加合理。
二、基本单位
对于移动端开发而言,为了做到页面高清的效果,视觉稿的规范往往会遵循以下两点:
- 首先,选取一款手机的屏幕宽高作为基准(以前是iphone4的320×480,现在更多的是iphone6的375×667)。
- 对于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}
举个例子:
vw
vw/vh
是基于 Viewport 视窗的长度单位window.innerWidth
/window.innerHeight
在CSS Values and Units Module Level 3中和Viewport相关的单位有四个,分别为vw
、vh
、vmin
和vmax
。
- 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中较大的值
可以看到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 + 百分比
适用场景:
- 追求阅读体验的场景,如列表页。
示例:
- 知乎(http://www.zhihu.com/)
- 追求阅读体验的场景,使用px布局。
- 腾讯(xw.qq.com/)
- 首页主要内容是新闻,为了更好的阅读体验,使用px布局。
作者:_Battle
链接:https://juejin.cn/post/6999438892441026591