一、首先明确几个概念:
- 物理像素、逻辑像素、渲染像素、css像素、设备像素比
- px、rem 、em、vh、vw、vmin、vmax
- 视口(viewport)、布局视口、视觉视口、理想视口
适配目标:
(1)更大的屏幕看到的内容更多,即相等距离,看到不同屏幕上的内容大小相同;
(2)更大的屏幕看到的内容更大,即不同屏幕看到的内容量相同。
(3) 同类型的屏幕看到的内容量相同,不同类型的屏幕下 大屏看到更多的内容。
!像素
**物理像素:**显示屏的硬件条件,反映显示屏内部led灯的数量,可以简单理解,一组三色led灯代表一个物理像素。
逻辑像素:(设备独立像素)为了屏蔽不同物理像素的屏幕内容显示大小而做出的一种抽象像素单位。如iphone屏幕,一个物理像素对应2~3个逻辑像素。
**渲染像素:**显卡或者其他视频输出设备输出的数字图像的分辨率,pc对应的就是设置里边的分辨率,一般推荐设置最大分辨率,此时渲染像素和物理像素一一对应。为了简化模型,此处等同于物理像素。
**viewport像素:**本质是DIP(Device Independent Pixels),设备无关像素。pc上 viewport像素不生效,所以pc上viewport像素和逻辑像素可以等同。
**css像素:**页面中设置的像素值。window.devicePixelRatio
设备像素比:物理像素/逻辑像素。
!!单位
em: 字体单位,可继承,1em = 其所继承的font-size px的值,如果页面未设置就是浏览器默认字体。
rem: root em, 1rem = html字体font-size的px的值的大小,如果页面未设置就是浏览器默认字体。
vh: 视口高度的1/100。
vw: 视口宽度的1/100。
vmin: min(vh, vw)。
vmax: max(vh, vw)。
!!!视口(viewport)
**视口:**简单理解就是浏览器窗口,只包括显示内容的区域,不包括菜单栏等。
**布局视口:**document.documentElement.clientWidth和 document.documentElement.clientHeight 组成的区域。为了兼容为pc端设计的网页,布局窗口的大小比视觉视口要大。默认页面使用布局视口。一般如果不设置缩放和页面宽度,默认布局视口宽度980px。
****视觉视口:可以看到的浏览器区域,****window.innerWidth, window.innerHeight 组成的区域。
理想**视口****:**可以完整显示内容,又不出现滚动条,和页面完美贴合的窗口。
二、布局方案分析
0.自然条件下显示(不使用rem、 viewport、媒体查询等方案)
对于android屏幕(1倍屏),如果按照设计稿设置宽度为750px,则几乎在所有的手机屏幕竖屏时,都是超出屏幕宽度的。如果要实现页面在屏幕上的自适应布局,可以使用flex布局,grid布局等。如果要实现响应式布局,要使用媒体查询。@media (min-height: 680px), screen and (orientation: portrait) { ... }
1.基于rem的布局方案
简介:蓝湖web设计稿,是按照屏幕宽度750px(iphone6)。
操作方法:在页面加载最开始,执行脚本,获取屏幕像素比,屏幕宽度等,设置html的font-size。
为了便于计算,将750分为100份或者10份,每一份设置为1rem,本文以10份作为1rem为标准。则需要设置字体为75px,在缩放比为1的屏幕上,如果宽为400px, 则设置html的font-size 为40px,并修正body的font-size为正常页面需要的字体大小。则,使用rem来设置大小时,会根据设备屏幕宽度进行缩放。
(1)设置布局窗口宽度 = 设备宽度。相当于设置了一个基准,在此基础上设置其他内容的size.
<meta name="viewport" content="width=device-width, initial-scale=scale, maximum-scale=scale" minimum-scale=scale, user-scalable=no'>
(2)根据像素比ratio,设置缩放。这样,设置1px,在页面中只占到1/ratio = scale px.
<meta name="viewport" content="width=device-width, initial-scale=scale, maximum-scale=scale" minimum-scale=scale, user-scalable=no'>
(3)设置html font-size 为 屏幕宽度/10。相当于创造了一个可供使用的单位,便于计算。如屏幕宽度w(px), 像素比ratio, 则设置font-size: w * ratio / 10 = 1rem; 对于android,360 * 640 ,ratio = 1, 则font-size = 36px;对于iphone, 375 * 667, ratio = 2 font-size = 375 * 2 / 10 = 75px.
document.documentElement.style.fontSize = document.documentElement.clientWidth / 10 + 'px';
(4) 转换css中的px为rem(postcss px2rem插件等)以750为基准,75px即为1 rem.
缺点:
1) px的使用受限, 如果行内style设置1px,在高倍屏幕(iphone)上就只显示会边模糊(因为对页面进行了缩放)。
2) 字体也做了缩放,导致不同设备字体不同,违背了设计初衷。
3) 同样px值在css文件中和行内css中的效果不同,可能造成结果和预想不一致。对于android机(假设设备无关像素 400 * 640) 同样设置宽400px, 行内设置会占满屏幕,css设置只有(400 / 750)屏幕宽,高同理。在iphone(6/7/8 ratio = 2,设备无关像素375 * 667)中,由于设置了initial-scale等为0.5, 行内css设置的宽度,最终显示只有一半,
效果:
对于android手机,ratio = 1, 假设width = 360px。页面真实宽度值/设计稿宽度值 = 360 / 750,其他通过转换rem后的size 均作等比缩放。1px问题近似解决。
对于iphone手机,假设ratio = 2,width = 375px (iphone6)。页面真实宽度为
2.基于vw的布局方案
由于原生vw即为viewport width / 100, 所以省去了转换px为rem的过程,直接使用即可,但是需要注意不同设备对vw的支持情况。vmin, vmax在切换横屏竖屏时,会比较有用。
3.前端将宽高传给后端,后端屏幕宽高,计算页面中组件的大小,并得scale,回传前端,供前端使用。
三、开发建议
1. 在head 设置width=device-width的viewport
2. 在css中使用px
3. 在适当的场景使用flex布局,或者配合vw进行自适应
4. 在跨设备类型的时候(pc <-> 手机 <-> 平板)使用媒体查询
5. 在跨设备类型如果交互差异太大的情况,考虑分开项目开发
参考文献:
1. caniuse.com/viewport-un… (vw, vh,vmin, vmax支持情况)