深入理解CSS之px,em和rem的区别(详解em的特性和细节)

这是一篇深入探讨px,em和rem的高级主题文章,我希望是这样。

固定宽度的页面和适配宽度的页面

要讲清楚px,em和rem的区别,还得从这个话题还是聊起。

其实我最开始对于页面固定宽度是非常不能理解的。
下面这个京东页面是在1080*1920分辨率的屏幕下显示的效果。
在这里插入图片描述
下面这个京东页面是在14寸笔记本1366*728分辨率的屏幕下显示的效果。
在这里插入图片描述
当我知道在不同分辨率下jd网站的宽度都是一样的时候,我是感到非常奇怪的。难道不进行适配吗?但是看到大厂都是这样的做的时候我也没什么好说的。

如果你做过Android开发的话,你会知道Android应用是一定要适配屏幕的,不适配就会显示不正常。其实这没有谁对谁错,只是一种取舍而已。只是不同平台处理的方式不一样,造成这种差异有很多种原因。比如操作系统的原因。Android的原生GUI系统是非常老的一套系统。这套GUI系统底层就要求你做适配,那么你就不得不适配。

这里想说的是,适配问题是不是强制要求的。对于BS应用来说。你不适配也不会出问题,只是等比例变小变小了而已,页面布局是不会发生改变的,这里只讨论在pc显示器上显示的情况,不考虑在手机上显示的情况。而且需要考虑的问题还只是宽度设置为800px还是1024px,到后面讨论宽度设置为1024px还是1280px这样的问题。这些你只要将浏览器缩放一下都不是问题。

如果要讨论pc的页面在移动端适配显示,那完全就是另外一回事。那已经不是适配不适配的问题,而是要不要开发一个手机版的问题。

还有一个原因是页面设计师的思维方式。固定宽度对于他们是很自然的事情。考虑变宽是难以理解和设计的。

其实还有一个重要的原因就是收益问题。如果一定要自适应,那么就要考虑非常多的东西,比如图片的大小就很难控制。在一个很大的屏幕上显示一个很小的图片,和在一个很小的屏幕上显示很大的图片都是不太合适的。你说这不是问题,我可以根据比例请求不同大小的图片,这实际上会给服务器很多的负担,情况也变得复杂,到最后,你可能发现得不偿失。还不如写成固定宽度。

绝对单位和相对单位

如果要是固定宽度开发页面,那么绝对单位px就是最佳选择。如果要开发自适应宽度的页面,那么就要考虑相对单位,比如em和rem。
像素单位px我们再熟悉不过了。需要注意的点是,网站开发的像素px和物理像素还是不一样的。CSS 像素并不严格等于显示器的像素,尤其在高清屏(视网膜屏)下。在一些分辨率特别高的屏幕下(比如苹果的4k显示器 ),操作系统是会对所有应用进行强制放大的,因为不放大固定大小的软件会看起来非常的小。不过对于网站,我们不太需要关心这个,因为结构比例是不会改变的。
而em和rem是相对文字来进行自适应的。是一种相对单位。相对单位的好处就是可以实现自适应。缺点就是会让设计变得复杂。

em名字的由来

是的,最开始我是特别好奇em是哪个单词的缩写,官方文档也没有说。查了半天,总结如下:
1.em不是单词缩写。
2.em来着印刷业,印刷需要考虑字母的大小问题,而M的大小差不多是一个正方形。所以,其他的字母都是参考M字母为标准来设计的。而M的英文发音(音标)就是em。
这个故事非常的合理,而且em在CSS种确实和字母大小有关。故事是不是真的就不考证了。
https://www.w3cplus.com/css/r-i-p-rem-viva-css-reference-pixel.html

em的概念和使用

CSS 中,1em 等于当前元素的字号。在不设置字体大小的情况下,默认字体大小是16px,1em也就默认等于16px。

        #box {
    
    
            display: inline-block;
            padding: 1em;
        }

在这里插入图片描述
在修改完字体大小后,1em的值也发生了改变。现在1em=20px。

        #box {
    
    
            display: inline-block;
            font-size: 20px;
            padding: 1em;
        }

在这里插入图片描述

CSS的文字绘制

很多人觉得文字非常简单,不就能显示就行了吗?其实不然,我们看下面的效果。
下图有非常多的特性,你可能会忽略或者看错了。
1.文字最左右两边和div边缘都是有空隙的。如果你文字比较小,你可能会看不见,误以为是紧贴着的。
2.字母g在底部看起来是紧贴着div外围的。但其实不是,如果把字体设置的非常大,是能够看到和div边缘还是有空隙的。只是间隙很小。
3.字母f虽然突出了,但明显,距离div顶部边缘还很远。

<div class="above">agofe</div>
        .above{
    
    
            display:inline;
            background-color: lightblue;
            font-size:500px
        }

在这里插入图片描述
而且,这些空隙是不能消除的,因为这些间隙是文字的组成部分。
我画了一张图来解释这是为什么。
从高度观察的话,CSS的文字绘制可能是没有下面的top和bottom线的。但是有ascent和descent这两条线对应文字的最底部和最顶部。leading表示文字基线。
看完这张图,上面出现的现象,就不用多解释了。
在这里插入图片描述

