扒一下W3C規範裡的BFC和IFC

NO IMAGE

一、盒子模型

頁面任何一個元素都可以看成是box,box分block-level,inline-level和匿名的。

匿名box:
<div>
Some text
<p>More text</p>
</div>
其中"Some text",瀏覽器會為其生成一個匿名box

二、BFC

什麼是BFC?

BFC的全稱是Block Formatting Context,直譯過來是:塊級格式化上下文。

在理解BFC時先理解三個概念:

1、Block-level elements
屬於diplay: block;的元素,都是Block-level elements(塊級元素);有可能會觸發BFC。

2、block boxes
W3C規範原文的定義:”Block-level boxes that are also block containers are called block boxes.”可以作為block containers的塊級元素,稱為block boxes

3、block container box
原文:”a block-level box is also a block container box”。

最後還有一句:”The three terms “block-level box,” “block container box,” and “block box” are sometimes abbreviated as “block” where unambiguous.”

都簡稱為塊級元素好了orz…為什麼要糾結這個?主要是被規範的用詞搞暈了,花了點時間才搞明白這三個詞的意思。

BFC的佈局規矩:


1、內部box在垂直方向,一個接一個的放置;
2、box的垂直方向由margin決定,屬於同一個BFC的兩個box間的margin會重疊
3、BFC區域不會與float box重疊(可用於排版);
4、BFC就是頁面上的一個隔離的獨立容器,容器裡面的子元素不會影響到外面的元素。反之也如此。
5、計算BFC的高度時,浮動元素也參與計算

哪些元素或屬性會觸發BFC?

1、根元素;
2、float屬性不為none;
3、position為absolute或fixed;
4、display為inline-block, flex, 或者inline-flex;
5、overflow不為visible;

扒了下 W3C的文件,裡面對BFC的解釋是醬紫的:

“9.4.1 Block formatting contexts

Floats, absolutely positioned elements, block containers (such as inline-blocks, table-cells, and table-captions) that are not block boxes, and block boxes with ‘overflow’ other than ‘visible’ (except when that value has been propagated to the viewport) establish new block formatting contexts for their contents.

In a block formatting context, boxes are laid out one after the other, vertically, beginning at the top of a containing block. The vertical distance between two sibling boxes is determined by the ‘margin’ properties. Vertical margins between adjacent block-level boxes in a block formatting context collapse.

In a block formatting context, each box’s left outer edge touches the left edge of the containing block (for right-to-left formatting, right edges touch). This is true even in the presence of floats (although a box’s line boxes may shrink due to the floats), unless the box establishes a new block formatting context (in which case the box itself may become narrower due to the floats).

For information about page breaks in paged media, please consult the section on allowed page breaks.”

三、IFC

同理,IFC是Inline formatting context。

規範 裡,IFC的描述比BFC的描述多很多,原文比較長,一點點扒吧:

an inline formatting context, boxes are laid out horizontally, one after the other, beginning at the top of a containing block. Horizontal margins, borders, and padding are respected between these boxes. The boxes may be aligned vertically in different ways: their bottoms or tops may be aligned, or the baselines of text within them may be aligned. The rectangular area that contains the boxes that form a line is called a line box.

在一個IFC中,從父級元素的頂部開始,盒子一個接一個橫向排列。此時,橫向的margin、borders、padding在這些盒子中都是有效的。這些盒子有可能通過不同的方式垂直對齊:1、他們底部或者頂部可以對齊,2、或者可以他們內部的文字基線可以對齊。如果一個矩形區域,包含著一些排成一條線的盒子,稱為line box。

The width of a line box is determined by a containing block and the presence of floats. The height of a line box is determined by the rules given in the section on line height calculations.

一個line box的寬度,由他的包含塊(containg block)和floats的存在情況決定。linebox的高度,由你給出的程式碼決定。

A line box is always tall enough for all of the boxes it contains. However, it may be taller than the tallest box it contains (if, for example, boxes are aligned so that baselines line up). When the height of a box B is less than the height of the line box containing it, the vertical alignment of B within the line box is determined by the ‘vertical-align’ property. When several inline-level boxes cannot fit horizontally within a single line box, they are distributed among two or more vertically-stacked line boxes. Thus, a paragraph is a vertical stack of line boxes. Line boxes are stacked with no vertical separation (except as specified elsewhere) and they never overlap.

