理解 CSS 百分比
你有没有搞不懂过 CSS 中百分比的工作原理?有没有想过为什么它有时如此混乱,毫无逻辑?没错,我就是这么想的。因此,我写了这篇文章,想和大家分享我通过研究和阅读获得的理解。
百分比是多少?
以百分比形式呈现,显然应该有一个目标作为参考源。大多数答案都指向我们指定百分比的元素的父块。这是正确的,但并不能完全涵盖所有情况。最正确的答案应该是包含块,即包含我们元素的块,它不必是直接父级。
我们来看下面的例子:
在这个例子中,我创建了 3 个嵌套的div
s,它们是 3 个正方形,具有以下特征:
- 最外层的祖父母div 为浅灰色,尺寸为4x4
- 父div 为深灰色,尺寸为2x2
- 我给红色子div 指定了50%的大小
如果百分比单位以父级为基准,子级的尺寸应该是它的一半,但事实并非如此,正如你所见,子级的尺寸实际上等于父级加上祖父级的一半。这是因为祖父级div 才是子级div真正的包含块,因为子级具有,与我在祖父级中设置的 相对应。position: absolute
position: relative
因此,要识别元素的实际包含块,完全取决于position
元素本身的属性。您可以在MDN上阅读更多内容。
然而,对于某些属性,百分比单位的引用源既不是父级也不是包含块,而是它本身——自身元素。
按属性百分比
width
/height
非常简单,正如您在上面的示例中看到的,当为元素分配百分比值时width
,其包含块width
的会被用作参考源。同样,元素的 指的是包含块的。height
height
padding
对于padding
,垂直(padding-top
/ padding-bottom
)或水平(padding-left
/ padding-right
)指的是包含块width
的。
例子:
在这个例子中,
- 父div的尺寸为6x4。
- 子div的大小为0,但分配
padding-top
了padding-left
50 %
结果是子项的大小相当于父项width
的1/2 ,即3x3 的正方形。
margin
与 类似padding
, 的百分比margin
(垂直和水平)是指width
包含块的。
例子:
在这个例子中,
- 父div的尺寸为6x4。
- 子div获得50 %
margin-top
margin-left
结果是子项位于距离父项顶部和左边距3 个单位的位置(父项的1/2 )。width
top
/ bottom
/ left
/right
对于这些属性(通常附带position
),垂直属性(top
/ bottom
)指的是包含块的height
,而水平属性(left
/ right
)指的是包含块width
的。
例子:
在这个例子中,
- 父div的尺寸为6x4。
- 子div拥有并给予50 %
position: absolute
top
left
结果是子div 位于距离父级顶部边缘2 个单位的位置(父级的1/2 ),并且位于距离父级左侧边缘3 个单位的位置(父级的1/2 )。height
width
transform: translate()
这是一个非常棒的动画/过渡属性,它还支持百分比值。然而,它并不指向其包含块,而是指向自身。
例子:
在这个例子中,
- 父div的尺寸为6x4。
- 子div的大小为2x1,
transform: translate(50%, 50%)
结果是子div 位于距离父级顶部边缘0.5 个单位(其自身的1/2 )的位置,并且位于距离父级左侧边缘1 个单位(其自身的1/2 )的位置。height
width
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-image
子div,并将属性设置background-size
为50% 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
设置为20pxline-height
设置为150%
height
整个区块的实际尺寸为~329px,
- 在这种情况下
line-height
是:20 * 150% = 30px。 - 那么
height
就是: 30 * 11 = 330px,近似于实际height
。
总结
希望这篇文章能够澄清你对 CSS 中百分比值的理解,而不是让事情变得更糟😅
我还在推特上发布了一张小抄来总结目前为止所写的内容,也许一开始记住这些含义会很有用:
这是文章中所有示例的集合:https://codepen.io/collection/xKwgdW