em的相对含义和计算问题

em会从父元素继承font-size作为基值。

<div id="box">
    <div class="outer">
        outer
        <div class="inner">inner</div>
    </div>
</div>
        .outer{
    
    
            height: 1em;
            background-color: lightgreen;
            width: 200px;
        }

        .inner{
    
    
            font-size: 1.2em;
            height: 1em;
            background-color: lightblue;
            width: 200px;
        }

outer继承了body的默认大小16px。同样高度都是设置为1em,inner的高度比outer的高度明显变大了。这是因为.inner设置了font-size,inner的height=outer.height*1.2*inner.height。
在这里插入图片描述

em的继承特性或存在的问题

em会从父元素继承font-size作为基值。这算是特性,但同时这也是一个非常严重的问题。
上面的代码如果目的本身就是为了放大字体那么没什么问题。 如果出现了多级嵌套的情况就会出现问题。

比如我有一个多级列表。我想设置ul的文字大小为1.2em。我的本意是所有的ul的大小都是1.2em,也就是1.216px。但这时候就会出现问题。ul的字体大小变成了逐级放大。我原意是要一样大小的,这是继承导致的,第一个ul的文字大小是16px1.2。第二个ul文字大小是(16px*1.2)*1.2。也就形成逐级放大的效果。
如果不行出现这样的问题,CSS为我们提供了另一个单位rem,rem的意思是root rem,也就是根据html标签的大小为标准,默认是16px。这样就没有了继承现象,同意以root元素的font-size为标准。就可以解决这个多级嵌套的问题。

        ul{
    
    
            font-size: 1.2em;
        }
    <div>
        <ul>
            <li>Top Level</li>
            <ul>
                <li>Second Level</li>
                <ul>
                    <li>Third Level</li>
                </ul>
            </ul>
        </ul>
    </div>

在这里插入图片描述

使用rem:
这样就不会逐级放大了。当然如果你就是想逐级放大,那么使用em可能就不是问题,而是一种技巧了。

      ul{
    
    
            font-size: 1.2rem;
      }

在这里插入图片描述

设置字号和浏览器缩放

浏览器是可以整体缩放网页。ctrl+或者ctrl-。这种做法只能单独缩放一个网页,而且是临时性。不知道为什么浏览器不支持自动缩放。还有一种方式是通过em。如果根据设置的字号,动态的改变大小,这种方式是永久性的。缺点就是,不是整体会受影响,比如图片是必须用px的。

停止像素思维,不太好的取巧方式

html的默认文字大小是16px,用em来计算不是特别多方便,比如我想要一个20px的文字,那么就要算20/16=1.25em。那么可能有人就想到一种请求到方式,就是把html的font-size设置为0.625em,因为0.625em*16px=10px。这样,如果我要计算比如18px的em值,就可以直接得出结论是1.8em。

但这样方式是典型的像素思维,并不是说不能用像素,而是你用em的时候就要用相对单位的思维,而不是还抱着像素不放。最关键的是这种做法有很明显的缺点。
1.默认10px是比较小的,设置字体的时候,你可能要重新设置字体非常的麻烦。
2.这种做法的本质还是像素思维。用着em,心里想的还是px。身在曹营心在汉。

还有一种改进的取巧方案:
这样用rem的时候可以快速计算,没有写大小的时候,默认大小也是16px。只不过还是老问题,还是用着em,心里想着像素。

html{
    
    
   font-size:0.625em
}

body{
    
    
   font-size:16px
}

em和响应式设计

很多年前,bootstrap非常流行的时候,响应式的概念也非常的火,而类似bootstrap这样的UI框架,他的底层原理就是使用em这种相对单位来实现的,再结合@media实现不同宽度显示不同的em大小。
实现的逻辑就是类似下面这种样子。

        :root {
    
    
            font-size: 0.75em;
        }

        @media (min-width: 800px) {
    
    
            :root {
    
    
                font-size: 1em;
            }
        }
        @media (min-width: 1200px) {
    
    
            :root {
    
    
                font-size: 1.25em;
            }
        }

响应式的定位

响应式布局是很好的,但要搞清楚响应式的定位。
响应式本质上还是网站,而不是App。响应式只是个移动端的显示效果而已,如果你要做成移动端的布局,那已经不是响应式的范围了,而是写了个网页版的app。
而且国内可能不会写网页版APP,而是用小程序做。因为用户实际上已经适应了移动端的操作,对于响应式的隐藏菜单用不习惯。
但是,在节约成本的前提下,响应式也是可以考虑的拿来充当App的。毕竟写移动端是很要修改很多东西。

总结

回归标题,如果非要说px,em,rem有什么区别,文章已经都分析了。
1.px是固定单位,em,rem是相对单位
2.em,rem可以实现响应式功能,更加灵活,也更加复杂。px相对来说更简单。
3.em,rem和字体大小是相关的。

猜你喜欢

转载自blog.csdn.net/ScottePerk/article/details/126943820