为了弄明白BFC、IFC以及定位、流的问题,翻译部分Visual Formatting Model章节要点,如下:
注:当且属首次翻译,特别粗糙,并无与实战结合,请勿相信,仅供参考
翻译约定:
中文名 | 英文名 | 示例描述 |
浏览器 | User agents | |
框 | box | |
元素 | element | |
块级元素 | block-level element | |
定位机制 | positioning scheme | |
内容块 | containing block | |
框的渲染/生成 | box generation | |
块级框 | block-level box | 如:display属性为“block”、“list-item”、“table”的元素,table框、可替换元素 |
块级容器框 | block container box | 如:不可替换的inline-block、不可替换的table cell |
块框 | block box | 即属于块级框、又属于块级容器框 |
行内级框 | inline-level box | 如:display属性值为"inline"、“inline-table”,“inline-block"的元素 |
行内框 | inline box | 如:大部分行内级框属于行内框,但是以下不属于行内框:可替换的行内级元素、inline-block元素、inline-table元素 |
原子性行内级框 | atomic inline-level block | 如:可替换的行内级元素(如:input)、inline-block元素、inline-table元素 |
可替换元素 | Replaced element | 如:<img>, <object>, <video>; <textarea>, <input>; 匿名可替换元素 |
不可替换元素 | Non-replaced element | |
流外 | Out of flow | 如:根元素、浮动元素、绝对定位元素 |
流内 | In flow |
部分关系图:
块级框、块级容器框、块框
行内级框、参与IFC的框、行内框
解释:
1. 可替换元素
可替换元素是一种其展现不在CSS限制范围的元素,也就是说:它的展现独立于CSS。典型的可替换元素有:
1. <img>, <object>, <video>, display属性为:inline
2. 表单元素:<textarea>, <input>. display属性为:inline-block
3. 有些元素在特定情况下才属于可替换元素,如:<audio>, <canvas>, display属性为:inline
4. 使用CSS属性content插入的内容称为匿名可替换元素。
这类元素的典型特点是:没有结束标签,因此开始结束标签之间也没有内容,内容通过属性(如:value)来指定;你也可以理解为:该标签会被外面的资源所代替。
2. 不可替换元素:
除上面之外的所有HTML元素称为不可替换元素。
翻译正文:
9. Visual Formatting Model 可视化排版模型(简称:VFM)
9.1 VFM介绍
本章和下一章描述了VFM:浏览器将DOM树转换为可视化的过程。
VMF中,DOM树中的每个元素根据框模型生成0或多个框。这些框的布局是根据以下因素控制:
1. 框尺寸和类型(框生成方式)
2. 定位机制(常规流、浮动、绝对定位)
3. DOM树中元素间的关系
4. 外部因素(例如:viewport尺寸、图片的内在尺寸等)
(跳过Continuous media, paged media)
VFM并没有规定排版的所有方面(如:letter-spacing算法),本规范也不会讲到不同浏览器对排版处理的差异。
9.1.1 viewport
(译者注:跳过不译)
9.1.2 内容块
CSS2.1中,许多框的position和size是根据其内容块计算的。一般来说,一个DOM元素生成的框会被后代框当做内容块,我们俗称:一个框为后代节点“建立”了内容块。短语:"一个框的内容块"指的是"包围这个框的内容块",并不是这个框生成的内容块。
每一个框都是根据它的内容块来定位,但并不总是限制于内容块中,因为它有可能会(溢出)overflow;
关于内容块尺寸计算的详细信息请参考下章。
9.2 框的渲染/生成
本小节讨论了CSS2.1中生成的框的类型,类型的不同会影响框在VFM中的处理方式。以下的display属性用于指定框的类型。
9.2.1 块级元素、块级框
DOM源码中,按照块排版的元素称为块级元素(Block-level element)(如:paragraph对应的p标签),当元素的display属性为“block”、“list-item”、“table”时,该元素成为块级元素;
每一个块级元素都会生成一个"主块级框"(Principal block-level box)用于包含后代框和生成的内容,这个框会参与到定位机制和BFC中。部分块级元素(如:“list-item”)会生成除了主块框之外的额外框,这些额外框根据主块级框的位置放置。
除了后面章节单独介绍的table框、可替换元素,一个块级框也是一个块级容器框。一个块级容器框要么只能包含块级框、或者行内框(建立一个IFC)。并非所有的块级容器框都属于块级框:不可替换的inline-block、不可替换的table cell属于块级容器框,但不属于块级框。
同时属于块级框和块级容器框的框称为块框。
块级框、块级容器框、块框有时一概简称为"块"。
9.2.1.1 匿名块框
如下的一段HTML代码:
<DIV> Some text <P>More text </DIV>
假设div和p元素的display为block,那么div就拥有了行内元素和块级元素,为了简化定义排版模型,我们假设存在一个匿名块围绕着文本some text。
换言之,如果块级容器框(如:div元素)包含块级框(如:p元素),那么我们强制块级容器框只包含块级框,即:将some text设置为块级框,只不过是匿名的。
当行内框的代码中包含块级框时,这个行内框(以及祖先行内框)会被分成多段围绕在这个块级框上下,因此行内框被打断成两段(即使其中一段是空文本),中间夹着块级框。考虑到上面简化的排版模型,这些前后的行内框被匿名块框包围,中间的那个块级框成为匿名块框的兄弟节点。当这样的行内框遇到相对定位时,也会影响到其中的块级框。
这种模型也会应用到如下规则(p元素为inline,span为block)的代码中:
p { display: inline }
span { display: block }
<P> This is anonymous text before the SPAN. <SPAN>This is the content of SPAN.</SPAN> This is anonymous text after the SPAN. </P>
p元素包含了匿名文本C1、块级元素C2、匿名文本C3,最终生成的框为:body代表一个块框,包含了一个行内框,这个行内框内部包含了:匿名块框C1、span块框、匿名块框C2。
匿名框会从父框中继承一些可被继承的属性(如:第一个例子中的div父框),不可继承的属性会有初始值。例如:匿名框的font会被继承,但是外边距是0。
设置在匿名框的父元素上的属性也会应用到元素本身和内容上。例如:在p元素上设置border属性,导致边框会围绕在C1(C1无右边框)和C2(无左边框)上。
针对行内容器框设置边框,部分浏览器会有其它的处理方式。(译者注:跳过不译)
9.2.2 行内元素、行内框
HTML代码中,不会按照块排版的元素称为行内元素。它的内容处于一行中(如:p元素中的em元素,行内图片等)。display属性值为"inline"、“inline-table”,“inline-block"的元素称为行内级框,这些框会参与到IFC(Inline Formatting Context)中。
当一个元素即属于行内级,且内容又参与到IFC中时,该元素称为行内框。不可替换元素的display属性为inline时称为行内框。不属于行内框的行内级框(例如:可替换行内级元素、inline-block元素、inline-table元素)称为:"原子性行内级框",因为他们会作为一个整体参与到IFC中。
9.2.2.1 匿名行内框
块容器元素内部的任何直接子文本都必须按照行内元素来处理(例外:内部含有块框时,会当做匿名块框处理)。
如下的一段代码:
<p>Some <em>emphasized</em> text</p>
p元素生成一个块框,em元素生成一个行内框,文本"Some"和"text"生成行内框。后者称为匿名行内框,因为他们没有相关联的行内级元素将这些文本包围起来。
匿名行内框会从父块框中继承部分属性,不可继承属性使用初始值。(如:匿名框从p元素继承了color,但background却是透明的(译者注:chrome下background也继承了))
由于"white-space"属性不会生成匿名块,因此空白内容应该会被重叠起来。
如果清楚匿名框在BFC、IFC中所属的类型,那么规范统称这些匿名行内框、匿名块框为匿名框。
更多的匿名框将在后面介绍table排版时介绍。
9.2.3 Run-in框
display为run-in将在CSS3中定义。
9.2.4 display属性
初始值 inline
下列各值的解释:
block
元素生成块框
inline-block
元素生成一个行内级的块容器框,对内是一个块框,对外则是一个原子性的行内框。
list-item
元素生成多个行内框,如:ul元素生成一个块框,里面的li元素的display属性默认为:list-item。
none
元素不会出现在VFM中,不会生成框,也不会对外面的布局有影响。后代元素也不会生成框,为后代节点设置display属性无法覆盖这种方式。
table,... 元素生成类似于table的格式。
除了定位元素、浮动元素、根元素外,display属性计算出来的值就是设定的值。关于这三类的情况,请参考这一节”display、position、float的关系“。
虽然display属性的初始值为inline,但浏览器的默认样式会覆盖这一值。
9.3 定位机制
CSS2.1中,一个框会根据三种定位机制来布局:
1. 常规流 块级框的块排版、行内级框的行内排版、块级框与行内级框的相对定位
2. 浮动 浮动模型中,框首先按照常规流布局,然后从常规流中去除,接着移动尽左或尽右的地方,它的内容会跟随移动。
3. 绝对定位 该模型中,框直接从常规流中移除,然后根据这个框的内容块来计算位置
根元素、浮动元素、绝对定位元素处于流外,不处于流外的其余元素处于流内。元素A的流包含了元素A本身、和A里面的所有最近流外祖先元素为仍A的元素。
注意:根元素虽然处于流外,但是position属性确属于static
9.3.1 position属性
CSS2.1中, position和float属性决定了采用哪种定位机制来计算框的位置。
可选值: static, relative, absolute, fixed, inherit
初始值: static
各值的解释:
static
该元素的框按照常规流布局,top, right, bottom, left属性无效
relative
框根据它在常规流中的正常位置进行偏移;该值对table-row-group, table-header-group, table-footer-group, table-row, table-column-group, table-column, table-cell, and table-caption元素无效。
absolute
框的位置根据框所在的内容块进行定位
fixed
框根据当前浏览器的视口定位(viewport),它不会随着页面的滚动而移动
多数浏览器会为根元素的position属性赋值static。
9.3.2 框偏移:top, right, bottom, left
如果一个元素的position属性不为static,则称这个元素为定位元素。定位元素生成定位框,拥有以下四个属性:
top
right
bottom
left
初始值 auto
赋值类型:
length
不允许负值
auto
对于不可替换元素,该值与所属的属性top,right, bottom, left有关。详见绝对定位小节。
对于可替换元素,其效果取决于该元素本身的尺寸。详见绝对定位小节。
9.4 常规流
常规流中,块级框参与BFC,行内级框参与IFC。
9.4.1 BFC
块框会参与到所属内容块为BFC的计算中,并非所有块框都会为其子节点建立BFC。满足下面任何一个条件即会建立BFC:
1. float元素不为none
2. 绝对定位元素(position不为static)
3. 不属于块框的块容器框(如:inlien-block,table-cells, table-caption)
4. overflow属性不为visible的块框(除非...,译者注:跳过不译)
BFC中,框会按照垂直方向依次排列,相邻的两个块级框的margin外边距会发生重叠。
BFC中,每个框的左外边缘贴在了内容块的左边,即使该框为float。
9.4.2 IFC
IFC中,行内框水平排列,margin不会发生重叠,对应的这个内容块成为行框。
行框的width是根据其内容块决定的,高度根据line-height计算规则决定。
(译者注:跳过不译)
9.7 display, position, float之间的关系:
影响框生成的三个属性:display, position, float关系如下:
1. display为none,则position和float无效,不会生成框。
2. 否则如果position为absolute, fixed,则float计算为none;display按下表格转换:inline变为block
3. 否则如果float不为none,display按下表格转换
4. 否则如果元素是根节点,display按下表格转换
5. 否则按照display设定的值展示
Specified value | Computed value |
---|---|
inline-table | table |
inline, table-row-group, table-column, table-column-group, table-header-group, table-footer-group, table-row, table-cell, table-caption, inline-block | block |
others | same as specified |
总结:display的值可能会变的情况是:position属性为absolute, fixed; 或者float不为none;或者根节点。
汇总:
从其他博客汇总来BFC的相关资料:
BFC的用处:
1. 自适应两栏布局 原因:BFC
的区域不会与float box
重叠
2. 清除内部浮动 原因:计算BFC
的高度时,浮动元素也参与计算
3. 防止垂直 margin 重叠 原因:Box
垂直方向的距离由margin决定。属于同一个BFC
的两个相邻Box
的margin会发生重叠
BFC的特点:
- 内部的Box会在垂直方向,一个接一个地放置。
- Box垂直方向的距离由margin决定。属于同一个BFC的两个相邻Box的margin会发生重叠
- 每个元素的margin box的左边, 与包含块border box的左边相接触(对于从左往右的格式化,否则相反)。即使存在浮动也是如此。
- BFC的区域不会与float box重叠。
- BFC就是页面上的一个隔离的独立容器,容器里面的子元素不会影响到外面的元素。反之也如此。
- 计算BFC的高度时,浮动元素也参与计算
如何新建BFC:
1. float不为none
2. position为absolute或fixed
3. display为inline-block, table-cell, table-caption, flex, inline-flex
4. overflow不为visible
参考资料: