什么是适配?
适配就是将设计图原封不动的展示到不同的手机上。所以可以得到公式 手机屏幕宽 / 设计图的宽(750)= 手机上的物理像素(物理像素) / 设计图的像素(px)
根据公式,物理像素 = 手机屏幕宽 / 750 * px
px可以根据设计图直接亮出来
手机屏幕宽可以根据 dom元素的方法 getBoundingClientRect().width 获得。
不过移动端有meta标签,也可以控制手机屏幕的宽度。
<meta name="viewport" content="width=device-width,initial-scale=1.0">
这个标签的intial-scale属性可以控制页面首次被显示时的缩放级别,
如果填写1则按照实际尺寸显示,无任何缩放,那么getBoundingClientRect().width 方法获取的尺寸就是屏幕的宽度。
如果填写2则会将实际尺寸放大2倍,那么getBoundingClientRect().width 方法获取的尺寸 * 2 才是屏幕的宽度
所以屏幕的真实宽度计算公式应为 getBoundingClientRect().width * intial-scale
使用scale就可以画出1px的线
flexible
flexible是手淘的适配方式,它的主要思想是
根据dpr控制scale来使页面进行放缩,目的是为了画出1px的线
根据dpr的值设定HTML的font-size值,使页面根据rem进行适配
参考:https://www.w3cplus.com/mobile/lib-flexible-for-html5-layout.html
px自动转换成rem:
postcss-pxtorem、px2rem-loader
1:概念
visual viewport / layout viewport = 屏幕宽度 / dom宽度 = 物理像素 / 逻辑像素 = dpr
以下是对这个公式的解释:
逻辑像素(px):相当于dom宽度的最小单位
物理像素:相当于屏幕宽度的最小单位
visual viewport 可见视口 屏幕宽度
layout viewport 布局视口 DOM宽度
ideal viewport 理想适口:dom宽度等于屏幕宽度,使用vw适配的原理就是使布局宽度和屏幕宽度一样宽,以此答到理想视口
visual viewport = layout viewport * dpr
scale是在meta标签中设置的
设备像素比 dpr:
(这里不对dpr进行解释)
当dpr 等于1时 1物理像素就等于1px 也就是说一个物理像素上面放1个px,
所以当dpr等于1时,屏幕宽度就是dom宽度
当dpr等于2时 2物理像素等于1px
所以当dpr等于2时,屏幕宽度就是一半的dom宽度。而为了使dpr=2与dpr=1时显示相同的效果(这个才是页面适配的目的),可以将页面缩小0.5,也就是逻辑像素缩小0.5,而这个0.5其实就是scale,所以根据公式visual viewport(物理像素) = layout viewport(px) * dpr 可以得出,当dpr等于2时,dom宽度为屏幕宽度的2倍
总结:屏幕宽度与dom元素的宽度比值就等于物理像素与逻辑像素的比值。当dpr等于1时,1物理像素就是1逻辑像素,当dpr等于2时,2物理像素等于1逻辑像素。
为了使多个终端显示效果一样,当dpr大于1时,可以将逻辑像素缩小。而这个比例,也就是屏幕宽度与dom宽度的比值
2:前端适配
从上面可以知道,适配的关键在于scale这个属性,也就是将逻辑像素缩小dpr。可以使用meta标签设置这个属性
<meta name="viewport" content="width=width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
rem与em
rem与em和px相似,都是css的单位。具体关系如下:
1rem = html标签的font-size的值。
例子:
html的font-size为10px
那么当某个子元素的宽度为20px=2rem
使用rem的优点就是当font-size的值变化时,所有已rem为单位的属性会同时变化。
根据这个原理,根据不同屏幕尺寸的终端,给根元素的font-size的值不同的值,便可以实现屏幕适配
em和rem相似,区别就是em是按照父元素的font-size为基准进行换算的,默认是body。
推荐使用rem,因为rem的基准是唯一的,而em是可变的。
flexible库
上面都是一些概念性的知识,有助于理解H5页面适配的原理。实际开发中可以使用flexible这个库。这个是淘宝团队适配页面使用的。但是我在GitHub上看源码好像不是太对。也许有可能是我没找到。下面只是说下我对这个库的理解,具体可以看
https://github.com/amfe/lib-flexible
这个库的原理:
1:获取当前的dpr,然后根据dpr设置meta标签的scale
2:给根元素设置data-属性。是动态的
2:当scale设置以后,就可以获取到当前的dom宽度,然后dom宽度除以10作为根元素的font-size的值,也就是1rem的值
使用sass可以使用如下函数:
@function px2em($px, $base-font-size: 16px) {
@if (unitless($px)) {
@warn "Assuming #{$px} to be in pixels, attempting to convert it into pixels for you";
@return px2em($px + 0px); // That may fail.
} @else if (unit($px) == em) {
@return $px;
}
@return ($px / $base-font-size) * 1em;
}
总结:个人理解H5页面主要是以下几步
1;根据dpr设置页面的缩放比例
2:设置缩放后,便可以获取到当前页面的实际dom宽度,然后利用rem的特性,对页面进行适配
参考:
https://github.com/amfe/article/issues/17
https://juejin.im/entry/5a44cc3d6fb9a0450f223ed0
媒体查询
还有一种适配方法是使用媒体查询。具体思路是
使用原生的媒体查询,配合rem或者em,通过查询出来当前的屏幕尺寸,然后动态的改边根节点的font-size的大小,以此使整个界面进行响应式变化。
本质都是都是当前屏幕尺寸设置根元素的font-size的值