佈局和包含塊
一個元素的尺寸和位置通常受其包含塊的影響。大多數情況下,包含塊是該元素最近的塊級祖先元素的內容區,但情況並非總是如此。在本文中,我們將探討決定元素包含塊的因素。
當用戶代理(如你的瀏覽器)佈局一個文件時,它會為每個元素生成一個盒子。每個盒子被分為四個區域:
- 內容區
- 內邊距區
- 邊框區
- 外邊距區

許多開發者認為,元素的包含塊總是其父元素的內容區,但這不一定正確。讓我們來研究一下決定元素包含塊的因素。
包含塊的影響
在學習什麼決定了元素的包含塊之前,瞭解它為什麼重要是很有用的。
元素的尺寸和位置通常受其包含塊的影響。應用於元素的 width、height、padding、margin,以及絕對定位元素(即其 position 設定為 absolute 或 fixed)的偏移屬性的百分比值,都是根據其包含塊計算的。
確定包含塊
確定包含塊的過程完全取決於元素 position 屬性的值:
- 如果
position屬性是static、relative或sticky,包含塊由最近的祖先元素的內容盒(content box)的邊緣構成,該祖先元素要麼是塊容器(例如 inline-block、block 或 list-item 元素),要麼建立了格式化上下文(例如 table 容器、flex 容器、grid 容器或塊容器本身)。 - 如果
position屬性是absolute,包含塊由最近的position值不是static(即fixed、absolute、relative或sticky)的祖先元素的內邊距盒(padding box)的邊緣構成。 - 如果
position屬性是fixed,包含塊由視口(對於連續媒體)或頁面區域(對於分頁媒體)建立。 - 如果
position屬性是absolute或fixed,包含塊也可能由最近的具有以下任一屬性的祖先元素的內邊距盒(padding box)的邊緣構成:- 一個值不為
none的filter、backdrop-filter、transform或perspective屬性。 contain屬性的值為layout、paint、strict或content(例如,contain: paint;)。container-type的值不為normal。will-change屬性的值包含某個屬性,該屬性的非初始值會形成包含塊(例如filter或transform)。content-visibility屬性的值為auto。
- 一個值不為
備註: 根元素(<html>)所在的包含塊是一個被稱為初始包含塊的矩形。它的尺寸為視口(對於連續媒體)或頁面區域(對於分頁媒體)的大小。
備註: 在 perspective 和 filter 屬性對包含塊形成的影響上存在瀏覽器不一致性。
根據包含塊計算百分比值
如上所述,當某些屬性被賦予百分比值時,其計算值取決於元素的包含塊。以這種方式工作的屬性是盒模型屬性和偏移屬性:
height、top和bottom屬性根據包含塊的height來計算百分比值。width、left、right、padding和margin屬性根據包含塊的width來計算百分比值。
備註: 一個塊容器(如 inline-block、block 或 list-item 元素)要麼只包含參與行內格式化上下文的行內級盒子,要麼只包含參與塊級格式化上下文的塊級盒子。一個元素只有在它包含塊級或行內級盒子時才是塊容器。
一些示例
我們所有示例的 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 盒模型模組
- 佈局模式
- 視覺格式化模型
- 塊格式化上下文
- 層疊上下文
- 外邊距摺疊
- 初始值、計算值、使用值和實際值
- 替換元素
- 固有尺寸