一般line box的高度對於子元素而言總是夠用的,不過有可能比他包含的最高的元素還高(如果這樣,內部包含的盒子會對齊,基線排成一排)。當盒子的高度小於父級盒子高度時,垂直方向的對齊由‘vertical-align’屬性決定(疑問:原文的box B是啥??)。
當幾個內聯盒子在line box一行內放不下時,它們會分佈在兩個以上的垂直並列(vertically-stacked)的line box上。因此,一個段落都是一堆line box堆疊在一起。line box在垂直堆疊的時候,不會有分離(no vertical separation)而且絕不會重疊(其他特殊情況除外【啥特殊情況??】)

In general, the left edge of a line box touches the left edge of its containing block and the right edge touches the right edge of its containing block. However, floating boxes may come between the containing block edge and the line box edge. Thus, although line boxes in the same inline formatting context generally have the same width (that of the containing block), they may vary in width if available horizontal space is reduced due to floats. Line boxes in the same inline formatting context generally vary in height (e.g., one line might contain a tall image while the others contain only text).

一般來說,line box和內部元素,都是左挨左,右挨右。不過浮動盒子可能會在包含塊和line box的邊緣之間。因此,即使line box在同一個IFC裡通常有相同的寬度。如果他們橫向間距會因float減少,它們寬度可能會不一樣。line box在同一個IFC高度可能不一樣(e.x.:含有不同高度的image)

When the total width of the inline-level boxes on a line is less than the width of the line box containing them, their horizontal distribution within the line box is determined by the ‘text-align’ property. If that property has the value ‘justify’, the user agent may stretch spaces and words in inline boxes (but not inline-table and inline-block boxes) as well.

當內聯盒子的總寬度比line box小的時候,它們的水平分佈由’text-align’屬性決定。如果該屬性值為’justify’,使用者可以拓寬在inline box的空間和文字。

When an inline box exceeds the width of a line box, it is split into several boxes and these boxes are distributed across several line boxes. If an inline box cannot be split (e.g., if the inline box contains a single character, or language specific word breaking rules disallow a break within the inline box, or if the inline box is affected by a white-space value of nowrap or pre), then the inline box overflows the line box.

如果內聯盒子的寬度超過了line box,內聯盒子會被分解成幾個盒子,然後分佈在幾個line box裡面。如果內聯盒子不能被分解(e.g.,如果內聯盒子有單個單詞、或者有特殊的換行規則,或者被’white-space’的’nowrap’、’pre’影響),它會超過line box。

When an inline box is split, margins, borders, and padding have no visual effect where the split occurs (or at any split, when there are several).

如果一個內聯盒子被分解了,margins、borders、和padding在他們被分解的位置沒有視覺效果。

Inline boxes may also be split into several boxes within the same line box due to bidirectional text processing.

由於雙向文字處理(bidirectional text processing)內聯盒子有可能在同一個line box裡被分解成不同的盒子。

Line boxes are created as needed to hold inline-level content within an inline formatting context. Line boxes that contain no text, no preserved white space, no inline elements with non-zero margins, padding, or borders, and no other in-flow content (such as images, inline blocks or inline tables), and do not end with a preserved newline must be treated as zero-height line boxes for the purposes of determining the positions of any elements inside of them, and must be treated as not existing for any other purpose.

line box主要被用來在IFC內裝載內聯級內容。不包含文字、不預留空白、沒有非零margins,padding,border 或者其他flow內容(images、 inline block 或者 inline tables)的內聯元素的line box必須被當成零高度的line box,主要為了定位其他在其裡面的元素,還有必須被當成不存在的或者其他目的(這是什麼鬼???看不懂)。

參考資料:

W3C規範:http://www.w3.org/TR/CSS2/visuren.html
MDN的介紹:https://developer.mozilla.org/zh-CN/docs/Web/Guide/CSS/Visual_formatting_model
知乎一個很棒的答案:https://www.zhihu.com/question/20086234