概念:
visual formatting model,可视化格式模型
The CSS visual formatting model is an algorithm that processes a document and displays it on visual media.
它是一种规则,用于规定用户代理如何将DOM树展示在可视化媒体中。
通俗的说,我们在HTML中写一个p标签,在浏览器中打开之后,他会是以什么样子展现出来(他的宽度、高度是多少,他在哪里,他与相邻的元素是什么关系。)这些,都是由这个规则来决定。
那么它是如何决定的呢?
首先,他先给每个DOM元素都穿上一套衣服,即框。
In the visual formatting model, each element in the document tree generates zero or more boxes according to the box model
在可视化格式模型中,一切都是框。
框:
Block-level elements and block boxes,块级元素及块框
Block-level elements are those elements of the source document that are formatted visually as blocks (e.g., paragraphs). The following values of the 'display' property make an element block-level: 'block', 'list-item', and 'table'.
Block-level boxes are boxes that participate in a block formatting context. Each block-level element generates at least one block-level box.
Except for table boxes, and replaced elements, a block-level box is also a block container box. A block container box either contains only block-level boxes or establishes an inline formatting context and thus contains only inline-level boxes.
Not all block container boxes are block-level boxes: non-replaced inline blocks and non-replaced table cells are block containers but not block-level boxes. Block-level boxes that are also block containers are called block boxes.
A replaced element is any element whose appearance and dimensions are defined by an external resource. Examples include images (
<img>
tags), plugins (<object>
tags), and form elements (<button>
,<textarea>
,<input>
, and<select>
tags).
- 块级元素产生一或多个块级框(block-level box),块级框用来参与块级格式化上下文(block formatting context)。
- 块级包含框是除了表格框和可替换元素(replaced element)之外的块级框。块级包含框要么只包含块级框要么只包含行内级框。
- 即是块级框又是块级包含框的,叫做块框。
其实这三个概念不过就是把块状的框分成三个大类:
display: block、table、list-item、non-replaced inline-block、replaced inline-block、non-replaced table cell、replaced table cell。
Inline-level elements and inline boxes
Inline-level elements are those elements of the source document that do not form new blocks of content; the content is distributed in lines (e.g., emphasized pieces of text within a paragraph, inline images, etc.). The following values of the 'display' property make an element inline-level: 'inline', 'inline-table', and 'inline-block'. Inline-level elements generate inline-level boxes, which are boxes that participate in an inline formatting context.
An inline box is one that is both inline-level and whose contents participate in its containing inline formatting context. A non-replaced element with a 'display' value of 'inline' generates an inline box. Inline-level boxes that are not inline boxes (such as replaced inline-level elements, inline-block elements, and inline-table elements) are called atomic inline-level boxes because they participate in their inline formatting context as a single opaque box
- 和块级元素相似,行内级元素(Inline-level elements)也会产生行内级框(inline-level boxes),行内级框用来参与行内级格式化上下文。
- 行框(inline box)是行内级框且他的包含元素参与它自己的行内级格式化上下文的框。display为inline的非替换元素产生的框叫做行框,display为其他值的行内级元素产生的框叫做原子级行内级框。
display: non-replaced inline、inline-block、replaced inline、 inline-table
Anonymous boxes ,匿名框
匿名框又分为匿名块框(Anonymous block boxes)和匿名行框()
上面提到:
- 在可视化格式模型中,一切皆是框。
- 块级包含框里面只能有块级框或只能有行内级框。
那么,如果在一个块级框里面添加一行文字呢?
<div>
Some text
<p>More text</p>
</div>
这时候,会产生一个匿名块框包裹住“Some text”。W3C上面的示意图:
为什么会产生匿名块框而不是匿名行内框呢?
if a block container box (such as that generated for the DIV above) has a block-level box inside it (such as the P above), then we force it to have only block-level boxes inside it.
在一个块包含框里面,只要有一个块级框,就认为,这个块框里面只能包含块级框。
(显然,可视化格式模型是重block轻inline的,在定义block-level elements时,它说只要像一个块的元素就是块级元素,定义inline-levels时说,不像一个块的元素就是行内级元素。这里又是,只要包含了块级框就只能有块级框)
在一个行框里面,如果有一个文档流内的块级框,这个行框就会被打断为两部分,分别放到一个匿名块框里面,分布在这个块级框的两侧。例如:
<p style="display: inline">
This is anonymous text before the SPAN.
<span style="display:block">This is the content of SPAN.</span>
This is anonymous text after the SPAN.
</p>
Any text that is directly contained inside a block container element (not inside an inline element) must be treated as an anonymous inline element.
如果一个块包含框里面有行框而没有块框,没有包含在行框里面的文字就会被包在匿名行框内,例如:
<p>Some <em>emphasized</em> text</p>
要注意只有文字会产生匿名框,也就是说,空白不会产生匿名框。这也就解释了为什么在HTML无论添加多少空格或换行符最终在浏览器中都会显示成为一个空格。
综上,以下三种情况会产生匿名框:
- 块包含框里面有块框时,行框会被包含在匿名块框里面。
- 块包含框里面只有行框时,不在框内的文字会被包含在匿名行框里面。
- 行框里面有文档流内的块级框时,行框会被打断,然后分别被包含在匿名块框里面分布在块框两侧
匿名框只是为了排版而产生,无法通过它来设置样式,它会继承非匿名的父框的可继承样式。他的包含元素也不会用它的宽度或高度来计算相应的值。
Positioning schemes 定位体系:
定位规则是根据position属性和float属性来计算一个盒子的位置的。
-
Normal flow 普通流
Block formatting contexts 块级格式化上下文
在块级格式化上下文中,框是在垂直方向一个接着一个的摆放的。框与框之间的垂直距离由padding、border、margin决定,同一个块级格式化上下文中的相邻margin会发生折叠。
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.
以下情况下的框,会为自己包含的内容创建一个新的BFC。
- float:left/right
- position:absolute
- display:inline-block/table-cell/table-caption
- overflow:hidden/scroll/auto
- Inline formatting contexts 行内级格式化上下文
在行内级格式化上下文中,框是在水平方向上一个接着一个的排列。他们之间的水平距离由padding、border、margin来决定。每一行的框都放在一个盒子里,这个盒子称为line box(行盒)。
行盒的高度总是能包含住它里面的框,除非用line-height属性强制规定它的高度。如果没有浮动的话,行盒的宽度由他包含的框的总宽度决定,如果出现浮动,行盒会变窄,为浮动让位。
Relative positioning
框相对于在流内的位置移动,像是一个框精分成一个透明的自己,用于在流中占据位置,还有一个想去远方的自己,根据透明的自己进行定位,覆盖在流内的框之上。
精分是它个人的行为,不会对其他的框的位置产生影响。
Floats
- A floated box is shifted to the left or right until its outer edge touches the containing block edge or the outer edge of another float.
- If there is not enough horizontal room for the float, it is shifted downward until either it fits or there are no more floats present.
- Since a float is not in the flow, non-positioned block boxes created before and after the float box flow vertically as if the float did not exist.
- the current and subsequent line boxes created next to the float are shortened as necessary to make room for the margin box of the float.
浮动的框不在流内,它会尽量去靠左(右),直到外边缘碰到包含框的边缘或是另一个浮动框的边缘。
在流内的块框会当做浮动不存在一样垂直排列。
行盒会缩短,给浮动框留出足够的位置。这就意味着,文字是会环绕在左浮动框的右侧的。
an element in the normal flow that establishes a new block formatting context must not overlap the margin box of any floats in the same block formatting context as the element itself.
创建了一个新的BFC的块框的外边框边缘不允许与浮动框的外边距重合。
clear property “清除”浮动
This property indicates which sides of an element's box(es) may not be adjacent to an earlier floating box. The 'clear' property does not consider floats inside the element itself or in other block formatting contexts.
和浮动在同一个BFC里的,挨着浮动的非绝对定位框,可以通过设置clear属性来让挨着自己的浮动框恢复正常(他的外边框边缘贴着浮动的外边缘)。
Absolute positioning
- In the absolute positioning model, a box is explicitly offset with respect to its containing block. It is removed from the normal flow entirely (it has no impact on later siblings)
- The containing block for a positioned box is established by the nearest positioned ancestor.(or, if none exists, the initial containing block)
- an absolutely positioned element (or its box) imply that the element's 'position' property has the value 'absolute' or 'fixed'
绝对定位框会根据离他最近的一个已定位(position:absolute/relative/fixed)的祖先包含框的内容区边缘的位置来定位,如果没有已定位的祖先框,就根据第一个包含框的位置来定位。
Fixed positioning
Fixed positioning is a subcategory of absolute positioning. The only difference is that for a fixed positioned box, the containing block is established by the viewport.
固定定位是绝对定位的一种特殊情况,即他的包含框永远都是视口。
Relationships between 'display', 'position', and 'float'
- 当display为none的时候,不会产生任何框。
- 当设置了position:absolute/fixed时,float的值会被强制转换成none,一切行内框都会变成块框。也就是说,给一个行内级元素设置了绝对定位,他就会变成一个块,就可以设置他的宽度和高度和垂直的margin、padding了。
- 当设置了float:left/right,一切行内框都会变成块框
Layered presentation:
- Each box belongs to one stacking context. Each positioned box in a given stacking context has an integer stack level
- The root element forms the root stacking context. Other stacking contexts are generated by any positioned element
- Within each stacking context, the following layers are painted in back-to-front order:
- the background and borders of the element forming the stacking context.
- the child stacking contexts with negative stack levels (most negative first).
- the in-flow, non-inline-level, non-positioned descendants.
- the non-positioned floats.
- the in-flow, inline-level, non-positioned descendants, including inline tables and inline blocks.
- the child stacking contexts with stack level 0 and the positioned descendants with stack level 0.
- the child stacking contexts with positive stack levels (least positive first).