注册

聊一聊移动端适配

一、引言



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



充分了解各种设备,我们会知道不同尺寸的屏幕本身就有各自的定位,像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}

举个例子:

aae57e20a7ba96b8e0732e1c2ace67d6.png























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 + 百分比


适用场景:



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

示例:





作者:_Battle
链接:https://juejin.cn/post/6999438892441026591

0 个评论

要回复文章请先登录注册