視覺格式化模型中的各種框

2018-02-24 15:22 更新

視覺格式化模型中的各種框

原作者:doyoe
原文鏈接:http://blog.doyoe.com/2015/03/09/css/%E8%A7%86%E8%A7%89%E6%A0%BC%E5%BC%8F%E5%8C%96%E6%A8%A1%E5%9E%8B%E4%B8%AD%E7%9A%84%E5%90%84%E7%A7%8D%E6%A1%86/

在聊這個(gè)話題之前,我們可能得先簡(jiǎn)單說說 視覺格式化模型 這個(gè)概念。

視覺格式化模型 的全稱是 Visual formatting model,它被用來描述用戶代理(比如瀏覽器)在圖形媒體下如何處理文檔樹。

視覺格式化模型 中,每個(gè)文檔樹的元素會(huì)根據(jù)框模型產(chǎn)生零到多個(gè)框(boxes)。這些框的布局取決于框的尺寸,類型,定位方式(正常流,浮動(dòng)和絕對(duì)定位),元素之間的關(guān)系和外部信息(例如:視口 ① 大小,置換元素的固有尺寸等等)。

舉個(gè)最簡(jiǎn)單的例子來講,假設(shè)一個(gè)頁面上有2個(gè)div,那么第2個(gè)div的位置會(huì)取決第1個(gè)div的高度定義;假設(shè)更復(fù)雜一點(diǎn),第1個(gè)div是浮動(dòng)的,那么第2個(gè)div的位置還要取決于第1個(gè)div的寬度。

不同類型的框

CSS 中,可能會(huì)產(chǎn)生不同類型的框,框的類型取決于 display 屬性的設(shè)定。某種程度上,框的類型會(huì)影響其在視覺格式化模型中的表現(xiàn)。接下來會(huì)詳細(xì)的聊聊這些不同類型的框以及它們?cè)谝曈X可視化模型中的表現(xiàn)。

在說這個(gè)之前,我們先回憶一下,大家常說的一些名詞:

  • Containing block(包含塊)
  • Block-level element(塊級(jí)元素)
  • Block element(塊元素)
  • Block-level box(塊級(jí)框), Block container box(塊容器框), Block box(塊框)
  • Inline-level element(行內(nèi)級(jí)元素)
  • Inline element(行內(nèi)元素)
  • Inline-level box(行內(nèi)級(jí)框), Atomic inline-level box(原子行內(nèi)級(jí)框), Inline box(行內(nèi)框)
  • Anonymous boxes(匿名框)

包含塊

首先,來看看什么是 包含塊?這個(gè)說及 CSS 一般的都會(huì)提及的基本概念。

一個(gè)元素,它的框的尺寸和位置會(huì)相對(duì)于一個(gè)特定的矩形框邊緣來計(jì)算而得到,這個(gè)特定的矩形框稱之為該元素的 包含塊

(為)一個(gè)元素生成的框通常會(huì)充當(dāng)其子框的包含塊;當(dāng)我們叫一個(gè) 框的包含塊 時(shí),其實(shí)表達(dá)的是 該框所處的包含塊,而不是其自身產(chǎn)生的包含塊。

每個(gè)框相對(duì)于其包含塊(該框所處的包含塊)都會(huì)被給予一個(gè)位置,不過該框并不局限在包含塊內(nèi),有可能會(huì)溢出,通常這個(gè)時(shí)候你會(huì)借助 overflow 屬性來進(jìn)行處理。

除了說什么是包含塊,這里順帶再介紹一下生成包含塊的一些特殊場(chǎng)景:

  • 由根元素生成的包含塊叫做 初始包含塊(initial containing block)
  • 對(duì)于其它元素,如果元素的 position 值是 relative 或者 static,其包含塊由最近的祖先 塊容器框 的內(nèi)容邊界(如果想知道什么是內(nèi)容邊界,可以先看看CSS盒模型)形成。

