正常流中的塊級和行內佈局
在本指南中,我們將探討塊級元素和行級元素在作為常規流的一部分時的基本行為。
常規流在 CSS 2.1 規範中定義,該規範解釋說,常規流中的任何框都將是格式化上下文的一部分。它們可以是塊級的或行級的,但不能同時是兩者。我們稱塊級框參與塊格式化上下文,行級框參與行格式化上下文。
具有塊級或行級格式化上下文的元素的行為也在此規範中定義。對於具有塊級格式化上下文的元素,規範中說:
“在塊格式化上下文中,盒子在包含塊中自上而下地垂直的一個接一個地排列。兩個兄弟盒子之間的垂直距離由 'margin' 屬性決定。在塊格式化上下文中,相鄰的塊級盒子之間的垂直外邊距會合並。”
“在塊格式化上下文中,每個盒子的左外邊緣都接觸包含塊的左邊緣(對於從右到左的格式,則右邊緣接觸)。” - 9.4.1
對於具有行級格式化上下文的元素:
“在行內格式化上下文中,盒子在包含塊中從上到下水平地一個接一個地排列。這些盒子之間的水平外邊距、邊框和內邊距都會被保留。盒子在垂直方向上可以以不同的方式對齊:它們的底部或頂部可以對齊,或者它們內部文字的基線可以對齊。包含形成一行的盒子的矩形區域稱為行盒。” - 9.4.2
請注意,CSS 2.1 規範將文件描述為處於水平的、從上到下的書寫模式。例如,透過描述塊級框之間的垂直距離。在垂直書寫模式下,塊級元素和行級元素的行為是相同的;我們在流式佈局和書寫模式指南中探討了這一點。
參與塊格式化上下文的元素
在像英語這樣的水平書寫模式中,塊級元素會垂直佈局,一個在另一個下面。

在垂直書寫模式中,它們將水平佈局。

在本指南中,我們將使用英語,因此是水平書寫模式。然而,如果你的文件是垂直書寫模式,所描述的一切都應該以相同的方式工作。
正如規範中所定義的,兩個塊級框之間的外邊距是建立元素之間分隔的原因。我們可以透過兩個段落的佈局看到這一點,我為它們添加了邊框。預設的瀏覽器樣式表透過為段落的頂部和底部新增外邊距來增加它們之間的間距。
<div class="box">
<p>
One November night in the year 1782, so the story runs, two brothers sat
over their winter fire in the little French town of Annonay, watching the
grey smoke-wreaths from the hearth curl up the wide chimney. Their names
were Stephen and Joseph Montgolfier, they were papermakers by trade, and
were noted as possessing thoughtful minds and a deep interest in all
scientific knowledge and new discovery.
</p>
<p>
Before that night—a memorable night, as it was to prove—hundreds of millions
of people had watched the rising smoke-wreaths of their fires without
drawing any special inspiration from the fact.
</p>
</div>
p {
border: 2px solid green;
}
如果我們將段落元素的外邊距設定為 0,那麼邊框將會接觸。
<div class="box">
<p>
One November night in the year 1782, so the story runs, two brothers sat
over their winter fire in the little French town of Annonay, watching the
grey smoke-wreaths from the hearth curl up the wide chimney. Their names
were Stephen and Joseph Montgolfier, they were papermakers by trade, and
were noted as possessing thoughtful minds and a deep interest in all
scientific knowledge and new discovery.
</p>
<p>
Before that night—a memorable night, as it was to prove—hundreds of millions
of people had watched the rising smoke-wreaths of their fires without
drawing any special inspiration from the fact.
</p>
</div>
p {
border: 2px solid green;
margin: 0;
}
預設情況下,塊級元素會佔據行內方向上的所有空間,所以我們的段落在其包含塊內會盡可能地展開。如果我們給它們一個寬度,它們仍然會一個接一個地垂直佈局——即使有空間讓它們並排。每一個都將從包含塊的起始邊緣開始,也就是在該書寫模式下句子開始的地方。
<div class="box">
<p>
One November night in the year 1782, so the story runs, two brothers sat
over their winter fire in the little French town of Annonay, watching the
grey smoke-wreaths from the hearth curl up the wide chimney. Their names
were Stephen and Joseph Montgolfier, they were papermakers by trade, and
were noted as possessing thoughtful minds and a deep interest in all
scientific knowledge and new discovery.
</p>
<p>
Before that night—a memorable night, as it was to prove—hundreds of millions
of people had watched the rising smoke-wreaths of their fires without
drawing any special inspiration from the fact.
</p>
</div>
p {
border: 2px solid green;
width: 40%;
}
外邊距摺疊
規範解釋說,塊級元素之間的外邊距會合併。這意味著,如果你有一個帶上外邊距的元素緊跟著一個帶下外邊距的元素,那麼總空間不是這兩個外邊距之和,而是外邊距會合並,最終會變得和兩個外邊距中較大的那個一樣大。
在下面的例子中,段落的上外邊距為 20px,下外邊距為 40px。段落之間的外邊距大小為 40px,因為第二個段落較小的上外邊距與第一個段落較大的下外邊距合併了。
<div class="box">
<p>
One November night in the year 1782, so the story runs, two brothers sat
over their winter fire in the little French town of Annonay, watching the
grey smoke-wreaths from the hearth curl up the wide chimney. Their names
were Stephen and Joseph Montgolfier, they were papermakers by trade, and
were noted as possessing thoughtful minds and a deep interest in all
scientific knowledge and new discovery.
</p>
<p>
Before that night—a memorable night, as it was to prove—hundreds of millions
of people had watched the rising smoke-wreaths of their fires without
drawing any special inspiration from the fact.
</p>
</div>
p {
border: 2px solid green;
margin: 20px 0 40px 0;
}
你可以在我們的文章掌握外邊距合併中閱讀更多關於外邊距合併的內容。
注意: 如果你不確定外邊距是否正在合併,請檢查瀏覽器開發者工具中的盒模型值。這將為你提供外邊距的實際大小,有助於你識別正在發生的情況。

