包含块
一、认识
元素的尺寸及位置,常常会受它的**包含块(containing block
)**所影响。对于一些属性,例如 width
, height
, padding
, margin
,绝对定位元素的偏移值(比如 position
被设置为 absolute
或 fixed
),当我们对其赋予百分比值时,这些值的计算值,就是通过元素的包含块计算得来。
二、规则
确定一个元素的包含块的过程完全依赖于这个元素的position
属性:
-
如果
position
属性为static
、relative
或sticky
时: 包含块可能由它的最近的祖先块元素(比如说inline-block
,block
或list-item
元素)的内容区的边缘组成,也可能会建立格式化上下文 -
如果
position
属性为absolute
, 包含块就是由它的最近的position
的值不是static
(也就是值为fixed
,absolute
,relative
或sticky
)的祖先元素的内边距区的边缘组成。 -
如果
position
属性是fixed
,在连续媒体的情况下 (continuous media
) 包含块是viewport
,在分页媒体 (paged media
) 下的情况下包含块是分页区域 (page area
)。 -
如果
position
属性是absolute
或fixed
,包含块也可能是由满足以下条件的最近父级元素的内边距区的边缘组成的:-
transform
或perspective
的值不是none
-
will-change
的值是transform
或perspective
-
filter
的值不是none
或will-change
的值是filter
-
contain
的值是paint
-
backdrop-filter
的值不是none
-
三、计算
如果某些属性被赋予一个百分值的话,它的计算值是由这个元素的包含块计算而来的。这些属性包括盒模型属性和偏移属性
-
要计算
height
、top
及bottom
中的百分值, 是通过包含块的height
的值。如果包含块的height
值会根据它的内容变化,而且包含块的position
属性的值被赋予relative
或static
,那么,这些值的计算值为auto
。 -
要计算
width
,left
,right
,padding
,margin
这些属性由包含块的width
属性的值来计算它的百分值。
3.1 计算 margin 百分比
margin
百分比 根据包含块的 width
值计算得出
-
box-sizing: content-box
时:实时编辑器function Test(props) { const parent = { width: "400px", height: "400px", padding: "24px", position: "relative", backgroundColor: "red", boxSizing: "content-box", border: "10px solid black", } const child = { width: "40px", height: "40px", margin: "20%", position: "absolute", backgroundColor: "blue" } return ( <div style={ parent }> <div style={ child }></div> </div> ); }
结果Loading...包含块宽度:
parentWidth + 2 * parentPadding
=400 + 2 * 24
=448
child 水平 margin:
child margin-left
=child margin-right
=包含块宽度 * 20%
child 垂直 margin:
child margin-top
=child margin-bottom
=包含块宽度 * 20%
-
box-sizing: border-box
时:实时编辑器function Test(props) { const parent = { width: "400px", height: "400px", padding: "24px", position: "relative", backgroundColor: "red", boxSizing: "border-box", border: "10px solid black", } const child = { width: "40px", height: "40px", margin: "20%", position: "absolute", backgroundColor: "blue" } return ( <div style={ parent }> <div style={ child }></div> </div> ); }
结果Loading...包含块宽度:
parentWidth - 2 * border
=400 - 2 * 10
=380
child 水平 margin:
child margin-left
=child margin-right
=包含块宽度 * 20%
child 垂直 margin:
child margin-top
=child margin-bottom
=包含块宽度 * 20%
3.2 计算 padding 百分比
padding
百分比 根据包含块的 width
值计算得出
-
box-sizing: content-box
时:实时编辑器function Test(props) { const parent = { width: "400px", height: "400px", padding: "24px", position: "relative", backgroundColor: "red", boxSizing: "content-box", border: "10px solid black", } const child = { padding: "20%", position: "absolute", backgroundColor: "blue" } return ( <div style={ parent }> <div style={ child }></div> </div> ); }
结果Loading...包含块宽度:
parentWidth + 2 * parentPadding
=400 + 2 * 24
=448
child 水平 padding:
child padding-left
=child padding-right
=包含块宽度 * 20%
child 垂直 padding:
child padding-top
=child padding-bottom
=包含块宽度 * 20%
-
box-sizing: border-box
时:实时编辑器function Test(props) { const parent = { width: "400px", height: "400px", padding: "24px", position: "relative", backgroundColor: "red", boxSizing: "border-box", border: "10px solid black", } const child = { padding: "20%", position: "absolute", backgroundColor: "blue" } return ( <div style={ parent }> <div style={ child }></div> </div> ); }
结果Loading...包含块宽度:
parentWidth - 2 * border
=400 - 2 * 10
=380
child 水平 padding:
child padding-left
=child padding-right
=包含块宽度 * 20%
child 垂直 padding:
child padding-top
=child padding-bottom
=包含块宽度 * 20%
3.3 计算 relative 包含块大小
relative
元素的包含块由最近的祖先块元素内容区的边缘组成, 即content
function Test(props) { const parent = { width: "400px", height: "400px", padding: "24px", position: "relative", backgroundColor: "red", boxSizing: "content-box", border: "10px solid black", } const child = { width: "20%", height: "20%", position: "relative", bottom: "24px", right: "0", backgroundColor: "blue" } return ( <div style={ parent }> <div style={ child }></div> </div> ); }
包含块宽度: parentWidth
3.4 计算 absolute 包含块大小
position: absolute
元素的包含块由它的最近的非 static
祖先元素的内边距区的边缘组成, 也就是 padding + content
。当这样的祖先元素不存在时, 则相对于 ICB
(inital container block, 初始包含块)
-
box-sizing: content-box
时:实时编辑器function Test(props) { const parent = { width: "400px", height: "400px", padding: "24px", position: "relative", backgroundColor: "red", boxSizing: "content-box", border: "10px solid black", } const child = { width: "50%", // 包含块宽度 = parentWidth + 2 * parentPadding height: "50%", // 包含块高度 = parentHeight + 2 * parentPadding position: "absolute", backgroundColor: "blue" } return ( <div style={ parent }> <div style={ child }></div> </div> ); }
结果Loading... -
box-sizing: border-box
时:实时编辑器function Test(props) { const parent = { width: "400px", height: "400px", padding: "24px", position: "relative", backgroundColor: "red", boxSizing: "border-box", border: "10px solid black", } const child = { width: "50%", // 包含块宽度 = parentWidth - 2 * parentBorder height: "50%", // 包含块高度 = parentHeight - 2 * parentBorder position: "absolute", backgroundColor: "blue" } return ( <div style={ parent }> <div style={ child }></div> </div> ); }
结果Loading...
3.5 计算 absolute 百分比宽度
-
box-sizing: content-box
时:实时编辑器function Test(props) { const parent = { width: "400px", height: "400px", padding: "24px", position: "relative", backgroundColor: "red", boxSizing: "content-box", border: "10px solid black", } const child = { width: "50%", // child 宽度 = child 的包含块宽度 / 2 height: "50%", // child 高度 = child 的包含块高度 / 2 position: "absolute", backgroundColor: "blue" } return ( <div style={ parent }> <div style={ child }></div> </div> ); }
结果Loading... -
box-sizing: border-box
时:实时编辑器function Test(props) { const parent = { width: "400px", height: "400px", padding: "24px", position: "relative", backgroundColor: "red", boxSizing: "border-box", border: "10px solid black", } const child = { width: "50%", // child 宽度 = child 的包含块宽度 / 2 height: "50%", // child 高度 = child 的包含块高度 / 2 position: "absolute", backgroundColor: "blue" } return ( <div style={ parent }> <div style={ child }></div> </div> ); }
结果Loading...
3.6 计算 fixed 屏幕视口包含块大小
fixed
元素的包含块默认由屏幕视口viewport
的内容区边缘组成, 即content
function Test(props) { const parent = { width: "400px", height: "400px", padding: "24px", position: "relative", backgroundColor: "red", boxSizing: "content-box", border: "10px solid black", } const child = { width: "20%", height: "20%", position: "fixed", bottom: "24px", right: "0", backgroundColor: "blue" } return ( <div style={ parent }> <div style={ child }></div> </div> ); }
包含块宽度: htmlWidth
3.7 计算 fixed 祖先元素包含块大小
fixed
元素的祖先元素中transform
、perspective
、filter
或 backdrop-filter
属性非 none
时,包含块由该祖先的内边距边缘组成,即content + padding
function Test(props) { const parent = { width: "400px", height: "400px", padding: "24px", position: "relative", backgroundColor: "red", boxSizing: "content-box", border: "10px solid black", transform: "scale(1)" } const child = { width: "20%", height: "20%", position: "fixed", bottom: "24px", right: "0", backgroundColor: "blue" } return ( <div style={ parent }> <div style={ child }></div> </div> ); }
包含块宽度: parentWidth + 2 * parentPadding