「前端早讀君」css進階之完全理解視覺格式化模型

今日勵志

不論你在何時開始,重要的是開始以後不要中止。css

前言

對於部分前端工程師來說,有時候CSS令他們很頭疼,明明設置了某個樣式,可是佈局就是不起做用。前端

clipboard.png

若是你也有這種問題,那麼是時候學習下什麼是css視覺格式化模型了。知己知彼方能解決問題。程序員

clipboard.png

CSS 視覺格式化模型(visual formatting model)是用來處理和在視覺媒體上顯示文檔時使用的計算規則。該模型是 CSS 的基礎概念之一。微信

視覺格式化模型會根據CSS盒子模型將文檔中的元素轉換爲一個個盒子,每一個盒子的佈局由如下因素決定:前端工程師

  1. 盒子的尺寸:精確指定、由約束條件指定或沒有指定
  2. 盒子的類型:行內盒子(inline)、行內級盒子(inline-level)、原子行內級盒子(atomic
    inline-level)、塊盒子(block)
  3. 定位方案(positioning scheme):普通流定位、浮動定位或絕對定位
  4. 文檔樹中的其它元素:即當前盒子的子元素或兄弟元素
  5. 視口尺寸與位置
  6. 所包含的圖片的尺寸
  7. 其餘的某些外部因素

該模型會根據盒子的包含塊(containing block)的邊界來渲染盒子。一般,盒子會建立一個包含其後代元素的包含塊,可是盒子並不禁包含塊所限制,當盒子的佈局跑到包含塊的外面時稱爲溢出(overflow)ide

盒子生成介紹

盒子的生成是 CSS 視覺格式化模型的一部分,用於從文檔元素生成盒子。盒子有不一樣的類型,不一樣類型的盒子的格式化方法也有所不一樣。盒子的類型取決於 CSS 的display屬性。佈局

塊級元素與塊盒子

當元素的 display爲 block、list-item或 table時,該元素將成爲塊級元素。一個塊級元素會被格式化成一個塊(例如文章的一個段落),默認按照垂直方向依次排列。學習

每一個塊級盒子都會參與塊格式化上下文(block formatting context)的建立,而每一個塊級元素都會至少生成一個塊級盒子,即主塊級盒子(principal block-level box)。有一些元素,好比列表項會生成額外的盒子來放置項目符號,而那些會生成列表項的元素可能會生成更多的盒子。不過,多數元素只生成一個主塊級盒子。flex

主塊級盒子包含由後代元素生成的盒子以及內容,同時它也會參與定位方案。ui

一個塊級盒子可能也是一個塊容器盒子。塊容器盒子(block container box)要麼只包含其它塊級盒子,要麼只包含行內盒子並同時建立一個行內格式化上下文(inline formatting context)。

可以注意到塊級盒子與塊容器盒子是不一樣的這一點很重要。前者描述了元素與其父元素和兄弟元素之間的行爲,然後者描述了元素跟其後代之間的行爲。有些塊級盒子並非塊容器盒子,好比表格;而有些塊容器盒子也不是塊級盒子,好比非替換行內塊和非替換表格單元格。

一個同時是塊容器盒子的塊級盒子稱爲塊盒子(block box)。

匿名塊盒子
在某些狀況下進行視覺格式化時,須要添加一些增補性的盒子,這些盒子不能用CSS選擇符選中,所以稱爲匿名盒子(anonymous boxes)。

CSS選擇器不能做用於匿名盒子(anonymous boxes),因此它不能被樣式表賦予樣式。也就是說,此時全部可繼承的 CSS 屬性值都爲 inherit ,而全部不可繼承的 CSS 屬性值都爲 initial。

塊包含盒子可能只包含行內級盒子,也可能只包含塊級盒子,但一般的文檔都會同時包含二者,在這種狀況下,就會在相鄰的行內級盒子外建立匿名塊盒子。

示例節
考慮下面的HTML代碼,假設 和 都保持默認的樣式(即它們的 display 爲 block):

<div>
   Some inline text
   <p>followed by a paragraph</p>
   followed by more inline text.
</div>

此時會產生兩個匿名塊盒子:一個是 元素前面的那些文本(Some inline text),另外一個是元素後面的文本(followed by more inline text.)。此時會生成下面的塊結構:

clipboard.png

顯示爲:

Some inline text

followed by a paragraph

followed by more inline text.

對這兩個匿名盒子來講,程序員沒法像<p>元素那樣控制它們的樣式,所以它們會從<div>那裏繼承那些可繼承的屬性,如 color。其餘不可繼承的屬性則會設置爲 initial,好比,由於沒有爲它們指定 background-color,所以其具備默認的透明背景,而 元素的盒子則可以用CSS指定背景顏色。相似地,兩個匿名盒子的文本顏色老是同樣的。

另外一種會建立匿名塊盒子的狀況是一個行內盒子中包含一或多個塊盒子。此時,包含塊盒子的盒子會拆分爲兩個行內盒子,分別位於塊盒子的前面和後面。塊盒子前面的全部行內盒子會被一個匿名塊盒子包裹,塊盒子後面的行內盒子也是同樣。所以,塊盒子將成爲這兩個匿名塊盒子的兄弟盒子。

若是有多個塊盒子,而它們中間又沒有行內元素,則會在這些盒子的前面和後面建立兩個匿名塊盒子。

行內級元素和行內盒子節
若是一個元素的display屬性爲inline、inline-block或inline-table,則稱該元素爲行內級元素。顯示時,它不會生成內容塊,可是能夠與其餘行內級內容一塊兒顯示爲多行。一個典型的例子是包含多種格式內容(如強調文本、圖片等)的段落,就能夠由行內級元素組成。

