自适应布局的常用解决方案对比(媒体查询、百分比、rem和vw/vh)

如何在不同分辨率的设备上更好的实现适配?
本文从px引入,介绍几种自适应解决方案包括媒介查询、百分比、rem/em和vw/vh。

一、px

px不是绝对单位,而是相对单位。
比如1px的文字在pc端和移动端的大小是不一样的。

所以说,你写好的布局样式与元素大小,在不同设备上的呈现是不一样的。
在别的设备上可能会乱或者字太小看不清等等。
如果一套样式不行,那么能否给每一种设备各一套不同的样式来实现自适应的效果?

答案是肯定的。

使用@media媒体查询可以针对不同的媒体类型定义不同的样式,特别是响应式页面,可以针对不同屏幕的大小,编写多套样式,从而达到自适应的效果。

我们引入媒介查询。

小补充:关于为什么px在pc端和移动端的大小是不一样的。
概括:我们所写的px是通过一定的计算规则呈现给我们的,同样的16px在计算参数不同的情况下计算出的结果是不一样的。

首先,呈现给我们的单位像素是css像素,px是最小单位的表示,并不定义为1css像素,只是在开发中设置了viewport后1px就变成设备逻辑像素了,也就是1css像素。

1css像素的计算规则:1 CSS像素 = 物理像素/分辨率

举个例子:
在pc端的布局视口通常情况下为980px,移动端以iphone6为例,分辨率为375 * 667,也就是说布局视口在理想的情况下为375px。比如现在我们有一个750px * 1134px的视觉稿,那么在pc端,一个css像素可以如下计算:

PC端: 1 CSS像素 = 物理像素/分辨率 = 750 / 980 =0.76 px

而在iphone6下

iphone6:1 CSS像素 = 物理像素 /分辨率 = 750 / 375 = 2 px

可以看到1css像素所代表的大小是不一样的。

二、媒介查询


    
你好

通过缩放浏览器的宽度大小查看样式变化。

上述的代码通过媒体查询定义了几套样式,通过max-width来划分,对分辨率在0~100px,100px~200px,200px~300px的屏幕设置了不同的背景颜色。

而且我们通过class=apx的div的显隐可以发现,媒介查询从最大宽度到最小宽度元素是会保留的,但从最小宽度到最大宽度是不会保留的。这也很好理解,我们定义的是max-width,宽度大的包含宽度小的,宽度小的不包含宽度大的。

缺点:通过 Media Queries 实现的布局需要配置多个响应断点,而且带来的体验也对用户十分的不友好:布局在响应断点范围内的分辨率下维持不变,而在响应断点切换的瞬间,布局带来断层式的切换变化,如同卡带的唱机般“咔咔咔”地一下又一下。

三、百分比

.apx{
        width:20%;
        height:20%;
        background-color: rgb(243, 147, 168);
}

百分比是可以使每个元素的大小自动实现响应式(不像媒介查询需要一个一个设置),而且百分比的显示更加自然,不会有断层感。
那么它的依据是什么?
css中的子元素中的百分比(%)到底是谁的百分比?
子元素的百分比完全相对于直接父元素(大部分)。

  • height百分比相对于父元素的height,width百分比相对于父元素的width
  • top和bottom相对于非static定位父元素的height,left和right相对于非static定位父元素的width
  • 子元素的padding、margin不论是垂直方向或者是水平方向,都相对于直接父亲元素的width,而与父元素的height无关。
    不相对于父元素的:
  • border-radius、translate、background-size等属性,如果设置border-radius为百分比,则是相对于自身的宽度

缺点:

  • 因为存在多级父元素嵌套的关系导致计算不方便
  • 不同的属性计算百分比的依据不同,使用时总是要操心到底依据谁

四、自适应场景下的em/rem解决方案

em
em也是依据父元素的,但和百分比不一样。
体现在:如果没给一个元素设置了font-size的大小,则根据父元素计算该em大小,如果已经设置过了,则根据自身计算。
举例:


  
    

这里的span因为设置了font-size:1rem;,它的padding不相对于父元素的div计算了,而是相对于自身计算,所以是18px。
缺点:多级父元素嵌套的关系导致计算太过复杂

rem
rem只相对于浏览器的根元素(HTML元素)的font-size。

html{font-size: 62.5%}  /* 16 ×  62.5% =10px */
body{font-size: 1.4rem;}   /* 1.4 × 10px = 14px */

默认情况下,html元素的font-size为16px,所以根元素的大小是10px。
需要注意的是:由于浏览器默认最小字体大小的限制,如果设置的根元素字体大小小于默认最小字体大小,那么就会以默认最小字体大小设置根元素。比如:在chrome中,最小字体大小是12px,如果你设置的字体大小小于12px,还是会以12px设置。
比如上面的例子,我们设置的最小字体是10px,但在chrome中,最小是12px,所以大小就是1.4rem*12px=16.8px

rem单位都是相对于根元素html的font-size来决定大小的,根元素的font-size相当于提供了一个基准,当页面的size发生变化时,只需要改变font-size的值,那么以rem为固定单位的元素的大小也会发生响应的变化。
因此,如果通过rem来实现响应式的布局,只需要根据视图容器的大小,动态的改变font-size即可。

这就需要我们使用js来动态计算了,实现的方案有很多种,我这里给大家提供一种:

(function  () {
        setRem();
        window.addEventListener('orientation' in window?"deviceorientation":"resize",setRem);
        function setRem () {
            var html = document.documentElement; 
            var width = html.clientWidth;
            html.style.fontSize = width/16 + 'px';       //跟html的font-size设置成62.5%的道理一样
            //假如页面宽为320px,则1rem为320/16px
        }
})();

上面代码的两个小知识:
documentElement:在控制台打印documentElement会返回文档对象里所有根元素的只读属性。就相当于你文档下所有代码的打印。
html.clientWidth的含义。

rem是移动端使用最多的一种布局方式。

缺点:唯一小小的缺点就是需要在头部内嵌一段脚本来进行监听分辨率的变化来动态改变根元素字体大小,使得 css和js耦合了在一起。

五. 通过vw/vh来实现自适应

vw和vh都是相对于浏览器的根元素(HTML元素)的font-size计算的。
vw:相对于视窗的宽度,视窗宽度是100vw
vh:相对于视窗的高度,视窗高度是100vh
vmin:vw和vh中的较小值
vmax:vw和vh中的较大值

使用方法也很简单,只需要将根元素的font-size,设置为一个流体单位:

html{ font-size: 2vw; }
    .apx{
        width:6rem;
        height:6rem;
        background-color: rgb(243, 147, 168);
    }

或者不设置html,直接使用也同样可行。

  .apx{
        width:6vmax;
        height:6vw;
        background-color: rgb(243, 147, 168);
    }

你可能感兴趣的:(web,CSS)