舉個(gè)例子,td, th 就算有父容器 tr,但它們的包含塊卻是由 table 生成,因?yàn)?table 是 塊容器框 而 tr 不是

  • 絕對(duì)定位元素的包含塊由最近的定位(position 值非 static)祖先生成,如果不存在這樣的祖先,則采用初始包含塊;
  • 固定定位元素(position: fixed)的包含塊一般情況下都由視口 ① 生成;

說了這幾個(gè)特殊的情景,你會(huì)發(fā)現(xiàn)并不是所有的包含塊都是由父元素所生成。

什么是塊級(jí)元素?

塊級(jí)元素是那些視覺上會(huì)被格式化成塊狀的元素,通俗一點(diǎn)來說就是那些會(huì)換新行的元素。display 屬性的:block, list-item, table, flex, grid 值都可以將一個(gè)元素設(shè)置成塊級(jí)元素。

舉個(gè)例子來說,li 是一個(gè) 塊級(jí)元素,但也有人會(huì)說它是一個(gè) 塊元素。嗯,li 確實(shí)是一個(gè)塊級(jí)元素,但并不是一個(gè)塊元素,為什么?

什么是塊元素?

塊元素是 display 屬性值為 block 的元素,它應(yīng)該是 塊級(jí)元素 的一個(gè)子集,而不是等同的,一個(gè) 塊元素 是一個(gè) 塊級(jí)元素,但一個(gè) 塊級(jí)元素 不一定是一個(gè) 塊元素,所以不要混淆。

塊級(jí)框,塊容器框,塊框

什么是塊級(jí)框?

塊級(jí)元素生成塊級(jí)框,這些框會(huì)參與某些 BFC。每個(gè)塊級(jí)元素都會(huì)生成一個(gè)主要的塊級(jí)框來包含其子框和生成的內(nèi)容,同時(shí)任何定位方式都會(huì)與這個(gè)主要的塊級(jí)框有關(guān)。

某些塊級(jí)元素還會(huì)在主要的塊級(jí)框之外產(chǎn)生額外的框:例如 list-item 元素,它需要生成一個(gè)額外的框用于包含 list-style-type。這些額外的框會(huì)相對(duì)于主要的塊級(jí)框來進(jìn)行排版。

什么是塊容器框?

一個(gè) 塊容器框 要么只包含 塊級(jí)框,要么創(chuàng)建一個(gè) IFC 而只包含 行內(nèi)級(jí)框,但不能同時(shí)包含 塊級(jí)框行內(nèi)級(jí)框。

除了 table框置換元素,一個(gè) 塊級(jí)框 同時(shí)也是一個(gè) 塊容器框。非置換的行內(nèi)塊單元格塊容器 但不是 塊級(jí)框

并不是所有的 塊級(jí)框 都是 塊容器框,也并不是所有的 塊容器框 都是 塊級(jí)框。

塊級(jí)框塊容器框 的另外一個(gè)重要的區(qū)別是:塊級(jí)框 需要能夠包含其生成的內(nèi)容,但 塊容器框 并不需要。這是什么意思呢?簡(jiǎn)單的解釋一下:

比如一個(gè) iframe 其內(nèi)容由 src 屬性所決定,這可以當(dāng)成是生成的內(nèi)容,所以 iframe 是一個(gè) 塊級(jí)框 但卻不是 塊容器框

什么是塊框?

簡(jiǎn)要的來說,是 塊容器塊級(jí)框 稱之為 塊框。

可以通過下面這個(gè)圖來快速的梳理清楚這3者之間的聯(lián)系:

block boxes(圖一)

說完了塊級(jí)框,接下來說說行內(nèi)級(jí)框

什么是行內(nèi)級(jí)元素?

行內(nèi)級(jí)元素是那些不會(huì)為自身內(nèi)容形成新的塊,而讓內(nèi)容分布在多行中的元素。display 屬性的:inline, inline-table, inline-block, inline-flex, inline-grid 值都可以將一個(gè)元素設(shè)置成行內(nèi)級(jí)元素。

