理解 CSS 百分比

2025-06-07

理解 CSS 百分比

你有没有搞不懂过 CSS 中百分比的工作原理?有没有想过为什么它有时如此混乱,毫无逻辑?没错,我就是这么想的。因此,我写了这篇文章,想和大家分享我通过研究和阅读获得的理解。

百分比是多少?

以百分比形式呈现,显然应该有一个目标作为参考源。大多数答案都指向我们指定百分比的元素的父块。这是正确的,但并不能完全涵盖所有情况。最正确的答案应该是包含块,即包含我们元素的块,它不必是直接父级。

我们来看下面的例子:

在这个例子中,我创建了 3 个嵌套的divs,它们是 3 个正方形,具有以下特征:

  • 最外层的祖父母div 为浅灰色,尺寸为4x4
  • div 为深灰色,尺寸2x2
  • 我给红色子div 指定了50%的大小

如果百分比单位以父级为基准,子级的尺寸应该是它的一半,但事实并非如此,正如你所见,子级的尺寸实际上等于父级加上祖父级的一半。这是因为祖父级div 才是子div真正的包含块,因为子级具有,与我在祖父级中设置的 相对应。position: absoluteposition: relative

因此,要识别元素的实际包含块,完全取决于position元素本身的属性。您可以在MDN上阅读更多内容。

然而,对于某些属性,百分比单位的引用源既不是父级也不是包含块,而是它本身——自身元素

按属性百分比

width/height

非常简单,正如您在上面的示例中看到的,当为元素分配百分比值时width,其包含块width会被用作参考源。同样,元素的 指的是包含块heightheight

padding

对于padding,垂直(padding-top/ padding-bottom)或水平(padding-left/ padding-right)指的是包含块width

例子:

在这个例子中,

  • 父div尺寸为6x4
  • 子div大小为0,但分配padding-toppadding-left50 %

结果是子项的大小相当于父项width的1/2 ,即3x3 的正方形。

margin

与 类似padding, 的百分比margin(垂直和水平)是指width包含的。

例子:

在这个例子中,

  • 父div尺寸为6x4
  • div获得50 %margin-topmargin-left

结果是子项位于距离父项顶部和左边距3 个单位的位置(父项1/2 )。width

top/ bottom/ left/right

对于这些属性(通常附带position),垂直属性(top/ bottom)指的是包含块的height,而水平属性(left/ right)指的是包含块width

例子:

在这个例子中,

  • 父div尺寸为6x4
  • div拥有给予50 %position: absolutetopleft

结果是div 位于距离父级顶部边缘2 个单位的位置(父级的1/2 ),并且位于距离父级左侧边缘3 个单位的位置(父级的1/2 )。heightwidth

transform: translate()

这是一个非常棒的动画/过渡属性,它还支持百分比值。然而,它并不指向其包含块,而是指向自身

例子:

在这个例子中,

  • 父div尺寸为6x4
  • 子div大小为2x1transform: translate(50%, 50%)

结果是div 位于距离父级顶部边缘0.5 个单位(其自身的1/2 )的位置,并且位于距离父级左侧边缘1 个单位(其自身的1/2 )的位置。heightwidth

background-size

background-size属性将百分比单位的复杂性提升到一个新的水平😄
此属性的百分比值现在指的是背景定位区域,我将其解释为类似于包含块,但增加了以下 3 个因素:

  • 仅包含内容的块(content-box
  • 包含内容和填充的块(padding-box
  • 包含内容、填充和边框的块(border-box

这 3 个因素由属性给出background-origin您可以在MDN上阅读更多内容。

例子:

在这个例子中,

  • 父div尺寸为6x4
  • 子div大小为3x2,否padding,否border
  • 我使用 DEV 徽标(正方形比例为1:1)作为background-imagediv,并将属性设置background-size50% 50%

结果是背景图像被拉伸到1.5x1的尺寸,相当于子图像尺寸的 1/2 。

background-position

类似地background-size,该属性的百分比background-position也依赖于背景定位区域

例子:

在此示例中,使用的图像和布局与上一个示例相同。随着 的值发生变化background-position,我们可以看到以下变化:

  • 没有任何值(默认情况下,值为0 0),背景图像位于左上角
  • background-position: 0 50%背景图像位于左中央
  • 使用background-position: 50% 50%,背景图像位于中心
  • background-position: 100% 100%背景图像位于右下方

注意background-position: 0 50%相当于:

  • background-position-x: 0
  • background-position-y: 50%

显然,此属性的百分比背后有一些计算,而不仅仅是图像顶部和左侧边缘到元素的距离。通过一些研究和测试,该属性似乎background-position依赖于以下计算才能得出实际值:

偏移量 X = (容器宽度 - 图像宽度) * 背景位置 x

偏移量 Y = (容器高度 - 图像高度) * 背景位置 Y

在这种情况下,

  • 容器作为div
  • 图像的宽度/高度是最终的大小background-size

font-size

对于font-size,百分比值仅指其直接父块

例子:

在这个例子中,我使用与第一个例子相同的布局,分配font-size如下:

  • 祖父母13px
  • 父级26px
  • 儿童50 %

结果,我们可以清楚地看到,子项font-size现在相当于祖父母项,是父母项的 1/2,忽略了分配给祖父母项而不是父母项的事实position: relative

line-height

虽然可能不那么流行,但我还是要提一下这个属性,因为它也支持百分比。的百分比值line-height取决于font-size本身

例子:

在这个例子中,

  • 本段共11
  • font-size设置为20px
  • line-height设置为150%

height整个区块的实际尺寸为~329px

  • 在这种情况下line-height是:20 * 150% = 30px
  • 那么height就是: 30 * 11 = 330px,近似于实际height

总结

希望这篇文章能够澄清你对 CSS 中百分比值的理解,而不是让事情变得更糟😅

我还在推特上发布了一张小抄来总结目前为止所写的内容,也许一开始记住这些含义会很有用:

这是文章中所有示例的集合:https://codepen.io/collection/xKwgdW

参考

文章来源:https://dev.to/khangnd/understanding-css-percentage-44gd
PREV
Monorepo – 作为全栈开发人员你必须知道的 One Repo 的魔力
NEXT
诺基亚 1100 模拟