行內級元素會生成行內級盒子,該盒子同時會參與行內格式化上下文(inline formatting context)的建立。行內盒子既是行內級盒子,也是一個其內容會參與建立其容器的行內格式化上下文的盒子,好比全部具備display:inline樣式的非替換盒子。若是一個行內級盒子的內容不參與行內格式化上下文的建立,則稱其爲原子行內級盒子。而經過替換行內級元素或display值爲inline-block或inline-table的元素建立的盒子不會像行內盒子同樣能夠被拆分爲多個盒子。

注意:開始的時候,原子行內級盒子叫作原子行內盒子,這並不許確,由於它們並非行內盒子。後來在一次勘誤時修正了這一問題。不過,當你見到某些文章中使用了「原子行內盒子」的時候,你盡能夠將其理解爲「原子行內級盒子」,由於這僅僅是一個名字的修改。

在同一個行內格式化上下文中,原子行內級盒子不能拆分紅多行:

<style> span {
    display: inline; /* default value*/
}</style>
<div style="width:20em;">
    The text in the span
    <span>can be split in several lines as it</span>
    is an inline box.
</div>

可能會顯示爲:

The text in the span can be split into several
lines as it is an inline box.

而:

<style> span {
    display: inline-block;
}</style>
<div style="width:20em;">
    The text in the span
    <span>
    cannot be split in several lines as it
    </span>
    is an inline-block box.
</div>

則可能顯示爲:

The text in the span 
cannot be split into several lines as it is an
inline-block box.

其中的「cannot be split into several lines as it」永遠不會換行。

匿名行內盒子

相似於塊盒子,CSS引擎有時候也會自動建立一些行內盒子。這些行內盒子沒法被選擇符選中,所以是匿名的,它們從父元素那裏繼承那些可繼承的屬性,其餘屬性保持默認值initial。

一種常見的狀況是CSS引擎會自動爲直接包含在塊盒子中的文本建立一個行內格式化上下文,在這種狀況下,這些文本會被一個足夠大的匿名行內盒子所包含。可是若是僅包含空格則有可能不會生成匿名行內盒子,由於空格有可能會因爲white-space的設置而被移除,從而致使最終的實際內容爲空。

其餘類型的盒子

行盒子

行盒子由行內格式化上下文建立,用來顯示一行文本。在塊盒子內部,行盒子老是從塊盒子的一邊延伸到另外一邊(譯註:即佔據整個塊盒子的寬度)。當有浮動元素時,行盒子會從向左浮動的元素的右邊緣延伸到向右浮動的元素的左邊緣。

行盒子更可能是以技術性目的而存在的,Web開發者一般不須要關心。

Run-in 盒子

Run-in 盒子經過display:run-in來定義,它能夠是塊盒子,也能夠是行內盒子,這取決於緊隨其後的盒子的類型。Run-in 盒子能夠用來在可能的狀況下將標題嵌入文章的第一個段落中。

注意:Run-in 盒子已經在CSS 2.1的標準中移除了,但可能會在CSS 3中做爲一個實驗性的內容再次加入。所以最好不要將其用於正式項目。

由其餘模型引入的盒子

除了行內格式化上下文和塊格式化上下文以外,CSS還定義了幾種內容模型,這些模型一樣能夠應用於元素。這些模型通常用來描述佈局,它們可能會定義一些額外的盒子類型:

  • 表格內容模型可能會建立一個表格包裝器盒子和一個表格盒子,以及多個其餘盒子如表格標題盒子等
  • 多列內容模型可能會在容器盒子和內容之間建立多個列盒子
  • 實驗性的網格內容模型或flex-box內容模型一樣會建立一些其餘種類的盒子

定位規則
一旦生成了盒子之後,CSS引擎就須要定位它們以完成佈局。下面是定位盒子時所使用的規則:

  • 普通流:按照次序依次定位每一個盒子
  • 浮動:將盒子從普通流中單獨拎出來,將其放到外層盒子的某一邊
  • 絕對定位:按照絕對位置來定位盒子,其位置根據盒子的包含元素所創建的絕對座標系來計算,所以絕對定位元素有可能會覆蓋其餘元素

普通流介紹

在普通流中,盒子會依次放置。在塊格式化上下文中,盒子在垂直方向依次排列;而在行內格式化上下文中,盒子則水平排列。當CSS的 position 屬性爲 static 或 relative,而且 float 爲 none 時,其佈局方式爲普通流。

浮動介紹

在浮動定位中,浮動盒子會浮動到當前行的開始或尾部位置。這會致使普通流中的文本及其餘內容會「流」到浮動盒子的邊緣處,除非元素經過 clear 清除了前面的浮動。一個盒子的 float 值不爲 none,而且其 position 爲 static 或 relative 時,該盒子爲浮動定位。若是將 float 設置爲 left,浮動盒子會定位到當前行盒子的開始位置(左側),若是設置爲 right,浮動盒子會定位到當前行盒子的尾部位置(右側)。不論是左浮動仍是右浮動,行盒子都會伸縮以適應浮動盒子的大小。

絕對定位介紹

在絕對定位中,盒子會徹底從當前流中移除,而且不會再與其有任何聯繫(譯註:此處僅指定位和位置計算,而絕對定位的元素在文檔樹中仍然與其餘元素有父子或兄弟等關係),其位置會使用 top、bottom、left 和 right

相對其包含塊進行計算。若是元素的 position 爲 absolute 或 fixed,該元素爲絕對定位。

對固定位置的元素來講,其包含塊爲整個視口,該元素相對視口進行絕對定位,所以滾動時元素的位置並不會改變。

參考資料MDN文檔:https://developer.mozilla.org...

你可能喜歡

clipboard.png

打開微信掃一掃關注早讀君,天天早晨爲你推送前端知識,度過擠地鐵坐公交的時光

相關文章
相關標籤/搜索