扒一下W3C規範裏的BFC和IFC

1、盒子模型

頁面任何一個元素均可以當作是box,box分block-level,inline-level和匿名的。html

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

2、BFC

什麼是BFC?瀏覽器

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

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

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

二、block boxes
W3C規範原文的定義:"Block-level boxes that are also block containers are called block boxes."能夠做爲block containers的塊級元素,稱爲block boxesflex

三、block container box
原文:"a block-level box is also a block container box"。ui

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

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

BFC的佈局規矩:orm

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

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

一、根元素;
二、float屬性不爲none;
三、position爲absolute或fixed;
四、display爲inline-block, flex, 或者inline-flex;
五、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."

3、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在這些盒子中都是有效的。這些盒子有可能經過不一樣的方式垂直對齊:一、他們底部或者頂部能夠對齊,二、或者能夠他們內部的文字基線能夠對齊。若是一個矩形區域,包含着一些排成一條線的盒子,稱爲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
相關文章
相關標籤/搜索