首先,感謝博主doyeo(CSS探索之旅)!
轉載自doyeo(CSS探索之旅)的視覺格式化模型中的各種框,具體戳這裏->視覺格式化模型中的各種框
在聊這個話題之前,我們可能得先簡單說說 視覺格式化模型
這個概念。
視覺格式化模型
的全稱是 Visual formatting model
,它被用來描述用戶代理(比如瀏覽器)在圖形媒體下如何處理文檔樹。
在 視覺格式化模型
中,每個文檔樹的元素會根據框模型產生零到多個框(boxes)。這些框的佈局取決於框的尺寸,類型,定位方式(正常流,浮動和絕對定位),元素之間的關係和外部信息(例如:視口 ① 大小,置換元素的固有尺寸等等)。
舉個最簡單的例子來講,假設一個頁面上有2個div,那麼第2個div的位置會取決第1個div的高度定義;假設更復雜一點,第1個div是浮動的,那麼第2個div的位置還要取決於第1個div的寬度。
不同類型的框
在 CSS
中,可能會產生不同類型的框,框的類型取決於 display
屬性的設定。某種程度上,框的類型會影響其在視覺格式化模型中的表現。接下來會詳細的聊聊這些不同類型的框以及它們在視覺可視化模型中的表現。
在說這個之前,我們先回憶一下,大家常說的一些名詞:
- Containing block(包含塊)
- Block-level element(塊級元素)
- Block element(塊元素)
- Block-level box(塊級框), Block container box(塊容器框), Block box(塊框)
- Inline-level element(行內級元素)
- Inline element(行內元素)
- Inline-level box(行內級框), Atomic inline-level box(原子行內級框), Inline box(行內框)
- Anonymous boxes(匿名框)
包含塊
首先,來看看什麼是 包含塊
?這個說及 CSS
一般的都會提及的基本概念。
一個元素,它的框的尺寸和位置會相對於一個特定的矩形框邊緣來計算而得到,這個特定的矩形框稱之爲該元素的 包含塊
。
(爲)一個元素生成的框通常會充當其子框的包含塊;當我們叫一個 框的包含塊
時,其實表達的是 該框所處的包含塊
,而不是其自身產生的包含塊。
每個框相對於其包含塊(該框所處的包含塊
)都會被給予一個位置,不過該框並不侷限在包含塊內,有可能會溢出,通常這個時候你會藉助 overflow
屬性來進行處理。
除了說什麼是包含塊,這裏順帶再介紹一下生成包含塊的一些特殊場景:
- 由根元素生成的包含塊叫做
初始包含塊(initial containing block)
。 對於其它元素,如果元素的
position
值是relative
或者static
,其包含塊由最近的祖先塊容器框
的內容邊界(如果想知道什麼是內容邊界,可以先看看CSS盒模型)形成。舉個例子,
td
,th
就算有父容器tr
,但它們的包含塊卻是由table
生成,因爲table
是塊容器框
而tr
不是絕對定位元素的包含塊由最近的定位(
position
值非static
)祖先生成,如果不存在這樣的祖先,則採用初始包含塊;- 固定定位元素(
position: fixed
)的包含塊一般情況下都由視口 ① 生成;
說了這幾個特殊的情景,你會發現並不是所有的包含塊都是由父元素所生成。
什麼是塊級元素?
塊級元素是那些視覺上會被格式化成塊狀的元素,通俗一點來說就是那些會換新行的元素。display
屬性的:block
, list-item
, table
, flex
, grid
值都可以將一個元素設置成塊級元素。
舉個例子來說,
li
是一個塊級元素
,但也有人會說它是一個塊元素
。嗯,li
確實是一個塊級元素,但並不是一個塊元素,爲什麼?
什麼是塊元素?
塊元素是 display
屬性值爲 block
的元素,它應該是 塊級元素
的一個子集,而不是等同的,一個 塊元素
是一個 塊級元素
,但一個 塊級元素
不一定是一個 塊元素
,所以不要混淆。
塊級框,塊容器框,塊框
什麼是塊級框?
塊級元素生成塊級框,這些框會參與某些 BFC
。每個塊級元素都會生成一個主要的塊級框來包含其子框和生成的內容,同時任何定位方式都會與這個主要的塊級框有關。
某些塊級元素還會在主要的塊級框之外產生額外的框:例如 list-item
元素,它需要生成一個額外的框用於包含 list-style-type
。這些額外的框會相對於主要的塊級框來進行排版。
什麼是塊容器框?
一個 塊容器框
要麼只包含 塊級框
,要麼創建一個 IFC
而只包含 行內級框
,但不能同時包含 塊級框
和 行內級框
。
除了 table框
和 置換元素
,一個 塊級框
同時也是一個 塊容器框
。非置換的行內塊
和 單元格
是 塊容器
但不是 塊級框
。
並不是所有的 塊級框
都是 塊容器框
,也並不是所有的 塊容器框
都是 塊級框
。
塊級框
和 塊容器框
的另外一個重要的區別是:塊級框
需要能夠包含其生成的內容,但 塊容器框
並不需要。這是什麼意思呢?簡單的解釋一下:
比如一個
iframe
其內容由src
屬性所決定,這可以當成是生成的內容,所以iframe
是一個塊級框
但卻不是塊容器框
什麼是塊框?
簡要的來說,是 塊容器
的 塊級框
稱之爲 塊框
。
可以通過下面這個圖來快速的梳理清楚這3者之間的聯繫:
(圖一)說完了塊級框,接下來說說行內級框
什麼是行內級元素?
行內級元素是那些不會爲自身內容形成新的塊,而讓內容分佈在多行中的元素。display
屬性的:inline
, inline-table
, inline-block
, inline-flex
, inline-grid
值都可以將一個元素設置成行內級元素。
什麼是行內元素?
如同塊元素之於塊級元素的關係,行內元素僅僅是 display
屬性值爲 inline
的元素,這裏不再贅述。
行內級框,原子行內級框,行內框
行內級元素生成行內級框,而這些框會參與某個 IFC
。一個 行內框
是 行內級框
,且其內容參與了包含它的 IFC
。一個 display
值是 inline
的非置換元素會生成一個行內框。那些不是行內框的行內級框(例如行內級置換元素、行內塊元素、行內表格元素)被稱爲 原子行內級框
,因爲它們是以單一不透明框的形式來參與其 IFC
的。
細心的你會發現並沒有一個 行內容器框
與 塊容器框
相對應,但卻多了一個 原子行內級框
。並且有趣的是行內塊
(包括置換和非置換元素)是原子行內級框
,而非置換行內塊
卻同時還是塊容器框
。
匿名框
匿名框
包括 匿名塊框
和 匿名行內框
。
假設一個 div
中包含有一個 p
和一段純文本 xxx
。由於 塊容器框
只允許要麼包含 塊級框
,要麼包含 行內級框
,所以,爲了符合這種情況,div
會生成一個匿名的塊級框用於包裹 xxx
,這個匿名框就叫做 匿名塊框
。
我們拿 W3C
上的一個例子來加深對匿名塊框的印象:
1 2 3 4 | <div> Some text <p>More text</p> </div> |
與此同時,我們將上面的代碼稍微改一下,將 p
變成 span
:
1 2 3 4 | <div> Some text <span>More text</span> </div> |
div
生成一個塊框,More text
由 span
生成一個行內框,由於 Some text
沒有與之相關的行級元素,將由 div
爲其生成一個行內框用以包裹,這個框稱爲匿名行內框。如圖四:
假設一個匿名框的類型可根據上下文來清晰界定,則 匿名行內框
和 匿名塊框
都可被簡稱爲 匿名框
。
匿名框的繼承屬性會從包含它的非匿名框那裏繼承,非繼承屬性取其初始值。
附註:
- ① 用戶代理一般會向用戶提供一個載體(屏幕上的一個窗口或其它可視區域)用以訪問文檔,這個載體就叫做
視口
。用戶代理可以在視口大小被調整時改變文檔的佈局。如果視口小於渲染文檔的畫布區域,用戶代理應當提供一個滾動機制。每個畫布只能擁有一個視口,但用戶代理可以把文檔渲染至多個畫布上(即爲相同文檔提供不同的視圖)。
說明:
文章中作者說了:由根元素生成的包含塊叫做 初始包含塊(initial containing block),
在前端html中,根元素爲html,這說明初始包含塊就是附註中的視口(viewport)即瀏覽器窗口,只是我們習慣這樣稱~
如果覺得還是有點繞,這兒有篇實戰文章供參考:css絕對定位中的初始包含塊問題