Better

Ethan的博客,欢迎访问交流

响应式设计与移动端适配

之前有尝试过使用flexible.js移动端适配的解决方案,当时并未理解到精髓,导致在最近的开发中,有点触碰到知识盲区的感觉,折腾了一阵子才整清楚。

基本概念

设备像素比(dpr) = 物理像素 / 设备独立像素

在不同的屏幕上,CSS像素所呈现的物理尺寸是一致的,而不同的是CSS像素所对应的物理像素具数是不一致的。在普通屏幕下1个CSS像素对应1个物理像素,而在Retina屏幕下,1个CSS像素对应的却是4个物理像素。

meta标签:<meta>标签有很多种,而这里要着重说的是viewport的meta标签,其主要用来告诉浏览器如何规范的渲染Web页面,而你则需要告诉它视窗有多大。

rem:rem就是相对于根元素<html>的font-size来做计算。

flexible原理

flexible:会在<html>元素上增加一个data-dpr属性,以及一个font-size样式。JS会根据不同的设备添加不同的data-dpr值,比如说2或者3,同时会给html加上对应的font-size的值。

在引入lib-flexible需要执行的JS之前,可以手动设置meta来控制dpr值

<meta name="flexible" content="initial-dpr=2" />

如果手动设置了dpr之后,不管设备是多少的dpr,都会强制认为其dpr是你设置的值。在此不建议手动强制设置dpr,因为在Flexible中,只对iOS设备进行dpr的判断,对于Android系列,始终认为其dpr为1。

flexible的实质

  • 动态改写<meta>标签
  • <html>元素添加data-dpr属性,并且动态改写data-dpr的值
  • <html>元素添加font-size属性,并且动态改写font-size的值

如何计算scale

scale = 1 / dpr
dpr = 1 / scale

flexiable具体逻辑

  1. 如果本身设置了viewport,则根据已有的meta设置比例
  2. 你也可以自定义 name = flexible 的meta,自己设置比例 dpr
  3. 如果都没有则根据navigator属性自动设置,具体规则为
    • ios根据window.devicePixelRatio设置dpr为1,2,3
    • android 直接使用dpr=1
  4. 在HTML根标签上设置data-dpr
  5. 如果本身没有设置viewport,动态创建meta标签,并写入scale
  6. 根据实际宽度,动态设置html的font-size
    • 移动设备的实际尺寸最大按640计算
    • remUnit(rem基准值,即1rem为多少px,也就是HTML的font-size)为 width / 10

浏览器的缩放会影响 devicePixelRatio 的值

px转换成rem

如果设计稿是750px大小,目前Flexible会将视觉稿分成100份(主要为了以后能更好的兼容vh和vw),而每一份被称为一个单位a。同时1rem单位被认定为10a,<html>对应的font-size为75px,具体的rem值 = 原始px值除以rem基准值即可。

1a   = 7.5px
1rem = 75px 

快速转换,利用工具:Sass、Less以及PostCSS这样的处理器。

字号不使用rem

经过flexible处理后的页面,你可以理解成一张照片,在大屏和小屏的显示是一致的。但有时候对于与段落文本,我们可能并不想这样,比如我们不希望文本在Retina屏幕下变小,另外,我们希望在大屏手机上看到更多文本。

如此一来,就决定了在制作H5的页面中,rem并不适合用到段落文本上。所以在Flexible整个适配方案中,考虑文本还是使用px作为单位。只不过使用[data-dpr]属性来区分不同dpr下的文本字号大小。

div { width: 1rem; height: 0.4rem; font-size: 12px; // 默认写上dpr为1的fontSize } 
[data-dpr="2"] div { font-size: 24px; } 
[data-dpr="3"] div { font-size: 36px; }

为什么

记住一个约定:px2rem和fleiable都约定remUnit = width / 10

在设计稿上,假定我们设置A元素宽度为w1,总宽度为w0,则对应rem=w1/remUnit=10w1/w0

在真实设备上,假定总宽度为w2,则remUnit=w2/10

因此A元素在真实设备上宽度为:10w1 / w0 * w2 / 10 = w1 * w2/ w0。这就说明了A元素的宽度会根据真实设备的宽度进行缩放。

更多



留言