什么是行內(nèi)元素?

如同塊元素之于塊級(jí)元素的關(guān)系,行內(nèi)元素僅僅是 display 屬性值為 inline 的元素,這里不再贅述。

行內(nèi)級(jí)框,原子行內(nèi)級(jí)框,行內(nèi)框

行內(nèi)級(jí)元素生成行內(nèi)級(jí)框,而這些框會(huì)參與某個(gè) IFC。一個(gè) 行內(nèi)框行內(nèi)級(jí)框,且其內(nèi)容參與了包含它的 IFC。一個(gè) display 值是 inline 的非置換元素會(huì)生成一個(gè)行內(nèi)框。那些不是行內(nèi)框的行內(nèi)級(jí)框(例如行內(nèi)級(jí)置換元素、行內(nèi)塊元素、行內(nèi)表格元素)被稱為 原子行內(nèi)級(jí)框,因?yàn)樗鼈兪且詥我徊煌该骺虻男问絹韰⑴c其 IFC 的。

細(xì)心的你會(huì)發(fā)現(xiàn)并沒有一個(gè) 行內(nèi)容器框塊容器框 相對(duì)應(yīng),但卻多了一個(gè) 原子行內(nèi)級(jí)框。并且有趣的是行內(nèi)塊(包括置換和非置換元素)是原子行內(nèi)級(jí)框,而非置換行內(nèi)塊卻同時(shí)還是塊容器框

inline boxes(圖二)

匿名框

匿名框 包括 匿名塊框匿名行內(nèi)框。

假設(shè)一個(gè) div 中包含有一個(gè) p 和一段純文本 xxx。由于 塊容器框 只允許要么包含 塊級(jí)框,要么包含 行內(nèi)級(jí)框,所以,為了符合這種情況,div 會(huì)生成一個(gè)匿名的塊級(jí)框用于包裹 xxx,這個(gè)匿名框就叫做 匿名塊框。

我們拿 W3C 上的一個(gè)例子來加深對(duì)匿名塊框的印象:

<div>
  Some text
  <p>More text</p>
</div>

Anonymous block boxes(圖三)

與此同時(shí),我們將上面的代碼稍微改一下,將 p 變成 span

<div>
  Some text
  <span>More text</span>
</div>

div 生成一個(gè)塊框,More textspan 生成一個(gè)行內(nèi)框,由于 Some text 沒有與之相關(guān)的行級(jí)元素,將由 div 為其生成一個(gè)行內(nèi)框用以包裹,這個(gè)框稱為匿名行內(nèi)框。如圖四:

Anonymous block boxes(圖四)

假設(shè)一個(gè)匿名框的類型可根據(jù)上下文來清晰界定,則 匿名行內(nèi)框匿名塊框 都可被簡(jiǎn)稱為 匿名框。

匿名框的繼承屬性會(huì)從包含它的非匿名框那里繼承,非繼承屬性取其初始值。

附注:

  • ① 用戶代理一般會(huì)向用戶提供一個(gè)載體(屏幕上的一個(gè)窗口或其它可視區(qū)域)用以訪問文檔,這個(gè)載體就叫做 視口。用戶代理可以在視口大小被調(diào)整時(shí)改變文檔的布局。如果視口小于渲染文檔的畫布區(qū)域,用戶代理應(yīng)當(dāng)提供一個(gè)滾動(dòng)機(jī)制。每個(gè)畫布只能擁有一個(gè)視口,但用戶代理可以把文檔渲染至多個(gè)畫布上(即為相同文檔提供不同的視圖)。

說明:

  • 最近的文章都是斷斷續(xù)續(xù)寫的,如讀者朋友發(fā)現(xiàn)存在描述錯(cuò)誤地方請(qǐng)及時(shí)提醒。
以上內(nèi)容是否對(duì)您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號(hào)
微信公眾號(hào)

編程獅公眾號(hào)