1. 简介
本节是规范性的。
CSS 接收一个组织为 元素树 的源文档(其中包含 元素 和 文本节点 的混合),以及 文本节点(包含文本),并将其渲染到诸如屏幕、纸张或音频流等画布上。尽管任何此类源文档都可以使用 CSS 渲染,但最常用的类型是 DOM。[DOM](其中一些更复杂的树类型可能具有额外的节点类型,例如 DOM 中的注释节点。就 CSS 而言,所有这些额外的节点类型都会被忽略,如同它们不存在一样。)
为此,它会生成一个中间结构,即 框树 (box tree),它代表了渲染文档的格式化结构。框树中的每个 框 (box) 代表其对应的元素(或伪元素)在画布上的空间和/或时间,而框树中的每个 文本序列 同样代表其对应文本节点的内容。
为了创建框树,CSS 首先使用层叠与继承,为源树中的每个元素和文本节点分配一个 CSS 属性的计算值。(参见 [CSS-CASCADE-3]。)
然后,对于每个元素,CSS 根据该元素的 display 属性生成零个或多个框。通常,一个元素会生成一个主体框,它代表元素本身,并包含其在框树中的内容。然而,某些 display 值(例如 display: list-item)会生成多个框(例如一个主体块框和一个子标记框)。有些值(如 none 或 contents)会导致元素和/或其后代根本不生成任何框。框通常通过其 display 类型来称呼——例如,由具有 display: block 的元素生成的框被称为“块框”或仅称为“块”。
除非另有说明,框被分配与其生成元素相同的样式。通常,继承属性分配给主体框,然后通过框树继承给由同一元素生成的任何其他框。非继承属性默认应用于主体框,但当元素生成多个框时,有时定义为应用于不同的框:例如,应用于 table 元素的边框 (border) 属性应用于其表格网格框,而不是其主体表格包装框。如果值计算过程更改了这些框的样式,并且请求了元素的样式(例如通过 getComputedStyle()),元素会针对每个属性反映其应用到的框的值。
同样,每个连续的同级文本节点序列会生成一个包含其文本内容的文本序列,该序列被分配与生成文本节点相同的样式。但是,如果序列不包含文本,则不会生成文本序列。
在构建框树时,由元素生成的框是任何祖先元素主体框的后代。一般情况下,元素主体框的直接父框是其最近生成框的祖先元素的主体框;但也有一些例外,例如 run-in 框、生成多个容器框的显示类型(如表格)以及介入的匿名框。
匿名框 (anonymous box) 是不与任何元素关联的框。匿名框在特定情况下生成,用于在框树需要特定嵌套结构而元素树生成的框未能提供时修正框树。例如,表格单元格框需要特定类型的父框(表格行框),如果其父级不是表格行框,它将围绕自身生成一个匿名表格行框。(参见 [CSS2] § 17.2.1。)与元素生成的框(其样式严格通过元素树继承)不同,匿名框(仅存在于框树中)通过其框树父级关系进行继承。
在布局过程中,框和文本序列可以分解为多个片段。例如,当行内框和/或文本序列在行之间断开,或者当块框在页面或列之间断开时,就会发生这种情况,这个过程称为碎片化 (fragmentation)。它也可能因为文本的双向重排(参见 CSS 书写模式中的应用双向重排算法)或更高级的显示类型框拆分(例如行内块拆分,参见 CSS2§9.2,或跨列块拆分,参见 CSS 多栏布局)而发生。因此,一个框由一个或多个框片段组成,一个文本序列由一个或多个文本片段组成。有关碎片化的更多信息,请参见 [CSS-BREAK-3]。
注意:许多 CSS 规范在这些术语完善之前就已经编写,或者引用时存在错误,因此在阅读使用这些术语的旧规范时需保持谨慎。通常可以根据上下文推断出它们真正指代的术语。发现规范中的错误时请报告错误,以便进行更正。
注意:关于“听觉”框树及其与 display 属性的交互的更多信息,可以在 CSS 语音模块中找到。[CSS-SPEECH-1]
1.1. 模块交互
本模块替换并扩展了 [CSS2] 第 9.2.4 节中定义的 display 属性定义。
本模块中的属性均不适用于 ::first-line 或 ::first-letter 伪元素。
1.2. 值定义
本规范遵循 [CSS2] 中的 CSS 属性定义约定,并使用 [CSS-VALUES-3] 中的 值定义语法。本规范中未定义的值类型在 CSS Values & Units [CSS-VALUES-3] 中定义。与其他 CSS 模块的组合可能会扩展这些值类型的定义。
除了定义中列出的属性特定值外,本规范中定义的所有属性也都接受 CSS 全局关键字 作为其属性值。为了可读性,未明确重复列出。
2. 框布局模式:display 属性
| 名称 | display |
|---|---|
| 值 | [ <display-outside> || <display-inside> ] | <display-listitem> | <display-internal> | <display-box> | <display-legacy> |
| 初始值 | inline |
| 应用于 | 所有元素 |
| 可继承 | 否 |
| 百分比 | 不可用 |
| 计算值 | 表示内部和外部显示类型的一对关键字,加上可选的 list-item 标志,或者是 <display-internal> 或 <display-box> 关键字;有关计算规则,请参见各种规范中的正文 |
| 规范顺序 | 按语法 |
| 动画类型 | 不可动画 |
用户代理应在所有媒体(包括非视觉媒体)上支持此属性。display 属性定义了元素的显示类型 (display type),它由元素如何生成框的两个基本特质组成:
某些 display 值具有额外的副作用:例如 list-item,它还会生成一个 ::marker 伪元素,以及 none,它导致元素的整个子树从框树中被遗漏。
值定义如下
<display-outside> = block | inline | run-in
<display-inside> = flow | flow-root | table | flex | grid | ruby
<display-listitem> = <display-outside>? && [ flow | flow-root ]? && list-item
<display-internal> = table-row-group | table-header-group |
table-footer-group | table-row | table-cell |
table-column-group | table-column | table-caption |
ruby-base | ruby-text | ruby-base-container |
ruby-text-container
<display-box> = contents | none
<display-legacy> = inline-block | inline-table | inline-flex | inline-grid
下方的非规范性表格总结了 display 的值:
| 简写 display | 全称 display | 生成的框 |
|---|---|---|
| none(无) | — | 子树从框树中省略 |
| 内容 | — | 元素在框树中被内容替换 |
| block | block flow | 块级 (block-level) 块容器 (block container),又称 块框 (block box) |
| flow-root | block flow-root | 块级 块容器,建立一个新的块格式化上下文 (BFC) |
| inline | inline flow | 行内盒 (inline box) |
| inline-block | inline flow-root | 行内级 (inline-level) 块容器,又称 行内块 (inline block) |
| run-in | run-in flow | Run-in 框(具有特殊框树合并规则的行内框) |
| list-item | block flow list-item | 带有额外标记框 (marker box) 的块框 |
| inline list-item | inline flow list-item | 带有额外标记框 的行内框 |
| flex | block flex | 块级 弹性容器 (flex container) |
| inline-flex | inline flex | 行内级 弹性容器 |
| grid | block grid | 块级 网格容器 (grid container) |
| inline-grid | inline grid | 行内级 网格容器 |
| ruby | inline ruby | 行内级 Ruby 容器 |
| block ruby | block ruby | 包含 Ruby 容器 的块框 |
| table | block table | 块级 表格包装框,包含表格网格框 |
| inline-table | inline table | 行内级 表格包装框,包含表格网格框 |
| <display-internal> 类型 | — | 布局特定的内部框 |
注意:遵循“最向后兼容,其次是最短”的优先规则,等效 display 值的序列化使用“简写 display”列。[CSSOM]
2.1. 流式布局的外部显示角色:block、inline 和 run-in 关键字
<display-outside> 关键字指定元素的外部显示类型,这本质上是其主体框在流式布局中的角色。它们定义如下:
- block
- 元素生成的框在放置于流式布局中时是块级框 (block-level box)。[CSS2]
- inline
- 元素生成的框在放置于流式布局中时是行内级框 (inline-level box)。[CSS2]
- run-in
- 元素生成一个 run-in 框,这是一种具有特殊行为的行内级框,它会尝试合并到后续的块容器中。详情请参见 § 5 Run-In 布局。
如果指定了 <display-outside> 值但省略了 <display-inside>,则元素的内部显示类型默认为 flow。
2.2. 内部显示布局模型:flow、flow-root、table、flex、grid 和 ruby 关键字
<display-inside> 关键字指定元素的内部显示类型,它定义了布局其内容的格式化上下文类型(假设它是非替换元素)。它们定义如下:
- flow
- 元素使用流式布局 (flow layout)(块和行内布局)布局其内容。
如果其外部显示类型是 inline 或 run-in,并且它正在参与块或行内格式化上下文,则它生成一个行内框。
否则它生成一个块容器框。
根据其他属性的值(例如 position、float 或 overflow)以及它本身是否参与块或行内格式化上下文,它要么为其内容建立一个新的块格式化上下文,要么将其内容集成到其父级格式化上下文中。参见 CSS2.1 第 9 章。[CSS2] 建立新块格式化上下文的块容器被视为具有 flow-root 的所用内部显示类型。
- flow-root
- 元素生成一个块容器框,并使用流式布局布局其内容。它始终为其内容建立一个新的块格式化上下文。[CSS2]
- table
- 元素生成一个主体表格包装框,它建立一个块格式化上下文,并包含一个额外生成的表格网格框,该框建立一个表格格式化上下文。[CSS2]
- flex
- 元素生成一个主体弹性容器框,并建立一个弹性格式化上下文。[CSS-FLEXBOX-1]
- grid
- 元素生成一个主体网格容器框,并建立一个网格格式化上下文。[CSS-GRID-1]
- ruby
- 元素生成一个Ruby 容器框,并在将其基级内容集成到父级格式化上下文(如果它是行内元素)或生成一个适当外部显示类型的包装框(如果不是)之外,建立一个Ruby 格式化上下文。[CSS-RUBY-1]
如果指定了 <display-inside> 值但省略了 <display-outside>,则元素的外部显示类型默认为 block——除了 ruby,它默认为 inline。
2.3. 生成标记框:list-item 关键字
list-item 关键字使元素生成一个内容由其 list-style 属性(CSS 2.1§12.5 列表)指定的 ::marker 伪元素 [CSS-PSEUDO-4],以及一个用于其自身内容的指定类型的主体框。[CSS2]
如果未指定内部显示类型值,则主体框的内部显示类型默认为 flow。如果未指定外部显示类型值,则主体框的外部显示类型默认为 block。
注意:在本级别中,正如语法所限制的那样,列表项仅限于流式布局显示类型(block/inline/run-in 配合 flow/flow-root 内部类型)。此限制在未来的模块版本中可能会放宽。
2.4. 布局内部显示类型:table-* 和 ruby-* 关键字
一些布局模型,如 table 和 ruby,具有复杂的内部结构,其子元素和后代可以扮演多种不同的角色。本节定义了这些“布局内部 (layout-internal)”的 display 值,它们仅在特定的布局模式内才有意义。
除非另有说明,使用这些 display 值的元素的内部显示类型和外部显示类型均设置为给定的关键字。
当替换元素的 display 属性计算为 布局内部 值之一时,它会被视为具有 inline 的所用值。空白折叠和匿名框生成必须基于该 inline 值围绕这些替换元素进行,就好像从未对其应用布局内部显示值一样。
<display-internal> 关键字定义如下:
- table-row-group、table-header-group、table-footer-group、table-row、table-cell、table-column-group、table-column
- 该元素是一个内部表格元素。它生成相应的内部表格框,参与表格格式化上下文。参见 CSS2§17.2 [CSS2]。
table-cell 框具有 flow-root 的内部显示类型。
- table-caption
- 该元素生成一个表格标题框,它是一个相对于表格和表格包装框具有特殊行为的块框。参见 CSS2§17.2 [CSS2]。
table-caption 框具有 flow-root 的内部显示类型。
- ruby-base、ruby-text、ruby-base-container、ruby-text-container
- 该元素是一个内部 Ruby 元素。它生成相应的内部 Ruby 框,参与Ruby 格式化上下文。[CSS-RUBY-1]
具有布局特定显示类型的框,在置于不兼容的父级中时,会根据其各自的规范在其周围生成匿名包装框。
如果父级错误,如下所示:
< div style = "display:block;" > < div style = "display:table-cell" > ...</ div > </ div >
它将在自身周围生成包装框,产生如下结构:
block box └anonymous table box └anonymous table-row-group box └anonymous table-row box └table-cell box
即使父级是另一个内部表格元素,如果它不是正确的那个,也会生成包装框。例如,在以下标记中:
< div style = "display:table;" > < div style = "display:table-row" > < div style = "display:table-cell" > ...</ div > </ div > </ div >
匿名包装框生成将产生:
table box └anonymous table-row-group box └table-row box └table-cell box
这种“修正”确保了表格布局具有可预测的运行结构。
2.5. 框生成:none 和 contents 关键字
虽然 display 可以控制元素将生成框的类型,但它也可以控制元素是否生成任何框。
<display-box> 关键字定义如下:
- 内容
- 元素本身不生成任何框,但其子元素和伪元素仍会正常生成框和文本序列。就框的生成和布局而言,该元素必须被视为在元素树中被其内容所替换(包括其源文档子元素及其伪元素,例如 ::before 和 ::after,它们像往常一样在元素的子元素之前/之后生成)。
注意:由于仅影响框树,因此基于文档树的任何语义(如选择器匹配、事件处理和属性继承)均不受影响。但截至编写本文时,主流浏览器中并未正确实现这一点,因此在 Web 上使用此功能必须小心,因为它可能会阻止可访问性工具访问元素的语义。
此值在替换元素和其他渲染不由 CSS 完全控制的元素上计算为 display: none;详情请参见 附录 B:display: contents 对特殊元素的影响。
注意:替换元素和表单控件受到特殊对待,因为只移除元素自身的生成框是一个定义模糊的操作。由于如果用例(和更精确的渲染模型)发展,此行为可能会细化,因此为了前向兼容性,作者应在这些元素上使用 display: none 而不是 display: contents。
- none(无)
- 元素及其后代不生成任何框或文本序列。
同样,如果文本节点被定义为表现为 display: none,它不会生成任何文本序列。
具有这两个值之一的元素没有内部或外部显示类型,因为它们根本不生成任何框。
注意:由于这些值导致受影响的元素不生成框,匿名框生成规则将完全忽略被省略的元素,就好像它们在框树中不存在一样。
然而,基于标记的关系不受这些值的影响,因为它们纯粹是渲染时的效果。 例如,虽然它们可能会影响哪个表格单元格显示在某一列中,但它们不会影响哪个表格单元格与特定的列元素相关联。同样,它们不能影响哪个 HTML summary 元素与特定表格相关联,也不能影响 legend 是否被视为特定 fieldset 内容的标签。
2.6. 预组合的行内级显示值
CSS 2 级为 display 使用单关键字语法,要求为同一布局模式的块级和行内级变体分别提供关键字。这些 <display-legacy> 关键字映射如下:
- inline-block
- 计算为 inline flow-root。
- inline-table
- 计算为 inline table。
- inline-flex
- 计算为 inline flex。
- inline-grid
- 计算为 inline grid。
注意:尽管这些关键字及其等效项计算为相同的值,但它们的指定值仍然是不同的。
注意:getComputedStyle() 序列化规则将始终输出这些预组合关键字,而不是等效的双关键字对,这是由于最短、最向后兼容的序列化原则。
2.7. 自动框类型转换
一些布局效果需要框类型的块化 (blockification) 或 行内化 (inlinification),这会将框的计算外部显示类型分别设置为 block 或 inline。(这对根本不生成框的显示类型没有影响,例如 none 或 contents。)此外:
-
如果行内框(inline flow)被行内化,它会递归地行内化其所有流内子元素,以便没有块级后代打破它所参与的行内格式化上下文。
-
出于遗留原因,如果行内块框(inline flow-root)被块化,它将变为一个 block 框(失去其 flow-root 性质)。为了保持一致性,run-in flow-root 框也会块化为 block 框。
-
如果布局内部框被块化,其内部显示类型转换为 flow,以便它变为块容器。行内化对布局内部框没有影响。(但是,将其置于此类行内上下文中通常会导致它们被包裹在适当类型的匿名行内级框中。)
注意:当框与其上下文不匹配时,有两种方法可用于修正框类型。一种是转换 display 的计算值,例如此处描述的块化和行内化。另一种是在框树构建期间(确定计算值后)发生的,即创建中间匿名框,这发生在表格、Ruby 和流式布局中。
2.8. 根元素的主体框
根元素的显示类型始终被块化,且其主体框始终建立一个独立格式化上下文。此框的包含块是初始包含块。
此外,display 为 contents 时,在根元素上计算为 block。
3. 显示顺序:order 属性
| 名称 | order |
|---|---|
| 值 | <integer>(整数) |
| 初始值 | 0 |
| 应用于 | 弹性项目 (flex items) 和 网格项目 (grid items) |
| 可继承 | 否 |
| 百分比 | 不可用 |
| 计算值 | 指定的整数 |
| 规范顺序 | 按语法 |
| 动画类型 | 按计算值类型 |
框通常按照它们在源文档中出现的顺序显示和布局。在某些格式化上下文中,可以使用 order 属性重新排列框的顺序,以刻意制造元素逻辑顺序与它们在 2D 视觉画布上空间排列的差异。(参见 § 3.1 重排与可访问性。)
具体而言,order 属性通过将弹性项目或网格项目分配到序数组中,来控制它们在其容器中出现的顺序。它接受单个 <integer> 值,指定项目所属的序数组。
article.sale-item{ display : flex; flex-flow : column; } article.sale-item > img{ order : -1 ; /* Shift image before other content (in layout order) */ align-self: center; }
< article class = "sale-item" > < h1 > Computer Starter Kit</ h1 > < p > This is the best computer money can buy, if you don’t have much money.< ul > < li > Computer< li > Monitor< li > Keyboard< li > Mouse</ ul > < img src = "images/computer.jpg" alt = "You get: a white desktop computer with matching peripherals." > </ article >
电脑入门套件
这是如果您预算不多,能买到的最好的电脑。
- 电脑
- 显示器
- 键盘
- 鼠标
弹性和网格容器以顺序修改后的文档顺序 (order-modified document order)布局其内容,从编号最小的序数组开始递增。属于同一序数组的项目按照它们在源文档中出现的顺序布局。这也会影响绘制顺序 [CSS2],就像弹性/网格项目在源文档中被重新排序一样。绝对定位的弹性/网格容器子元素在确定它们相对于弹性/网格项目的绘制顺序时,被视为具有 order: 0。
除非未来的规范另有说明,此属性对非弹性项目或网格项目的框没有影响。
3.1. 重排与可访问性
order 属性不会影响非视觉媒体(如语音)中的排序。同样,order 不会影响顺序导航模式(如循环切换链接)的默认遍历顺序,请参见例如 tabindex [HTML]。
作者必须仅将 order 用于内容的视觉重排,而不是逻辑重排。使用 order 执行逻辑重排的样式表是不符合规范的。
注意:这是为了让非视觉媒体和非 CSS 用户代理(通常呈线性内容)能够依赖逻辑源顺序,同时使用 order 来定制布局顺序。(由于视觉感知是二维且非线性的,所需的布局顺序并不总是逻辑上的顺序。)
为了在所有呈现模式下保留作者预期的顺序,创作工具——包括 WYSIWYG 编辑器以及基于 Web 的创作辅助工具——必须重新排列底层的文档源,并且不得使用 order 执行重排,除非作者明确指出了空间顺序应该与底层文档顺序(决定语音和导航顺序)不同步。
由于大多数情况下,重排应影响所有屏幕范围以及导航和语音顺序,工具通常会在 DOM 层执行拖放重排。然而,在某些情况下,作者可能希望针对不同屏幕尺寸设置不同的布局。工具可以通过结合使用 order 和媒体查询来实现此功能,但也应将最小屏幕尺寸的排序与底层 DOM 顺序挂钩(因为这很可能是逻辑线性呈现顺序),同时使用 order 定义其他尺寸范围内的视觉呈现顺序。
该工具将是符合规范的,而仅使用 order 处理拖放重排(无论实现起来多么方便)的工具则是不符合规范的。
注意:包括浏览器、辅助技术和扩展在内的用户代理可能会提供空间导航功能。本节并不排除在确定此类空间导航模式下的元素顺序时尊重 order 属性;事实上,要使此类功能工作,确实需要考虑这一点。但 order 并不是实现此类空间导航功能时唯一(甚至不是主要)需要考虑的 CSS 属性。一个实现完善的空间导航功能需要考虑 CSS 中所有修改空间关系的布局特性。
4. 不可见性:visibility 属性
| 名称 | visibility |
|---|---|
| 值 | visible | hidden | collapse |
| 初始值 | visible |
| 应用于 | 所有元素 |
| 可继承 | 是 |
| 百分比 | 不适用 |
| 计算值 | 按指定值 |
| 规范顺序 | 按语法 |
| 动画类型 | 离散 (discrete) |
| 媒体 | 视觉 |
visibility 属性指定盒子是否被渲染。不可见 (Invisible) 盒子仍会影响布局。(将 display 属性设置为 none 可完全抑制盒子的生成)。各属性值含义如下:
- visible
- 生成的盒子正常可见。
- 该组件可以在本包或其他任何使用包的其他组件中被引用;它不能在使用包中被不同的组件覆盖。
- 元素生成的任何盒子均为 不可见。但是,如果元素的后代具有 visibility: visible,则该后代可以可见。
- collapse
- 表示盒子是 折叠的 (collapsed),这可能导致它以特定于格式化上下文的方式占用比平时更少的空间。参见 表格中的动态行列效果 [CSS2] 以及 Flex 布局中的 折叠弹性项目 [CSS-FLEXBOX-1]。但在所有其他情况下(即除非另有规定),这只会使盒子变得 不可见,就像 hidden 一样。
注意: 目前,许多用户代理和/或辅助功能工具未能正确实现与 不可见 元素具有语义关联的可见元素所带来的辅助功能影响。因此,例如,将具有特殊角色(如表格行)的父元素设为 不可见,同时保留具有特殊角色(如表格单元格)的子元素为可见,可能会给这些工具的用户带来问题。在工具支持改善之前,作者应避免创建此类情况。
不可见 (Invisible) 盒子不会被渲染(就像它们完全透明一样),无法与之交互(其行为如同拥有 pointer-events: none),会被从导航中移除(类似于 display: none),并且不会被语音渲染(除非 speak 属性为 always [CSS-SPEECH-1])。然而,与 display: contents 一样,它们作为容器的语义角色不会受到影响,以确保任何 可见 的后代都能得到正确解读。
注意: 如果 speak 属性为 always,则原本 不可见 的盒子会被渲染为语音,并且可以通过非视觉/空间方法与之交互。
例如,以下是一个“剧透”元素的(故意简化的)可能实现方式,点击隐藏文本即可显示。
< p > The symbolism earlier in the movie becomes obvious at the end, when it’s revealed that< spoiler-text >< span > Luke is his own father</ span ></ spoiler-text > , making the wizard’s cryptic riddles meaningful.< style > spoiler-text { border-bottom : 1 px solid ; } spoiler-text > span { visibility : hidden ; } spoiler-text . shown > span { visibility : visible ; } </ style > < script > [... document. querySelectorAll( "spoiler-text" )]. forEach( el=>{ el. addEventListener( "click" , e=> el. classList. toggle( "shown" )); }); </ script >
此示例故意进行了大幅简化。它缺少了设计良好的剧透元素应具备的许多辅助功能和用户体验特性,以更清楚地展示 visibility 的用法。请勿在真实网站中直接复制此代码。
5. Run-In 布局
Run-in 盒子 是一种合并到其后续块中的盒子,它将自身插入到该块行内级内容的开头。这对于格式化紧凑的标题、定义和其他类似内容非常有用,因为虽然在 DOM 结构上标题位于正文之前,但期望的显示效果却是作为行内标题与文本并排布局。
<dl class='dict'>
<dt>dictionary
<dd>a book that lists the words of a language in alphabetical
order and gives their meaning, or that gives the equivalent
words in a different language.
<dt>glossary
<dd>an alphabetical list of terms or words found in or relating
to a specific subject, text, or dialect, with explanations; a
brief dictionary.
</dl>
<style>
.dict > dt {
display: run-in;
}
.dict > dt::after {
content: ": "
}
</style>
其格式化结果为
dictionary: a book that lists the words of a language in alphabetical order and explains their meaning. glossary: an alphabetical list of terms or words found in or relating to a specific subject, text, or dialect, with explanations; a brief dictionary.
Run-in 盒子的行为与其他任何 行内级盒子完全相同,但以下情况除外:
- 具有 flow 内部显示类型 的 Run-in 盒子会将其内容 行内化 (inlinifies)。
- 如果 Run-in 序列后紧跟一个未建立新的 块格式化上下文 的块盒子,它将作为该块盒子的直接子元素插入:位于其 ::marker 伪元素盒子(如果有)之后,但在该块内容生成的任何其他盒子(包括 ::before 伪元素生成的盒子,如果有)之前。如果可能,这种重新父级化 (re-parenting) 会递归进行(这样 Run-in 实际上成为其格式化上下文中后续最深层的“段落”的一部分,并沿途收集新邻近的 Run-in)。
重新父级化后的内容将如同最初就在该处一样进行格式化。注意,只有布局受到影响,继承不会,因为非匿名盒子的属性继承仅基于元素树。
- 否则(如果 Run-in 序列没有后跟这样的块),则会在 Run-in 序列及所有随后紧跟的行内级内容(直到但不包括下一个 Run-in 序列,如果有)周围生成一个匿名块盒子。
Run-in 序列 是连续兄弟 Run-in 盒子以及中间出现的 空白 和/或 流外盒子 (out-of-flow boxes) 的最大序列。
注意: 此陈述暗示流外盒子如果在两个 Run-in 盒子之间,会被重新父级化。另一种选择是保留中间的流外盒子,或者让流外盒子阻碍早期盒子的 Run-in。鼓励实现者和作者如果对此有倾向性的行为,请联系 CSSWG,因为当前这种行为是随机选择的。
此修正发生在 CSS2§9.2 中描述的匿名块和行内盒子修正之前,并影响受影响元素 第一格式化行 的确定,就好像 Run-in 序列最初就在盒子树中的最终位置一样。
注意: 由于最早的 Run-in 代表了其包含块 第一格式化行 上的首个文本,因此应用于该块元素的 ::first-letter 伪元素会选中 Run-in 的首字母,而不是其自身内容的首字母。
注意: 该 Run-in 模型与 [CSS2] 早期版本中提出的模型略有不同。
附录 A:术语表
以下术语在此定义以便查阅:
- 根元素
- 文档树 根部的 元素。在 DOM 下生成的 文档树 中,这是 文档元素;在 HTML 中它是
html元素。[DOM] [HTML] - 主体盒
- 当一个 元素 生成一个或多个 盒子 时,其中一个是 主体盒子 (principal box),它包含其后代盒子和生成的内容,也是涉及任何定位方案的盒子。
某些元素除主体盒子外可能还会生成额外的盒子(例如 list-item 元素会生成额外的标记盒子,或 table 元素会生成一个 主体 表格包装盒子 和一个额外的 表格网格盒子)。这些额外的盒子相对于主体盒子放置。
- 行内级
- 参与行内布局的内容。具体来说,即行内级盒子和 文本序列。
- 块级
- 参与 块布局 的内容。具体来说,即块级盒子。
- 行内盒 (inline box)
- 一个非替换的 行内级 盒子,其 内部显示类型 为 flow。行内盒子的内容参与与行内盒子本身相同的行内格式化上下文。
- inline
- 在无歧义时用作 行内盒子 或 行内级盒子 的简写,或作为形容词意为 行内级。后一种用法已弃用。
- 原子行内 (atomic inline)
- 一种行内级盒子,它是被替换的(如图像)或建立了新的格式化上下文(如 inline-block 或 inline-table),并且不能跨行拆分(如 行内盒子 和 ruby 容器 可以跨行拆分)。
- 块状容器
- 块容器要么仅包含参与 行内格式化上下文 的行内级盒子,要么仅包含参与 块格式化上下文 的块级盒子(必要时生成匿名块盒子以确保此约束,定义见 CSS2§9.2.1.1)。
仅包含行内级内容的块容器会建立一个新的 行内格式化上下文。该元素随后还会生成一个 根行内盒子 (root inline box),用于包裹其所有行内内容。注意,此 根行内盒子 概念有效地取代了 CSS2§9.2.2.1 中引入的“匿名行内元素”概念。
如果块容器的父格式化上下文不是 块格式化上下文,则它建立一个新的 块格式化上下文;否则,当自身参与 块格式化上下文 时,它要么为内容建立新的 块格式化上下文,要么沿用其参与的上下文,具体取决于其他属性(如 overflow 或 align-content)的约束。
注意: 块容器盒子可以同时建立块格式化上下文和行内格式化上下文。
- 块盒 (block box)
- 同时也是 块容器 的 块级盒子。
注意: 并非所有 块容器 盒子都是 块级 盒子:例如,非替换的 行内块 (inline blocks) 和非替换的表格单元格是块容器,但不是块级盒子。同样,并非所有块级盒子都是块容器:例如,块级替换元素(display: block)和 Flex 容器(display: flex)就不是块容器。
- block
- 在无歧义时,用作 块盒子、块级盒子 或 块容器盒子 的简写。
- 被替换元素
- 内容超出 CSS 格式化模型范围的元素,例如图像或嵌入文档。 例如,HTML
img元素的内容通常被其src属性所指向的图像所取代。替换元素通常具有 固有尺寸 (natural dimensions)。例如,位图图像具有以绝对单位指定的固有宽度和高度(从中显然可以确定固有比例)。另一方面,其他对象可能没有任何固有尺寸(例如,一个空白的 HTML 文档)。参见 [css-images-3]。
如果用户代理认为 替换元素 的尺寸可能向第三方泄露敏感信息,则可以认为它没有任何 固有尺寸。例如,如果 HTML 文档的固有尺寸根据用户的银行余额而改变,那么 UA 可能希望表现得好像该资源没有 固有尺寸 一样。
替换元素的内容不被视为 CSS 格式化模型的一部分;然而,它们的 固有尺寸 用于各种布局计算。替换元素总是建立一个 独立的格式化上下文。
非替换 (non-replaced) 元素是指未被 替换 的元素,即其渲染由 CSS 模型决定。
- 包含块 (containing block)
- 构成与其关联的 盒子 的尺寸和定位基础的矩形。值得注意的是,包含块 (containing block) 不是一个 盒子(它是一个矩形),但它通常源自 盒子 的尺寸。每个 盒子 都会相对于其 包含块 获得一个位置,但它并不受该 包含块 的限制;它可以 溢出。“盒子的包含块”一词指“盒子所处的包含块”,而不是它生成的包含块。
通常,盒子 的 边缘 作为后代盒子的 包含块;我们称一个盒子为其后代“建立”了 包含块。如果引用了 包含块 的属性,则它们引用的是生成该 包含块 的 盒子 上的值。(对于 初始包含块,除非另有规定,值取自根元素。)
详细信息请参见 [CSS2] 第 9.1.2 节 和 第 10.1 节 以及 CSS 定位布局 3 § 2.1 定位盒子的包含块。
- 包含块链 (containing block chain)
- 通过 包含块 关系形成祖先-后代链的一系列连续 包含块。例如,行内盒子 的包含块是其最接近的 块容器 祖先的内容盒;如果该块容器是流内 块,那么它的包含块由其父 块容器 形成;如果该祖父 块容器 是 绝对定位的,那么它的包含块是其最接近的定位祖先(不一定是父元素)的内边距边缘,依此类推,直到 初始包含块。
- initial containing block
- 根元素 的 包含块。初始包含块 建立了一个 块格式化上下文。有关其位置和尺寸,请参见 CSS2.1§10.1(针对 连续媒体)以及 [CSS-PAGE-3](针对 分页媒体)。
- 格式化上下文 (formatting context)
- 格式化上下文 是布局一组相关盒子的环境。不同的 格式化上下文 根据不同的规则布局其盒子。例如,Flex 格式化上下文 根据 Flex 布局 规则 [CSS-FLEXBOX-1] 布局盒子,而 块格式化上下文 根据块级和行内布局规则 [CSS2] 布局盒子。此外,某些类型的 格式化上下文 会交错并共存:例如,行内格式化上下文 存在于建立它的元素的 块格式化上下文 之内并与之交互,ruby 容器 在其 ruby 基础容器 所参与的 行内格式化上下文 之上覆盖了一个 ruby 格式化上下文。
一个盒子要么建立一个新的 独立格式化上下文,要么沿用其包含块的 格式化上下文。在某些情况下,它可能额外建立一个新的(非独立的)共存格式化上下文。然而,除非另有规定,建立一个新的 格式化上下文 都会产生一个 独立格式化上下文。该盒子建立的格式化上下文类型由其 内部显示类型 决定。例如,网格容器 建立一个新的 网格格式化上下文,ruby 容器 建立一个新的 ruby 格式化上下文,而 块容器 可以建立一个新的 块格式化上下文 和/或 一个新的 行内格式化上下文。参见 display 属性。
- 独立格式化上下文
- 当一个盒子建立一个独立的格式化上下文时(无论该 格式化上下文 类型是否与其父级相同),它本质上创建了一个新的、独立的布局环境:除了通过盒子本身的尺寸外,其后代的布局(通常)不受盒子外部 格式化上下文 的规则和内容影响,反之亦然。
例如,在 块格式化上下文 中,浮动盒子会影响周围盒子的布局。但它们的影响不会逃出其 格式化上下文:建立它们的 格式化上下文 的盒子会增长以完全包含它们,而外部的浮动不允许突出并影响该盒子内部的内容。
再例如,外边距不会跨越 格式化上下文 边界进行折叠。
排除项 (Exclusions) 能够影响跨越 独立格式化上下文 边界的内容。(在撰写本文时,它们是唯一能这样做的布局功能。) [CSS3-EXCLUSIONS]
某些属性可以强制一个盒子在原本不会的情况下 建立一个独立格式化上下文。例如,使一个盒子 流外 (out-of-flow) 会导致它 块化 (blockify) 以及 建立一个独立格式化上下文。再例如,contain 属性的某些值会导致盒子 建立一个独立格式化上下文。将一个块变成 滚动容器 会导致它 建立一个独立格式化上下文;然而,将一个 子网格 (subgrid) 变成 滚动容器 则不会——它继续充当子网格,其内容参与父 网格容器 的布局。
一个 块盒子,如果 建立了一个独立格式化上下文,则会为其内容建立一个新的 块格式化上下文。在大多数其他情况下,强制盒子 建立一个独立格式化上下文 是无操作的——要么盒子已经建立了 独立格式化上下文(例如 Flex 容器),要么无法在该类型的盒子上建立完全独立的格式化上下文(例如非替换的 行内盒子)。
- 块格式化上下文
- 行内格式化上下文
- 块 和 行内格式化上下文 定义于 CSS 2.1 第 9.4 节。行内格式化上下文 存在于(作为其包含的)块格式化上下文 内部;例如,属于 行内格式化上下文 的行盒会与属于 块格式化上下文 的浮动元素交互。
- 块布局(block layout)
- 在 块格式化上下文 内执行的 块级盒子 的布局。
- 块格式化上下文根(block formatting context root)
- 建立一个新的 块格式化上下文 的 块容器。
- BFC
- 块格式化上下文 或 块格式化上下文根 的缩写。有各种非正式定义,指代那些包含内部浮动、排除外部浮动并抑制外边距折叠的盒子,因此可能专门指代以下之一:
- 流外
- 流内
- 如果一个盒子被从其预期的位置和与周围内容的交互中提取出来,并使用其父格式化上下文中内容正常流之外的另一种范式进行布局,则该盒子是 流外 (out-of-flow) 的。如果盒子被浮动(通过 float)或 绝对定位(通过 position),则会发生这种情况。如果盒子不是 流外 的,则它是 流内 (in-flow) 的。
注意: 一些 格式化上下文 会抑制浮动,因此具有 float: left 的元素并不一定是 流外 的。
- 文档顺序
- 文档中盒子或内容出现的顺序(可能与渲染时出现的顺序不同)。为了确定伪元素的相对顺序,使用盒子树顺序,参见 CSS 伪元素 4 § 4 遵守树结构的伪元素。
有关这些术语的更完整定义,请参见 [CSS2] 第 9 章。
附录 B:display: contents 对特殊元素的影响
本节(目前)是非规范性的。
有些元素并非纯粹通过 CSS 盒子概念来渲染;例如,替换元素(如 img)、许多表单控件(如 input)以及 SVG 元素。
本附录定义了它们如何与 display: contents 交互。
HTML 元素
brwbrmeterprogress画布 (canvas)embedobjectaudioiframeimgvideoframeframesetinput (输入)textareaselect-
display: contents 计算为 display: none。
图例 (legend)-
根据 HTML,具有 display: contents 的
legend元素不是 渲染后的图例,因此它没有神奇的显示行为。(因此,它会对 display: contents 做出正常反应。) buttondetailsfieldset-
这些元素没有任何特殊行为;display: contents 仅仅移除它们的 主体盒子,而其内容照常渲染。
- 任何其他 HTML 元素
-
其行为与 display: contents 的正常行为一致。
SVG 元素
- 具有 CSS 盒子布局的
svg元素(这包括所有父元素为 HTML 元素的svg,以及文档根元素) -
display: contents 计算为 display: none。
- 所有其他同时也是 可渲染元素 的 SVG 容器元素
- SVG 文本内容子元素
use-
display: contents 将该元素从格式化树中剥离,并将其内容提升到原位置显示。这些内容包括
use的 shadow-DOM 内容。 - 任何其他 SVG 元素
-
display: contents 计算为 display: none。
例如,SVG 中的文本内容和文本格式化元素需要 text 元素上下文;如果您移除了 text,其子文本内容和元素就不再合法。因此,text 上的 display: contents 会阻止整个文本元素被渲染。相反,tspan 或 textPath 内的任何合法内容也是父文本格式化上下文中的合法内容,因此这些元素的提升行为适用。
同样,如果提升会将子元素从 非渲染元素(例如,pattern 或 symbol 内部的形状)转换为 渲染元素(例如,作为 svg 直接子元素的形状),这是非法的渲染上下文变更。因此,从不渲染的容器元素不能被 display: contents“取消盒子化 (un-boxed)”。
当一个元素从格式化树中剥离时,该元素上控制布局和视觉格式的任何 SVG 属性在渲染内容时都会被忽略。然而,映射到 CSS 属性的 SVG 呈现属性 仍会影响值处理和继承 [CSS-CASCADE-3];因此,此类属性可以通过影响这些后代上相应属性的值,从而影响该元素后代的布局和视觉格式。
MathML 元素
对于所有 MathML 元素,display: contents 计算为 display: none。
附录 C:规范作者的盒子构建指南
本节是非规范性的,为规范作者提供指导。
-
对其内容进行 块化 的盒子不能直接包含 行内级 内容;在此类元素内生成的任何盒子或文本序列必须被 块化 或包裹在 匿名 块容器 中。
-
从根本上无法建立 独立格式化上下文 的盒子(如非替换的行内元素)不应被要求 建立一个独立格式化上下文。请先将它们块化,或以其他方式将其盒子类型更改为能够建立 独立格式化上下文 的类型。
致谢
我们要感谢多年来试图分离盒子生成中不同细节的许多人,特别是 Bert Bos,他最后一次使用 display-model 和 display-role 的尝试虽然没有成功,但为当前的规范做了准备;Anton Prowse,他对 CSS2.1 第 9 章的不懈抨击迫使混乱中产生了一些秩序;以及 Oriol Brufau,他梳理了本规范中数十个细微的区别和错误。还要特别提到 David Baron、Mats Palmgren、Ilya Streltsyn 和 Boris Zbarsky 的反馈。
变更 (Changes)
2020 候选推荐标准以来的变更
自 2020 年 5 月 19 日候选推荐标准 以来的 意见处置 已发布。
自 2020 年 5 月 19 日候选推荐标准 以来的变更包括:
- 将“文本运行 (text run)”更名为“文本序列 (text sequence)”。(Issue 7768)
- 定义了 根元素,并在 § 2.8 根元素的主体盒子 及 初始包含块 的定义中澄清了其作为块级的布局。(PR 8095, Issue 7207, Issue 6480, Issue 7786)
- 从 [CSS-FLEXBOX-1] 中引入了 order 属性定义,因为它也适用于 网格项目。(Issue 5865)
- 从 [CSS2] 导入了 visibility 属性定义,并对其进行了更新,使其更加详尽和完整。(Issue 6123)
- 定义了具有 布局内部 (layout-internal) display 的 替换元素 被视为 display: inline。(Issue 6000)
-
澄清了 <display-legacy> 值实际上 计算 为与其等效的双关键字形式相同的值。(Issue 5575)
- inline-…
-
表现为计算为 inline …。
注意:尽管这些关键字及其等效形式计算为相同的值,但它们的 指定值 保持不同。
注意:
getComputedStyle()序列化规则将始终输出这些预组合的关键字,而不是等效的双关键字对,这是由于 最短且最向后兼容的序列化原则。 -
澄清了 块化 和 行内化 是 计算值 的变更。(Issue 6251)
- 为方便起见,在术语表中添加了 块布局 的定义。
- 更新了对 CSS 网格布局 的引用。
- 各种轻微的编辑修正和交叉链接改进。
2019 候选推荐标准以来的变更
自 2019 年 7 月 11 日候选推荐标准 以来的变更包括:
- 合并了来自 [CSS2] 的额外文本到 包含块 的定义中。
-
澄清了对于 CSS 而言,元素和文本以外的 DOM 节点被忽略。
(某些源文档从更复杂的树开始,例如 DOM,它可以有注释节点和其他类型的内容。对于 CSS 而言,所有这些额外的节点类型都会被忽略,就好像它们不存在一样。)
- 改进/移动了与 绝对定位 相关的术语表定义。
自 2018 年 8 月 28 日候选推荐标准 以来的变更包括:
- 定义了盒子树的父级关系;参见 父盒子。
- 在术语表中添加了 绝对定位 的定义;从 CSS2 复制 以便更易于引用。
- 在 § 1 简介 中添加了对各种碎片形式的交叉引用。
- 将“表格盒子”重命名为“表格网格盒子”,以便与“表格包装盒子”更容易区分。
- 将“除非另有规定”添加到根元素 → 初始包含块的传播中,因为针对 HTML
body元素存在一些令人遗憾的特殊例外。
达到候选推荐标准状态之前的变更
有可用的 意见处置。
自 2018 年 4 月 20 日工作草案 以来的变更包括:
- 具有 display: contents 且表现为 display: none 的元素现在计算为 display: none。(Issue 2755)
- 区分了“新的” 格式化上下文 和 独立格式化上下文,因为某些格式化上下文会发生分层。(Issue 2597, Issue 1457)
- 定义了建立 独立格式化上下文 的 块盒子,其使用的 display 为 flow-root,以提供一个更容易的参考点。(Issue 1550)
- 澄清了 display 是不可动画的(而不是离散动画的)。(Issue 2938)
- 轻微的编辑修正。
自 2017 年 7 月 20 日工作草案 以来的变更包括:
-
收紧了 inline-block / inline flow-root 块化 的规则,以确保与 CSS2 兼容。(Issue 1246)更新了 run-in flow-root 的处理方式以匹配。(Issue 1715)
-
调整了 display 的语法,将 list-item 关键字放在最后。这会影响预期的序列化顺序。(Issue 1621)
-
增加了对建立行内格式化上下文的块容器中 块格式化上下文 和 行内格式化上下文 之间交互的更好定义。(Issue 1553)
-
更清晰地定义了属性值如何在元素及其盒子之间反映(在元素生成多个盒子的情形下)。(Issue 1643)
-
澄清了空文本对象在 CSS 渲染中会被忽略。(Issue 1808)
-
澄清了 display 对文档语义没有影响,因为这是 UA 中的一个常见错误。(Issue 2355)
-
修正了 display 的 计算值 定义中的错误(它肯定不是“如指定的那样”,因为各种属性触发了 块化 和 行内化 规则)。(Issue 1716)
-
添加了对 文档顺序 的定义。
-
在 附录 B 关于 display: contents 的细节中添加了缺失的 SVG 元素(Issue 2118),澄清了 SVG 属性的影响(Issue 2502),并定义了 MathML 的行为(Issue 2167)。
-
为未来匿名盒子构建规则的规范作者添加了一些 指导。(Issue 1643)
-
将关于“成为格式化上下文”的部分推回至 CSS 包含 (Containment) 中,并在那里使用。
-
各种轻微的措辞修正和澄清。
自 2017 年 1 月 26 日工作草案 以来的变更包括:
-
移除等效于 inline list-item 的 inline-list-item 值。
-
向 元素树 添加了“文本节点”的概念,并向 盒子树 添加了“文本运行”的概念,以定义在 display: contents 上下文中的行为。(Issue 19, Issue 32)
-
定义了根元素为“流内”。(Issue 3)
-
定义了 ::first-line/::first-letter 与 run-in 之间的交互。(Issue 5, Issue 42)
-
澄清了块/行内/Run-in 仅决定 流布局 中的行为;在其他上下文中被忽略。
-
Run-in 是一种行内盒子类型,而不仅仅是“类似于”行内盒子。
-
修复了 Run-in 盒子树构建中缺乏递归的问题。(Issue 45)
-
添加了一个关于 display: contents 如何在“特殊元素”上工作的附录。(Issue 8, Issue 18)
-
添加了“成为格式化上下文”的定义。
-
各种轻微的修正和轻微的澄清。
还有一个可用的 意见处置。
自 2015 年 10 月 15 日工作草案 以来的变更包括:
- 将 box-suppress/display-or-not 属性推迟到下一级 Display 中,以便留出时间进行更多用例的讨论。
- 指定了 display: contents 对特殊元素(如替换元素和表单控件)的影响。
- 澄清了如果由于 display: contents 而未生成元素本身的盒子,其 ::before 和 ::after 伪元素仍然存在。
- 澄清了事件冒泡不受 display: contents 的影响。
- 澄清了 Run-in 与流外元素及 ::first-letter 的交互。
- 将 table-caption 和 table-cell 切换为使用 flow-root 作为其 内部显示类型,因为它们总是形成格式化上下文根。
- 结束了剩余的问题并添加了风险清单。
自 2015 年 7 月 21 日工作草案 以来的变更包括:
自 2014 年 9 月 11 日工作草案 以来的变更包括:
- 移除了 display-inside、display-outside 和 display-extras 长属性,转而使 display 支持多值。(这样做是为了对可组合的内容施加约束。如果未来不再需要或不再希望保留这些限制,本规范的后续版本可能会放宽其中部分或全部限制。)
- 创建了 flow 和 flow-root 内部显示类型,以更好地表达流式布局的 显示类型,并为将元素设为 BFC 根元素创建了显式开关。(这应该能够消除对诸如 ::after { clear: both; } 和 overflow: hidden 这样旨在达到此目的的 Hack 手段的需求。)
隐私考虑
本规范未引入新的隐私考虑。
安全考虑
本规范未引入任何新的安全考量。
自我评估问卷
- 本规范是否处理个人身份信息?
不。
- 本规范是否处理高价值数据?
不。
- 本规范是否为跨浏览会话持久化的源引入了新状态?
不。
- 本规范是否向 Web 暴露了持久的、跨源的状态?
不。
- 本规范是否向一个源暴露了它目前无法访问的其他数据?
不。
- 本规范是否启用了新的脚本执行/加载机制?
不。
- 本规范是否允许源访问用户位置?
不。
- 本规范是否允许源访问用户设备上的传感器?
不。
- 本规范是否允许源访问用户本地计算环境的各个方面?
不。
- 本规范是否允许源访问其他设备?
不。
- 本规范是否允许源对用户代理的原生 UI 有一定程度的控制?
不。
- 本规范是否向 Web 暴露临时标识符?
不。
- 本规范是否区分第一方和第三方上下文中的行为?
不。
- 本规范应如何在用户代理的“隐身”模式上下文中工作?
没有区别。
- 本规范是否将数据持久化到用户的本地设备?
不。
- 本规范是否有“安全考虑”和“隐私考虑”部分?
是的。
- 本规范是否允许降低默认安全特性?
不。