布局和包含块
元素的大小和位置通常会受到其**包含块**的影响。大多数情况下,包含块是元素最近的**块级**祖先的**内容区域**,但这并非总是如此。在本文中,我们将探讨确定元素包含块的因素。
当用户代理(如您的浏览器)布局文档时,它会为每个元素生成一个盒子。每个盒子被分成四个区域
- 内容区域
- 填充区域
- 边框区域
- 外边距区域
许多开发人员认为元素的包含块始终是其父元素的内容区域,但这并不一定正确。让我们研究一下决定元素包含块的因素。
包含块的影响
在了解是什么决定了元素的包含块之前,了解它为什么重要是有帮助的。
元素的大小和位置通常会受到其包含块的影响。应用于绝对定位元素的**width
**、**height
**、**padding
**、**margin
**和偏移属性的百分比值(即其**position
**设置为**absolute
**或**fixed
**)是根据元素的包含块计算的。
识别包含块
识别包含块的过程完全取决于元素的**position
**属性的值
- 如果**
position
**属性是**static
**、**relative
**或**sticky
**,则包含块由最近祖先元素的内容框边缘形成,该祖先元素要么是**块级容器**(例如内联块、块或列表项元素),要么**建立格式化上下文**(例如表格容器、flex 容器、网格容器或块级容器本身)。 - 如果**
position
**属性是**absolute
**,则包含块由最近祖先元素的填充框边缘形成,该祖先元素的**position
**值不为**static
**(**fixed
**、**absolute
**、**relative
**或**sticky
**)。 - 如果**
position
**属性是**fixed
**,则包含块由**视窗**(在连续媒体的情况下)或页面区域(在分页媒体的情况下)建立。 - 如果**
position
**属性是**absolute
**或**fixed
**,则包含块也可以由最近祖先元素的填充框边缘形成,该祖先元素具有以下任何属性- **
filter
**、**backdrop-filter
**、**transform
**或**perspective
**值不为**none
**。 - 当
contain
属性的值为layout
、paint
、strict
或content
(例如contain: paint;
)时。 - 当
container-type
属性的值不为normal
时。 - 当
will-change
属性的值包含一个属性,该属性的非初始值会形成包含块(例如filter
或transform
)时。 - 当
content-visibility
属性的值为auto
时。
- **
注意: 根元素(<html>
)所在的包含块是一个称为初始包含块的矩形。它的尺寸与视窗(对于连续媒体)或页面区域(对于分页媒体)的尺寸相同。
注意: 浏览器在 perspective
和 filter
属性是否参与形成包含块方面存在不一致。
从包含块计算百分比值
一些示例
我们所有示例的 HTML 代码如下:
<body>
<section>
<p>This is a paragraph!</p>
</section>
</body>
以下每个示例中只更改 CSS。
示例 1
在本例中,段落是静态定位的,因此它的包含块是 <section>
,因为它是最接近的祖先,并且是一个块级容器(由于 display: block
)。
body {
background: beige;
}
section {
display: block;
width: 400px;
height: 160px;
background: lightgray;
}
p {
width: 50%; /* == 400px * .5 = 200px */
height: 25%; /* == 160px * .25 = 40px */
margin: 5%; /* == 400px * .05 = 20px */
padding: 5%; /* == 400px * .05 = 20px */
background: cyan;
}
示例 2
在本例中,段落的包含块是 <body>
元素,因为 <section>
不是一个块级容器(由于 display: inline
),并且没有建立格式化上下文。
body {
background: beige;
}
section {
display: inline;
background: lightgray;
}
p {
width: 50%; /* == half the body's width */
height: 200px; /* Note: a percentage would be 0 */
background: cyan;
}
示例 3
在本例中,段落的包含块是 <section>
,因为后者的 position
是 absolute
。段落的百分比值受其包含块的 padding
影响,但是如果包含块的 box-sizing
值为 border-box
,则不会发生这种情况。
body {
background: beige;
}
section {
position: absolute;
left: 30px;
top: 30px;
width: 400px;
height: 160px;
padding: 30px 20px;
background: lightgray;
}
p {
position: absolute;
width: 50%; /* == (400px + 20px + 20px) * .5 = 220px */
height: 25%; /* == (160px + 30px + 30px) * .25 = 55px */
margin: 5%; /* == (400px + 20px + 20px) * .05 = 22px */
padding: 5%; /* == (400px + 20px + 20px) * .05 = 22px */
background: cyan;
}
示例 4
在本例中,段落的 position
是 fixed
,因此它的包含块是初始包含块(在屏幕上,是视窗)。因此,段落的尺寸会根据浏览器窗口的大小而变化。
body {
background: beige;
}
section {
width: 400px;
height: 480px;
margin: 30px;
padding: 15px;
background: lightgray;
}
p {
position: fixed;
width: 50%; /* == (50vw - (width of vertical scrollbar)) */
height: 50%; /* == (50vh - (height of horizontal scrollbar)) */
margin: 5%; /* == (5vw - (width of vertical scrollbar)) */
padding: 5%; /* == (5vw - (width of vertical scrollbar)) */
background: cyan;
}
示例 5
在本例中,段落的 position
是 absolute
,因此它的包含块是 <section>
,它是具有非 none
的 transform
属性的最接近的祖先。
body {
background: beige;
}
section {
transform: rotate(0deg);
width: 400px;
height: 160px;
background: lightgray;
}
p {
position: absolute;
left: 80px;
top: 30px;
width: 50%; /* == 200px */
height: 25%; /* == 40px */
margin: 5%; /* == 20px */
padding: 5%; /* == 20px */
background: cyan;
}
另请参阅
all
属性contain
属性aspect-ratio
属性box-sizing
属性min-content
和max-content
尺寸值- 构建块:在 CSS 中对项目进行尺寸设置
- 盒子模型
- CSS 盒模型 模块
- 布局模式
- 视觉格式化模型
- 块级格式化上下文
- 堆叠上下文
- 边距折叠
- 初始、计算、使用 和 实际 值
- 替换元素
- 内在尺寸