前言
当不同设备对应的屏幕不一样时,这时对于px,rpx来写的样式就会存在样式适配问题。
对于移动端设备进行适配,采用设置最大宽度,并且在meta标签中设置理想视口,可以保证在移动设备以及PC上面的整体布局效果。
由于小程序方面,微信官方已经将样式适配问题处理得非常完善了,不用我们操心,但如果开发的是移动端页面等等需要自己适配,或面试考到,那么这方面内容就需要再深入了解一下了。
可见视口
Visual Viewport其实很好理解,就是整个屏幕的可见区域大小。由于设备的物理像素,也就是CSS中的pt单位是固定的,页面在移动端被缩放了之后,页面中的CSS像素分布在设备上也发生了变化。
理想视口
Ideal Viewport其实是上面两者的结合,当我们将Layout Viewport的宽度设置成屏幕的宽度,就保证了页面中CSS像素点的恒定。
这里就用到了移动端适配常用的
<meta name="viewport" content="width=device-width">
这个标签可以保证在移动端设备中,页面的宽度与屏幕宽度相同。
正题
目前对于移动端适配的内容布局解决方案大致可分为以下几种:
(1)百分比,所有需要动态调整的元素宽高采用百分比,字号固定像素。
(2)rem,通过计算或者JavaScript获取到设备像素/CSS像素的比例,确定根元素的字体像素,然后所有单位根据根元素字体像素进行rem设置,确定大小。而基础rem会根据设备变化而变化。
(3)vw,根据当前设备的Visual Viewport宽度作为100vw,然后得出单位vw的宽度,所有元素按照vw为单位进行样式排布。
(4)Media Query:通过断点来进行不同宽度区间的设备样式适配。
以上几个方法各自都有各自的好处,我们可以看一下实际应用时候的效果:
💥 百分比 💥
使用百分比作为内容大小的标准,在大部分条件下是可行的,百分比可以很好地让元素乖乖呆在自己的位置,无论屏幕的宽度大小。
但是文字就存在非常大的问题了,由于文字是固定大小,在屏幕dpr变化的时候,文字的CSS像素不变,就导致了文字在页面中的占位发生了变化。这样的结果就是,文字过多或者屏幕dpr过小的时候,会发生溢出;但是如果按照小屏幕为基准,又会发生字体太小这种情况。
百分比在当前移动端适配排版的时候,更多地会作为section级别元素的兼容排版。这个也要和设计稿中的效果相关,如果设计稿中要求一个元素定宽,那么就直接用px来保证宽度就可以了。
💥 rem 💥
rem这个单位和之前常用的em有点类似,唯一的区别在于rem及基于根元素的font-size来进行计算的一个相对值。em存在很多缺点,比如层层嵌套之后,可能就会忘记了上一层的font-size到底是多大。或者比如像现在的模块化开发,一个路由套在另一个路由里面,甚至找父元素都需要到其他文件中去找。
为了解决em存在的问题,标准中还有rem这个单位来帮助排版。所有的元素大小都用rem来作为单位,然后在页面的根元素中,我们为根元素的font-size进行确定化地赋值,这样所有的rem单位都是同一个明确的基准了。当屏幕进行适配的时候,只需要调整这个基准值,就可以保证每个元素的大小自动按照比例调整。
阿里的lib-flexible解决方案实际上就是利用了这个方式,通过给<html>标签绑定font-size以及data-dpr属性来进行整个页面的适配。
方案将整个页面宽度分成100份,分成100份的原因可以看下面的另一个方案。每10个单位宽度作为1rem,也就是整个视觉稿的宽度会被分成10rem的100份,假如拿到的视觉稿是750px的,那么1rem就代表75px。这样得到的比例系数就是75/750,也就是每次在进行设计稿到CSS的转换的时候,只需要对设计稿的像素值/10就可以得到对应的rem值。
通过一个预先加载的JavaScript脚本,计算根节点的字体大小,document.documentElement.style.fontSize = window.innerWidth / 10 + ‘px’;,然后我们在写页面代码的时候只需要将原始的像素值/基准值就可以得到对应的rem单位了。当然每次都要按计算器肯定是不行的。如果想方便使用的话,可以用less或者sass这种预处理器来处理页面。
💥 vw/vh(是最终解决方案吗?)💥
首先看看vw的浏览器支持情况吧,can i use vw支持情况,使用这个单位意味着你放弃了IE11以下的PC用户,在现在一个主要兼容移动端的世界里,并没有太大的副作用(这里吐槽一句,其实PC端的兼容远远要比移动端来的方便。移动端奇奇怪怪的分辨率以及2x,3x的屏幕,还有苦逼的ipad、横屏让我每次做兼容的时候想一跃解千愁)。
vw自身将整个可见视口横向分成了100份,每一个单位就是1vw,这个单位最大的优势就是在移动端的时候,无论是竖屏或者横屏,vw永远都是针对于横向的,比rem的方案好在当屏幕大小发生变化(顺便兼容了以后的可调节屏幕大小的移动设备[手动斜眼])的时候,不会让页面崩掉。
对于移动设备来说,比如iphone6+的375pxCSS像素宽度,1vw就等于3.75px,通过这个单位可以解决上面的依赖于脚本绑定根元素font-size的问题,在竖屏和横屏下面都有比较好的效果。
在通过vw解耦了CSS和JS之后,那么vw是否可以独立解决所有问题呢?
💥 media query(媒介查询)💥
CSS响应式布局
① 使用 @media 查询可以针对不同的媒体类型定义不同的样式。
② @media 可以针对不同的屏幕尺寸设置不同的样式,特别是如果需要设置设计响应式的页面。
③ 重置浏览器大小的过程中,页面也会根据浏览器的宽度和高度重新渲染页面。
[@media](/user/media) 媒介类型and|not|only (媒介特征) {
...
}
实例:
为不同页面宽度设置不同的CSS样式——页面宽度大于320px和页面宽度等于320px时分别为div设置不同的背景颜色。
#square{
width:100px;
height:100px;
}
[@media](/user/media) only screen and (min-width: 320px) {
#square {
background:red;
}
}
[@media](/user/media) only screen and (min-width: 320px) and (max-width: 320px) {
#square {
background:yellow;
}
}
结论
虽然根据实现出来的效果,几种方法可能没有什么太大的效果差别,但是最大的问题在于,需要实现这种效果需要多么复杂的代码呢。CSS的兼容性不在于解释器上,而是在于设备的屏幕上面。大部分时间不仅需要将页面展示在用户的面前,而是需要将页面稳定且优雅地展示给用户。无论是百分比,rem还是vw,都是进行局部容器元素定位的,作为最底层的叶子元素或者单元元素来说,更多时间还是会使用px来尽量还原视觉稿。
长远考虑这个问题,vw在仅进行移动端访问的情况下效果拔群,因为不考虑兼容,只需要考虑适配问题。工程中到底使用哪个方法进行,取决于大部分业务需要兼容的环境。