參與行格式化上下文的元素
行級元素按照特定書寫模式中句子的走向一個接一個地顯示。雖然我們通常不認為行級元素有盒子,但和 CSS 中的所有東西一樣,它們確實有。這些行級框一個接一個地排列。如果包含塊中沒有足夠的空間容納所有的框,一個框可以換到新的一行。建立的這些行被稱為行盒。
在下面的例子中,我們有三個由一個段落和一個 <strong> 元素建立的行級框。
<p>
Before that night—<strong>a memorable night</strong>, as it was to
prove—hundreds of millions of people had watched the rising smoke-wreaths of
their fires without drawing any special inspiration from the fact.
</p>
在 <strong> 元素之前和 </strong> 元素之後的單詞周圍的框被稱為匿名盒,這些框被引入以確保所有東西都被包裹在盒子裡,但是我們不能直接選擇它們。
行盒在塊級方向上的尺寸(在英語中即高度)由其內部最高的盒子定義。在下一個例子中,<strong> 元素的字型大小為 300%;由於該內容跨越兩行,它現在定義了這兩行的行盒高度。
<p>
Before that night—<strong>a memorable night</strong>, as it was to
prove—hundreds of millions of people had watched the rising smoke-wreaths of
their fires without drawing any special inspiration from the fact.
</p>
strong {
font-size: 300%;
}
在我們的視覺格式化模型指南中瞭解更多關於塊級和行級框的行為。
display 屬性和流式佈局
除了 CSS2.1 中存在的規則外,新級別的 CSS 進一步描述了塊級和行級框的行為。display 屬性定義了一個盒子及其內部任何盒子的行為。在 CSS Display Model Level 3 中,我們可以更多地瞭解 display 屬性如何改變盒子及其生成的盒子的行為。
一個元素的顯示型別定義了其外部顯示型別;這決定了該盒子如何與同一格式化上下文中的其他元素一起顯示。它還定義了內部顯示型別,這決定了該元素內部的盒子如何行為。在考慮彈性佈局時,我們可以非常清楚地看到這一點。在下面的例子中,我有一個 <div>,我給它設定了 display: flex。這個彈性容器的行為像一個塊級元素:它顯示在新的一行,並佔據了行內方向上所有可用的空間。這是 block 的外部顯示型別。
然而,彈性專案參與的是彈性格式化上下文,因為它們的父元素是帶有 display: flex 的元素,其內部顯示型別為 flex,為直接子元素建立了彈性格式化上下文。
<div class="container">
<div>Flex Item</div>
<div>Flex Item</div>
<div>
<div>Children</div>
<div>are in</div>
<div>normal flow</div>
</div>
</div>
.container {
display: flex;
}
.container > * {
border: 1px solid green;
}
因此,你可以認為 CSS 中的每個盒子都以這種方式工作。盒子本身有一個外部顯示型別,所以它知道如何與其他盒子一起表現。然後它有一個內部顯示型別,這改變了其子元素的行為方式。這些子元素也同樣有外部和內部顯示型別。前面例子中的彈性專案變成了彈性級盒子,所以它們的外部顯示型別是由它們作為彈性格式化上下文一部分的方式決定的。然而,它們的內部顯示型別是流,這意味著它們的子元素參與常規流。除非有東西改變了它們的顯示型別,否則我們彈性專案內部的巢狀專案會像塊級和行級元素一樣佈局自己。
外部和內部顯示型別的這個概念很重要,因為它告訴我們,一個使用像彈性盒子(display: flex)和網格佈局(display: grid)這樣的佈局方法的容器,仍然在參與塊級和行級佈局,因為這些方法的外部顯示型別是 block。
更改元素參與的格式化上下文
瀏覽器根據對該元素通常有意義的方式,在塊級或行級格式化上下文中顯示專案。例如,<strong> 元素用於強烈強調一段內容,並且在瀏覽器中預設以粗體顯示。讓那個 <strong> 元素作為一個塊級元素顯示,換到新的一行,通常是沒有意義的。如果你確實想讓所有的 <strong> 元素都顯示為塊級框,你可以透過設定 strong { display: block; } 來做到。使用 CSS 為內容設定樣式的能力意味著你總是可以使用最合適的語義化 HTML 元素來標記你的內容,然後用 CSS 來改變它們的顯示方式。
<p>
Before that night—<strong>a memorable night</strong>, as it was to
prove—hundreds of millions of people had watched the rising smoke-wreaths of
their fires without drawing any special inspiration from the fact.
</p>
strong {
display: block;
}
總結
在本指南中,我們探討了元素如何在常規流中作為塊級和行級元素顯示。由於這些元素的預設行為,一個沒有任何 CSS 樣式的 HTML 文件,將以可讀的方式顯示。透過理解常規流的工作原理,你會發現佈局更容易,因為你理解了改變元素顯示方式的起點。