本文旨在揭开相对长度单位的神秘面纱。相对长度单位与绝对长度单位 (px 是最著名的代表) 不同,相对长度单位指定了相对于其他东西的长度。这个 “其他的东西” 可以是各种类型的,例如,父元素的字体大小,父容器的宽度,或者视口的高度。
这两种类型的单位都有术语长度,但在这种情况下,长度单位到底是什么?有字体长度单位 (如 em
, rem
),这是相对于字符或元素的字体相关属性。此外,还有相对于视口的长度单位 (例如,vw
, vh
)。
在相对单元的上下文中,另一种常见的 CSS 数据类型是百分比 (%)。也有接受整数值的 CSS 属性。这种单位最常见的用例是将其与行高属性一起使用。
相对单元从流动布局和 web 可访问性的角度来看,对于支持依赖缩放的用户来说尤为重要。这些流体布局基于比例设计,其中长度是根据容器的百分比定义的。
因此,基于相对单元的组件在运行时可能会改变大小,因为它们是根据上下文容器 (重新) 计算的,例如,通过旋转设备或减少浏览器窗口的大小。
首先,我们将看看最常见的相对字体相关的 CSS 单元是如何工作的:em
和 rem
。
em
单位浏览器将 em
值转换为相对于当前字体大小上下文的 px
值。让我们看一个例子。
h2
元素的margin-top
是多少?打开 Chrome DevTools,选择 h2
,然后导航到 CSS 部分中的 Computed 选项卡。该值为 40px
。
这个值是如何产生的?考虑的 HTML 元素 (h2
) 的 CSS 属性 (margin-top
) 的计算公式为:
em
值 (2) 乘以要样式化的 HTML 元素的 px 中的实际字体大小 (20)。在我们的例子中,这意味着:2 * 20px = 40px
。
那么例子中 h3
元素的顶部边距呢?最后的值是 46.8px
。
这是为什么呢?我们没有像对 h2
元素那样声明一个字体大小值。然而,每个元素都有一个值 —— 这是 CSS 的本质。
如我们所见,h3
元素的默认字体大小为 1.17em
。这也没有 px
值。我们必须沿着父元素层次结构往上走,直到我们找到一个 px
值。
在 DevTools 的帮助下,我们发现 body
元素有一个来自浏览器默认值的绝对font-size
值,因为我们没有指定自定义值。
有了这些信息,我们可以计算出具体的值:2.5 * 1.17 * 16 = 46.8px
。
下一个示例演示了 em
并不只用于样式化文本内容;相反,它可以在任何可以使用长度单位的地方使用。一开始可能会觉得有点疏离,但是你可以确定非文本元素的样式,不会有任何问题。
rem
单位与字体相关的相对单位 rem
代表 “root em”,它与浏览器根元素 (通常是 html
元素) 的字体大小相关。很容易确定:将 rem
值乘以浏览器 html
元素的 px
中的实际字体大小。
计算出的 h2
元素的边距顶部值是 32px
,因为定义的 rem
值 (2) 乘以 html 元素的绝对字体大小值 (16px
)。因为我们没有提供一个选择器来定义 html
元素的字体大小,所以它是浏览器默认的。
对于大多数 (桌面) 浏览器,默认值是 16px
。但是为了找到答案,你可以再次利用 DevTools。
rem
和em
使用 rem
和 em
与响应式设计、可用性和可访问性等主题密切相关。
rem
的优点是没有font-size
继承的统一大小。作为应用程序设计人员,你可以对用户的字体设置作出反应,以便适当地显示内容。这一点很重要,这样就不会排除用户对易访问性设计的依赖。当用户增加字体大小时,你有机会保持布局的完整性,例如,文本不会被压缩到一个固定宽度的小容器。
em
是每个 CSS 开发人员的强大工具。样式元素的基本原则是根据父元素的字体大小来确定 “尺寸值”(例如边距、宽度)。因此,它并不局限于根元素 (html
)。
em
的主要好处之一是它能够在一个上下文 (例如,一个按钮或一个预告模块) 的设计元素之间建立比例关系。em
的使用与上下文可伸缩性和响应式设计的问题密切相关。下一个示例演示如何将 em
用于响应式组件设计。
按钮组件响应结构是用按钮选择器定义的。边框、padding
和 border-radius
使用与所定义的字体大小值相关的相对单位。不同的按钮大小由具体的类选择器定义 (例如,size-l
)。
因为字体大小值也是 em
单位,所以具体的上下文值来自于用 main
和 footer
选择器定义的具体 px
值。
这种方法的好处是你可以在不同的上下文中轻松地重用这些组件。你只需要为不同的上下文容器定义不同的字体大小,然后继承来完成剩下的工作。
在 CSS 中,percent (%
) 本身不是一个长度单位,而是一种数据类型。使用它感觉像是一个长度单位,因为你可以把它应用到任何你可以使用 px
,em
等的地方。所以在这种情况下提到它是公平的。
此数据类型总是引用父组件的一部分。在 percentage 中定义的长度是基于父元素的相同属性的长度 (计算值为 px
)。下面的例子说明了这一点:
main {
width: 400px;
height: 50%;
}
h1 {
width: 50%;
}
<body>
<main>
<h1>hello world</h1>
</main>
</body>
h1
元素的计算宽度是其父元素 main
的一半,即 200px
。如果父容器是 body
元素,那么百分比总是指浏览器视口的大小。在我们的例子中,main
元素的 height
属性的计算值是 viewport
容器计算值高度的一半。
让我们仔细看看一些细节。在下面的代码中,灰色背景容器是 h2
元素的父元素 (蓝色背景)。
没有用户定义宽度的块级元素的默认行为是占用父容器的可用水平空间,正如你在 demo 1 中看到的那样。h2 的水平填充 (深蓝色背景) 没有添加到总宽度中。
然而,正如你在 demo 2 中看到的,定义width:100%
会导致显示水平滚动条。这是为什么呢?
在演示 1 中,默认的宽度值为 auto
,与之相反,在计算中定义一个百分比值包括填充、边距和边框,并使子容器的宽度超过其父容器的宽度。你可以在 CSS 规范中阅读它。
在 demo 3 中,我们也指定了 width: 100%
,但是我们没有水平滚动条。这是因为我们将默认值 box-sizing: content-box
更改为 box-sizing: border-box
后,子元素的边框和填充并没有增加水平间距。在整个 CSS 设计中定义一个全局选择器来使用 border-box
,这并不少见。
在 demo 4 和 demo 5 中,你可以看到这个百分比不一定与直接的父元素有关,而是与父树中更上一层的元素有关。
百分比值 (%
) 总是指向父元素。然而,视口单元值表示当前浏览器视口的百分比。
视口单元的值是根据视口容器的宽度 (vw
) 和高度 (vh
) 确定的。取值范围为 1 ~ 100。
1vw
是视口宽度的 1%; 同样,1vh
是视口高度的 1%
。100vw
是视口宽度的 100%
; 同样,100vh
是视口高度的 100%
。viewport 单元最明显的用例是将它们用于顶层容器,它们占用与 viewport 大小相关的空间;没有涉及父元素的级联或影响。与 %
相反,对于视口单元,要设计样式的元素放在标记的什么位置并不重要。
所以全宽截面可以用 100vw
,对吧?是的,但有一个警告。
不考虑元素的边框和边距,因此在下一个示例中可以看到,头容器超出了浏览器的视口,显示了一个水平滚动条。文章容器通过将 box-sizing
属性的默认值 content-box
设置为 border-box
来解决这个问题。
对于主容器,我们使用另一种方法来防止这个问题,即使用 calc ()
减去两边的边框宽度和边距。
如果你的用例是获得一个全宽的 section,使用旧的 width: 100%
(display: block
的默认值) 会更容易,就像你在页脚容器中看到的那样。使用 width: 100%
更好,因为旧的浏览器在显示滚动条时可能会遇到问题。
一个更有益的方法是使用与视口高度相关的 vh
单位。如果你想将容器拉伸到视口的高度,那么 vh
优于 %
,因为后者与父容器相关。因此,对于 %
单元,你必须使用固定的布局技术来确保父容器填充了视口的高度。
相关的单位是 vmin
和 vmax
:
20vmin
与 20vw
或 20vh
有关,取较小的数 10vmax
与 10vw
或 10vh
有关,取两者中较大的一个 让我们重新解释一下:举个例子,10vmin
在纵向上是当前视口宽度的 10%,在横向上是视口高度的 10%。
理解相对单位是流体布局或响应式设计 (随便你怎么称呼它) 的关键,使 CSS 能够应付几乎无限的视口大小和 dpi。
基于字体的单位一开始可能会觉得很奇怪,但在获得一些经验后,你会意识到它们比绝对单位更有好处。视口单元 (尤其是 vh
) 很有用,但重要的是要理解什么时候使用它们,什么时候使用老式的 % 数据类型。
在开发网站的过程中,一个经常被忽视的方面是使网站具有可访问性。就其本质而言,这些相对单位尊重用户特定的字体大小和缩放设置。
本网站搬运了CC社区和XJ社区的cskzwr数据,大家可以在这里查询cskzwr数据,下载cskz地图和demo,同时还提供了一些kz视频制作教程。