1. 引言
本节为规范性内容。
CSS 以源文档为输入,源文档组织为树,由元素(可包含其他元素和文本节点的混合),以及文本节点(可包含文本), 并将其渲染到一个画布上,如你的屏幕、纸张或者音频流。 虽然任何这样的源文档都可以被 CSS 渲染, 最常用的类型是 DOM。[DOM](有些更复杂的树类型可能还包含其他类型的节点, 如 DOM 中的注释节点。 对于 CSS 而言, 所有这些额外节点类型都会被忽略, 就好像它们不存在一样。)
为此,CSS 生成了一个中间结构, 即盒子树, 它表示渲染文档的格式结构。 盒子树中的每个盒子,对应于画布上的其相应元素(或伪元素)在空间和/或时间上的表现, 而盒子树中的每个文本序列,同样表示其文本节点的对应内容。
要创建盒子树, CSS 首先使用级联与继承, 为源树中的每个元素和文本节点的每个 CSS 属性分配一个计算值。 (参见[CSS-CASCADE-3]。)
然后,对于每个元素, CSS 根据该元素的display属性生成零个或多个盒子。 通常,一个元素会生成一个盒子, 即主盒, 它代表自身并在盒子树中包含其内容。 不过,有些display值 (如display: list-item) 会生成多个盒子 (例如一个主块盒和一个子标记盒)。 而有些值 (如none或contents) 会导致该元素及/或其后代不生成任何盒子。盒子通常按其display类型称呼——例如,由 display: block 元素生成的盒子称为“块盒”或简称“块”。
一个盒子会分配与其生成的元素相同的样式,除非另有说明。
一般来说,继承属性会分配给主盒,
并通过盒子树继承到同一元素生成的其他盒子。
非继承属性默认应用于主盒,
但当元素生成多个盒子时,
有时会规定应用于其他盒子:
例如,应用于表格元素的border属性
实际应用于其表格网格盒,
而不是其主表格包装盒。
如果值计算过程改变了这些盒子的样式,
当获取元素样式(如通过getComputedStyle())时,
元素会反映每个属性实际应用到的盒子的值。
同样,每个相邻的文本节点序列会生成一个文本序列,包含它们的文本内容, 并分配与生成的文本节点相同的样式。 但如果序列没有文本,则不会生成文本序列。
在构建盒子树时, 由一个元素生成的盒子是其祖先元素主盒的后代。 一般情况下, 一个元素的父盒是其最近祖先元素生成的主盒; 但也有一些例外, 如run-in盒、 生成多个容器盒的显示类型(如表格), 以及中间的匿名盒。
匿名盒 指没有与任何元素关联的盒子。匿名盒在特定情况下生成, 以在盒子树需要某种嵌套结构但元素树生成的盒子无法满足时修正结构。 例如,表格单元格盒需要特定类型的父盒(表格行盒), 如果其父不是表格行盒,则会在自己外层生成一个匿名表格行盒。 (参见[CSS2] § 17.2.1。) 与元素生成的盒子不同,后者的样式严格通过元素树继承, 匿名盒(仅存在于盒子树中)会通过其盒子树父级进行继承。
在布局过程中,盒子和文本序列都可以被分割为多个片段。 例如,当行内盒和/或文本序列在换行时被分割, 或块盒在分页或分栏时被分割, 这一过程称为碎片化。 也可能因为双向文本重排序(详见应用双向重排序算法, CSS Writing Modes), 或更高级别的显示类型盒分割, 如块中行内分割(见CSS2§9.2), 或跨列分块分割 (见CSS 多栏布局)。 因此,一个盒子由一个或多个盒子片段组成, 文本序列由一个或多个文本片段组成。 更多关于碎片化的信息,参见[CSS-BREAK-3]。
注:许多 CSS 规范编写于这些术语尚未明确之前, 或者使用术语不准确, 因此在阅读旧规范时使用这些术语要留意其实际含义。 应能根据上下文推断其真正含义。 如果发现规范有误,请报告错误,以便修正。
注:关于“听觉”盒子树及其与display属性的交互,参见CSS Speech 模块。[CSS-SPEECH-1]
1.1. 模块交互
本模块替换并扩展了display属性在[CSS2]第9.2.4节中的定义。
本模块中的任何属性均不适用于::first-line或::first-letter伪元素。
1.2. 取值定义
本规范遵循CSS 属性定义惯例(见[CSS2]),并使用取值定义语法(见[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>关键字;具体计算规则见各规范正文 |
| 规范顺序: | 按语法 |
| 动画类型: | 见§ 2.9 display 的动画与插值 |
用户代理应在所有媒介(包括非可视媒介)上支持该属性。 display 属性定义了元素的显示类型, 即元素生成盒子的两种基本方式:
某些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 | — | 子树在盒子树中被省略 |
| contents | — | 元素在盒子树中被内容替代 |
| block | block flow | 块级 块容器(即块盒) |
| flow-root | block flow-root | 块级 块容器,建立新的块格式化上下文(BFC) |
| inline | inline flow | 行内盒 |
| inline-block | inline flow-root | 行内级 块容器(即inline block) |
| run-in | run-in flow | run-in 盒(一种带有特殊盒子树处理规则的行内盒) |
| list-item | block flow list-item | 块盒,带有额外的标记盒 |
| inline list-item | inline flow list-item | 行内盒,带有额外的标记盒 |
| flex | block flex | 块级 flex 容器 |
| inline-flex | inline flex | 行内级 flex 容器 |
| grid | block grid | 块级 grid 容器 |
| inline-grid | inline grid | 行内级 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
- 元素在流式布局中生成一个块级盒。[CSS2]
- inline
- 元素在流式布局中生成一个行内级盒。[CSS2]
- run-in
- 元素生成一个run-in 盒,它是一种特殊行为的行内级盒,尝试与后续块容器合并。 详见§ 6 Run-In 布局。
如果指定了<display-outside>值,但省略了<display-inside>, 元素的内部显示类型默认为flow。
2.2. 内部显示布局模型:flow、flow-root、table、flex、grid 和 ruby 关键字
<display-inside> 关键字指定元素的内部显示类型, 决定了内容的格式化上下文类型 (假定它是非替换元素)。 定义如下:
- flow
-
元素使用流式布局(块与行内布局)排列内容。
如果其外部显示类型为inline或run-in, 且参与的是块或行内格式化上下文, 则生成一个行内盒。
否则,生成一个块容器盒。
根据其他属性值(如position、float 或 overflow), 以及它自身是否参与块或行内格式化上下文, 它要么为内容创建新的块格式化上下文, 要么将内容整合进父格式化上下文。 参见CSS2.1 第9章。[CSS2]会为内容新建块容器 并建立新的块格式化上下文时, 其实际使用的内部显示类型视为flow-root。
- flow-root
- 元素生成一个块容器盒, 并以流式布局排列内容。 总是为内容新建一个块格式化上下文。[CSS2]
- table
- 元素生成主表格包装盒,建立块格式化上下文, 并包含一个额外生成的表格网格盒用于建立表格格式化上下文。[CSS2]
- flex
- 元素生成主flex 容器盒, 并建立flex 格式化上下文。[CSS-FLEXBOX-1]
- grid
-
元素生成主grid 容器盒,
并建立grid 格式化上下文。[CSS-GRID-1]
(使用subgrid 的 grid 可能不会新建grid 格式化上下文; 详见[CSS-GRID-2]。)
- ruby
- 元素生成ruby 容器盒, 并建立ruby 格式化上下文,此外还会将其基础内容集成到父格式化上下文(若为行内)或生成适当外部显示类型的包装盒(若非行内)。[CSS-RUBY-1]
如果指定了<display-inside>值但省略<display-outside>, 元素的外部显示类型默认为block——除了ruby,其默认为inline。
2.3. 生成标记盒:list-item 关键字
list-item 关键字 使元素生成一个::marker伪元素[CSS-PSEUDO-4],其内容由list-style属性指定 (CSS 2.1§12.5 列表)[CSS2], 以及指定类型的主盒用于自身内容。
如果没有指定内部显示类型值, 主盒的内部显示类型默认为flow。 如果没有指定外部显示类型值, 主盒的外部显示类型默认为block。
注:在本级别中,受语法限制, 列表项仅限于流式布局显示类型 (block / inline / run-in,配合 flow / flow-root 内部类型)。 这一限制未来版本可能会放宽。
2.4. 布局内部显示类型:table-* 和 ruby-* 关键字
某些布局模型,如table和ruby, 具有复杂的内部结构, 子元素和后代可以承担多种不同的角色。 本节定义了这些“布局内部”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-caption
- 元素生成表格标题盒, 它是一个块盒,在表格与包装盒之间有特殊行为。 见CSS2§17.2 [CSS2]。
-
- 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> 关键字定义如下:
- contents
-
元素自身不会生成任何盒子,
但其子元素和伪元素仍照常生成盒子和文本序列。
在盒子生成和布局时,
该元素必须视为在元素树中被其内容替换
(包括其源文档子元素和伪元素,
如::before和::after伪元素,
它们在子元素前后照常生成)。
注:只有盒子树受影响, 基于文档树的语义,如选择器匹配、事件处理和属性继承不受影响。但实际主流浏览器尚未正确实现此特性, 因此在网页上使用时需谨慎, 可能会导致辅助工具无法获取元素语义。
此值在替换元素及渲染不完全受 CSS 控制的其他元素上,会被计算为display: none; 详情见附录B:display: contents 对非常规元素的影响。
注:替换元素和表单控件会被特殊处理, 因为仅移除元素自身生成的盒子的行为基本上是未定义的。 随着相关用例和更精确的渲染模型发展,此行为可能被细化, 作者应优先对这类元素使用display: none,而非display: contents,以保证前向兼容性。
- none
-
元素及其后代不会生成盒子或文本序列。
同样地,如果文本节点被定义为display: none, 它不会生成文本序列。
使用这两种值的元素没有内部或外部显示类型, 因为它们根本不会生成任何盒子。
注:由于这些值导致元素不生成盒子, 匿名盒生成规则会完全忽略这些被省略的元素, 就像它们在盒子树中不存在一样。
但基于标记的关系并不受这些值影响,
因为它们只在渲染时生效。 例如,
虽然它们可能影响哪一个表格单元格显示在一列中,
但不会影响哪个单元格与特定列元素关联。
同样,它们也不会影响哪个 HTML
summary
元素与特定表格关联,
或
legend
是否视为标记特定
fieldset
的内容。
2.6. 预组合行内级 display 取值
CSS 第二级使用单关键字语法表示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 (分别对应)。 (这对根本不生成盒子的display 类型, 如none或contents,无任何影响。) 另外:
-
如果一个行内盒(inline flow)被行内化, 会递归对其所有 in-flow 子元素行内化, 以保证没有块级后代分隔其所处的行内格式化上下文。
-
出于兼容性考虑, 如果一个inline block 盒 (inline flow-root) 被块化, 它会变为block盒 (失去其flow-root特性)。 为保持一致, run-in flow-root盒 块化后也变为block盒。
-
如果一个布局内部盒被块化, 其内部显示类型转换为flow,从而成为块容器。行内化对布局内部盒无影响。 (但放入此类行内上下文时, 通常会在其外层包裹合适类型的匿名行内级盒。)
注:当盒子类型与其上下文不匹配时,有两种修正方式。 一种是对display的计算值进行转换,如本节所述的块化和行内化。 另一种是在盒子树构建(计算值已定后)阶段创建中间匿名盒, 例如表格、ruby和流式布局中的处理。
- 绝对定位或浮动元素会块化盒子的显示类型。[CSS2]
- 包含于ruby 容器会行内化该盒的显示类型,详见[CSS-RUBY-1]。
- 父元素为grid或flex的display 值会块化盒子的显示类型。[CSS-GRID-1] [CSS-FLEXBOX-1]
2.8. 根元素的主盒
根元素的显示类型始终会被块化, 其主盒始终建立一个独立格式化上下文。 该盒子的包含块是初始包含块。
此外,根元素上的display为contents时会被计算为block。
2.9. display 的动画与插值
一般来说, display属性的动画类型为离散。 不过, 类似于visibility的插值(参见Web Animations § Animation of visibility), 在 none 与其他display值间插值时,p 介于 0 和 1 时映射为非 none 值。 另外, 只要元素的display值(无视 Transitions 和 Animations 的 cascade origins)会被计算为 none,该元素就是inert的。
3. 显示顺序:order 属性
| 名称: | order |
|---|---|
| 取值: | <integer> |
| 初始值: | 0 |
| 适用对象: | 弹性盒项目(flex items)和网格项目(grid items) |
| 继承性: | 否 |
| 百分比: | 不适用 |
| 计算值: | 指定的整数 |
| 规范顺序: | 按语法 |
| 动画类型: | 按计算值类型 |
盒子通常按照它们在源文档中的顺序显示和布局。 在某些格式化上下文中, 可以使用order属性重新排列盒子的顺序, 故意制造元素逻辑顺序与其在二维可视画布上的空间排列不一致的效果。 (参见§ 3.1 重排与可访问性。)
具体来说, order属性通过将弹性盒项目或网格项目 分配到多个序号组,实现其在容器内的显示顺序控制。 它只接受一个<integer>值, 用于指定项目属于哪个序号组。
article.sale-item{ display : flex; flex-flow : column; } article.sale-item > img{ order : -1 ; /* 将图片在布局顺序上提前 */ 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 >
Computer Starter Kit
This is the best computer money can buy, if you don’t have much money.
- Computer
- Monitor
- Keyboard
- Mouse
弹性盒容器和网格容器 以顺序修正后的文档顺序布局其内容, 从序号最小的组开始依次排列。 属于同一序号组的项目,按其在源文档中的顺序排列。 这也影响绘制顺序[CSS2], 就好像弹性盒/网格项目在源文档中被重排一样。 弹性盒/网格容器的绝对定位子元素在确定其与 flex/grid 项的绘制相对顺序时,视为 order: 0。
除非未来规范另有规定, 此属性对不是弹性盒项目或网格项目的盒子无效。
3.1. 重排与可访问性
order属性不会影响非可视媒体(如语音)中的顺序。
同样,order不会影响顺序导航模式(如 Tab 键循环链接,参见 tabindex
[HTML])的默认遍历顺序。
作者只能用order进行空间顺序重排,不得用于逻辑顺序重排。 使用order进行逻辑重排的样式表不符合规范。
注:这样做可保证非可视媒体和非CSS用户代理(通常线性展现内容) 可以依赖逻辑源顺序, 而order用于调整布局顺序。 (视觉感知是二维且非线性的,所需布局顺序未必等于逻辑顺序。)
为确保所有呈现模式下作者意图顺序一致, 编辑工具(包括所见即所得编辑器及基于Web的辅助工具)必须在底层文档源做重排, 不得用order进行重排, 除非作者明确要求空间顺序与底层文档顺序(决定语音和导航顺序)不同步。
通常情况下,重排应影响所有屏幕尺寸及导航和语音顺序, 工具应在 DOM 层进行拖拽重排。 但有时作者希望不同屏幕尺寸下布局顺序不同。 工具可通过 order 配合媒体查询实现, 同时将最小屏幕尺寸的顺序与底层 DOM 顺序绑定 (因为这多半是逻辑线性顺序), 其他尺寸则用 order 定义视觉顺序。
这种工具是合规的,而仅用 order 实现拖拽重排 (即便实现简单)则不合规。
注:用户代理(包括浏览器、可访问性技术及扩展) 可以提供空间导航特性。 本节不妨碍在此类空间导航模式下参考order属性 来决定元素顺序; 实际上,为使该功能生效,必须考虑此属性。 但order并非此类空间导航特性需要考虑的唯一(甚至主要)CSS属性。 一个良好的空间导航功能应综合考虑所有影响空间关系的 CSS 布局特性。
4. 阅读顺序:reading-flow 属性
阅读流容器 是具有有效 reading-flow 值(非 normal)的 flex 或 grid 容器。
渲染定义的同级阅读流 是 阅读流容器 的一个有序的容器内在流子元素列表。 所有子元素必须渲染为一个元素,并被视为阅读流容器中的同级。 顺序由 reading-flow 属性决定。
这个属性是否也应该应用于表格?[Issue #9922]
定义 reading-flow 如何与可聚焦的 display: contents 元素交互。[Issue #9230]
| 名称: | reading-flow |
|---|---|
| 取值: | normal | flex-visual | flex-flow | grid-rows | grid-columns | grid-order |
| 初始值: | normal |
| 适用于: | flex 和 grid 容器 |
| 是否继承: | 否 |
| 百分比: | 不适用 |
| 计算值: | 按指定 |
| 规范顺序: | 按语法 |
| 动画类型: | 不可动画 |
reading-flow 属性控制 flex 或 grid 布局中元素在语音渲染或使用(线性)顺序导航方法时的呈现顺序。
它只接受一个关键字值。取值定义如下:
- normal
- 遵循 DOM 中元素的顺序。
- flex-visual
- 仅对 flex 容器生效。 遵循 flex 项的视觉阅读顺序, 并考虑书写模式。 因此,如果文档为英文,且 flex-direction: row-reverse 并设置 reading-flow: flex-visual,则其阅读顺序为从左到右。
- flex-flow
- 仅对 flex 容器生效。 遵循 flex-flow 的方向。
- grid-rows
- 仅对 grid 容器生效。 按行遵循 grid 项的视觉顺序, 并考虑书写模式。
- grid-columns
- 仅对 grid 容器生效。 按列遵循 grid 项的视觉顺序, 并考虑书写模式。
- grid-order
- 仅对 grid 容器生效。 遵循 order-modified document order。 因此,除非使用 order 属性更改了项目顺序,否则与 normal 一样。
< div class = "wrapper" > < a href = "#" > Item 1</ a > < a href = "#" > Item 2</ a > < a href = "#" > Item 3</ a > </ div >
.wrapper{ display : flex; flex-direction : row-reverse; reading-flow : flex-visual; }
< div class = "wrapper" > < a class = "a" href = "#" > Item 1</ a > < a class = "b" href = "#" > Item 2</ a > < a class = "c" href = "#" > Item 3</ a > < a class = "d" href = "#" > Item 4</ a > </ div >
.wrapper{ display : grid; grid-template-columns : repeat ( 3 , 150 px ); grid-template-areas : "d b b" "c c a" ; reading-flow : grid-rows; } .a{ grid-area : a; } .b{ grid-area : b; } .c{ grid-area : c; } .d{ grid-area : d; }
reading-flow 属性不会影响布局或绘制顺序,因此对视觉 画布 的渲染没有影响。
当使用 flex-* 或 grid-* 关键字值时, 会考虑 order 属性。
order=-1。
这些项目的阅读顺序因此为:
“Item 3”、“Item 1”、“Item 2”。
< div class = "wrapper" > < a href = "#" > Item 1</ a > < a href = "#" > Item 2</ a > < a href = "#" > Item 3</ a > </ div >
.wrapper a:nth-child ( 3 ) { order : -1 ; } .wrapper{ display : flex; reading-flow : flex-flow; }
源文档应表达元素的底层逻辑顺序。 reading-flow 属性用于某些文档在布局变化时可能有多种阅读顺序的场景, 例如响应 媒体查询 时。 此类情况下,最常用或最基本的阅读顺序应编码在源顺序中, 以便文档在没有 CSS 时也具有合理意义。
设计考量与背景
关于 reading-flow 设计的部分考量有:
-
存在明显的用例需要将阅读和导航顺序与盒子布局顺序分离, 其中最基本的是确保阅读和导航顺序与视觉感知顺序一致,当其与盒子布局顺序不同时。 (视觉感知是非线性的,并受视觉元素的大小、颜色对比度、间距等影响, 而不仅仅是页面上的空间坐标。)
-
这是Web 平台架构的核心原则, 以便内容能够被现有及未来的各种设备上的最广泛用户访问, 底层文档应当在没有 CSS 的情况下也是有意义的。 因此底层文档顺序应代表元素的逻辑顺序, 而不受视觉表现影响。
-
对于页面中没有强烈固有顺序的组件, 一个文档可以有多种视觉表现和不同布局, 但都传递相同的语义信息。 应当让这些表现都具有良好的无障碍性。
-
线性导航、焦点顺序和屏幕阅读器顺序应始终一致,因为有些用户会同时使用它们。
-
页面的每个组件或层级都可能有不同的重排序需求, 所以 CSS 的重排序控制不应过于容易被“一刀切”地应用 (如 box-sizing) 而应更偏向于针对性的使用 (如 流向相关与物理属性值)。
DOM 需要一个方便的重排序函数, 以便作者(包括通常不写 JS 的作者) 在需要时能轻松进行源顺序重排, 而不是误用 order 或 reading-flow。[Issue #7387]
5. 不可见性:visibility 属性
| 名称: | visibility |
|---|---|
| 取值: | visible | hidden | collapse |
| 初始值: | visible |
| 适用于: | 所有元素 |
| 是否继承: | 是 |
| 百分比: | 不适用 |
| 计算值: | 按指定 |
| 规范顺序: | 按语法 |
| 动画类型: | 离散型 |
| 媒体: | 视觉 |
visibility 属性指定盒子是否被渲染。不可见的盒子仍然参与布局。 (将 display 属性设置为 none 可以完全阻止盒子的生成。) 各取值含义如下:
- visible
- 生成的盒子正常可见。
- hidden
- 该元素生成的所有盒子均为 不可见。 但如果其子元素设置了 visibility: visible,则这些后代元素可以可见。
- collapse
- 表示盒子已折叠, 这可能导致其在特定格式化上下文下占据更少空间。 详见 表格中的动态行和列表现 [CSS2] 以及 flex 布局下的 折叠 flex 项 [CSS-FLEXBOX-1]。 但在所有其他情况下, (即除非另有说明) 这只会使盒子 不可见, 与 hidden 一样。
注意: 目前许多用户代理和/或无障碍工具 并未正确实现 与 不可见元素有语义关系的可见元素的无障碍影响, 例如, 让具有特殊角色(如表格行)的父元素 不可见,而其具有特殊角色(如单元格)的子元素可见, 对这些工具的用户来说可能会带来问题。 作者应避免此类情况, 直到工具支持改善为止。
不可见的盒子不会被渲染 (就像它们完全透明一样), 也无法被交互 (行为类似于 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 的用法。 请勿直接用于真实网站。
6. 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.
- 具有内部显示类型为flow的run-in 盒会对其内容进行行级化。
-
如果run-in 序列后紧跟一个不会建立新块格式化上下文的块盒,
那么该序列会作为该块盒的直接子元素插入:
插入位置在其::marker伪元素盒(如有)之后,
但在该块内容生成的其他盒(包括::before伪元素生成的盒,如有)之前。
这种重新父级操作会递归进行(因此 run-in 实际上会成为其格式化上下文中最深层后续“段落”的一部分,逐步收集新相邻的 run-in)。
重新父级后的内容会像最初就在那一样进行排版。注意:只影响布局,不影响继承,因为非匿名盒的属性继承仅基于元素树。
- 否则(即run-in 序列后没有这种块), 会在该run-in 序列以及其后所有紧跟的行级内容(直到下一个run-in 序列,如有)外面生成一个匿名块盒。
run-in 序列指一组最大长度的连续同级run-in 盒及其间的空白和/或脱离流的盒。
注意: 这意味着如果两个 run-in 盒之间有脱离流的盒,这些脱离流的盒也会被重新归为子级。 另一种做法是将这些脱离流的盒留在原处,或让其阻止前一个 run-in 盒并入后续块。 实现者和作者如有偏好行为,欢迎联系 CSSWG,目前这一行为是随机选定的。
此修正发生在CSS2§9.2中描述的匿名块和行盒修正之前, 并影响受影响元素的首行的判定, 就好像run-in 序列最初就在盒树的最终位置一样。
注意: 最早的 run-in 代表其包含块的首行的首文本, 所以对该块元素应用::first-letter伪元素时,会选中 run-in 的首字母,而不是其自身内容的首字母。
注意: 该 run-in 模型与早期 [CSS2] 的提案略有不同。
附录A:术语表
以下术语定义于此,便于查阅:
- 根元素
- 元素在文档树的根部。
在 DOM 生成的文档树中,
即document element;
在 HTML 中是
html元素。[DOM] [HTML] - 主盒
-
当元素生成一个或多个盒时,
其中有一个是主盒,
它包含其后代盒和生成内容,
并且也是参与任何定位方案的盒。
有些元素除了主盒还会生成其他盒 (如list-item元素, 会额外生成 marker 盒, 或table元素, 会生成主表包装盒和一个额外的表格网格盒)。 这些附加盒的位置是相对主盒放置的。
- 行级
- 参与行内布局的内容。 具体为行级盒和文本序列。
- 块级
- 参与块布局的内容。 具体为块级盒。
- 行盒
- 非替换的行级盒,其内部显示类型为flow。 行盒的内容与自身一起参与相同的行内格式化上下文。
- inline
- 可作为行盒或行级盒的简写(在不歧义时), 或作为形容词表示行级。 后者用法已不推荐。
- 原子行内
- 替换类的行级盒(如图片), 或建立新格式化上下文的盒(如inline-block或inline-table), 且不可跨行断开(而行盒和ruby 容器可以)。
- 块容器
-
块容器要么只包含参与行内格式化上下文的行级盒,
要么只包含参与块格式化上下文的块级盒
(可能生成匿名块盒以满足该约束,
详见CSS2§9.2.1.1)。
只包含行级内容的块容器会建立新的行内格式化上下文。 元素还会生成一个根行盒包裹所有行内容。注意,这个根行盒的概念 实际上取代了CSS2§9.2.2.1中的“匿名行内元素”概念。
当其父格式化上下文不是块格式化上下文时, 块容器会建立新的块格式化上下文; 否则,在自身参与块格式化上下文的情况下, 它要么为自身内容建立新块格式化上下文, 要么沿用现有的, 具体由其他属性(如overflow或align-content)的约束决定。
注意: 块容器盒可以同时建立块格式化上下文和行内格式化上下文。
- 块盒
-
既是块级盒也是块容器的盒。
注意: 并非所有块容器都是块级盒: 非替换的inline-block和非替换表格单元格 就是块容器,但不是块级盒。 同样,并非所有块级盒都是块容器: 块级替换元素(display: block) 和 flex 容器(display: flex), 不是块容器。
- block
- 在不歧义时,作为块盒、块级盒或块容器盒的简写。
- 替换元素
-
内容不受 CSS 排版模型控制的元素,比如图片或嵌入文档。 例如,HTML
img元素的内容 通常会被其src属性指定的图片替换。替换元素通常有自然尺寸。 例如,位图图片有用绝对单位指定的自然宽高(可据此得出自然比例)。 但其他对象可能没有任何自然尺寸 (如空白 HTML 文档)。 详见[css-images-3]。
如果认为自然尺寸可能泄露敏感信息,用户代理可以认为替换元素没有自然尺寸。 例如,如果 HTML 文档的自然尺寸会随用户的银行余额变化, UA 可能会将其视为没有自然尺寸。
替换元素的内容不参与 CSS 排版模型; 但其自然尺寸会用于各种布局计算。 替换元素总是建立独立格式化上下文。
非替换元素是指不是替换的元素, 即其渲染由 CSS 模型决定。
- 包含块
-
用于确定与其相关盒的尺寸和定位的矩形。
注意,包含块不是盒(而是矩形),
但通常来源于某个盒的尺寸。
每个盒相对于其包含块有一个位置,
但不会受包含块约束;
可以溢出。
“盒的包含块”指
“盒所处的包含块”,
而不是它生成的那个。
一般来说,盒边会作为后代盒的包含块; 这称为某盒“建立”了其后代的包含块。 若引用包含块的属性, 就引用生成该包含块的盒上的值。 (对于初始包含块, 除非另有说明,值取自根元素。)
详见[CSS2] 9.1.2节、10.1节和CSS Positioned Layout 3 § 2.1 定位盒的包含块。
- 包含块链
- 一组通过包含块关系连接而成的祖先-后代链的连续包含块序列。 例如,行盒的包含块是其最近的块容器祖先的内容盒; 如果该块容器是流内块, 则它的包含块由其父块容器形成; 如果该祖父块容器是绝对定位的, 则它的包含块是最近定位祖先的内边距边(不一定是其父), 依此类推直至初始包含块。
- 初始包含块
- 根元素的包含块。 初始包含块会建立块格式化上下文。 有关其位置和尺寸,参见CSS2.1§10.1的连续媒体; 以及[CSS-PAGE-3]的分页媒体。
- 格式化上下文
-
格式化上下文指一组相关盒被排版的环境。
不同的格式化上下文有各自的排版规则。
例如,flex 格式化上下文遵循flex 布局规则[CSS-FLEXBOX-1],
而块格式化上下文则用块与行规则[CSS2]。
有些类型的格式化上下文是交错/共存的:
例如行内格式化上下文存在于
并与建立它的元素的块格式化上下文互动,
ruby 容器会在其ruby 基础容器参与的行内格式化上下文上叠加ruby 格式化上下文。
盒要么建立新的独立格式化上下文,要么延续其包含块的格式化上下文。 某些情况下, 还会建立新的(非独立的)共存格式化上下文。 但除非另有说明, 建立新格式化上下文时即创建独立格式化上下文。 盒建立何种格式化上下文由其内部显示类型决定。 例如,grid 容器建立grid 格式化上下文, ruby 容器建立ruby 格式化上下文, 块容器可建立块格式化上下文和/或行内格式化上下文。 详见display属性。
- 独立格式化上下文
-
当盒建立独立格式化上下文时(不论其类型与父上下文是否一致),
实际上建立了一个新的独立排版环境:
除非通过盒自身尺寸,
其后代的布局一般不受外部格式化上下文规则和内容影响,反之亦然。
例如,在块格式化上下文中, 浮动盒会影响周围盒的布局。 但其影响不会超出其格式化上下文: 建立该格式化上下文的盒会扩展以完全包含它们, 外部的浮动不会侵入盒内影响其内容。
另一个例子,外边距不会跨格式化上下文边界折叠。
排除区可以跨独立格式化上下文边界影响内容。 (截至撰写时,这是唯一可以跨布局特性的情况。)[CSS3-EXCLUSIONS]
某些属性可强制盒 建立独立格式化上下文,即使通常不会。 例如, 将盒设为脱离流会导致其块级化,同时建立独立格式化上下文。 还有, contain属性的某些值 也可导致盒建立独立格式化上下文。 将块变为滚动容器也会让其建立独立格式化上下文; 但将子网格设为滚动容器不会——其内容仍参与父grid 容器的布局。
块盒建立独立格式化上下文后,会为其内容建立新的块格式化上下文。 其他大多数情况下, 强制盒建立独立格式化上下文无实际效果——要么盒已建立独立格式化上下文(如flex 容器), 要么无法在该类型盒上建立独立新格式化上下文(如非替换行盒)。
- 块格式化上下文
- 行内格式化上下文
- 块和行内格式化上下文定义见CSS 2.1 第9.4节。行内格式化上下文存在于 (属于其包含的)块格式化上下文; 例如,属于行内格式化上下文的行盒会与属于块格式化上下文的浮动发生交互。
- 块布局
- 块级盒的布局, 在块格式化上下文内执行。
- 块格式化上下文根
- 建立新块格式化上下文的块容器。
- BFC
- 块格式化上下文或块格式化上下文根的缩写。 有多种非正式定义,通常指包含内部浮动、排除外部浮动、抑制外边距折叠的盒, 因此可能特指以下之一:
- 脱离流
- 流内
-
如果盒从其预期位置和与周围内容的关系中被抽离,
并使用不同的机制在父格式化上下文的正常流之外进行布局,
就是脱离流。
这发生在盒被浮动(通过float)
或绝对定位(通过position)时。
如果不是脱离流,则为流内。
注意: 有些格式化上下文抑制浮动, 因此设置float: left 的元素不一定是脱离流。
- 文档顺序
- 盒或内容在文档中出现的顺序 (可能与渲染顺序不同)。 在确定伪元素的相对顺序时, 使用盒树顺序, 参见CSS Pseudo-Elements 4 § 4 树状伪元素。
附录 B:display: contents 对非常规元素的影响
本节目前为非规范性内容。
有些元素并非完全通过 CSS 盒模型渲染;
例如,替换元素(如
img),
许多表单控件(如
input),
以及 SVG 元素。
本附录定义了它们与 display: contents 的交互方式。
HTML 元素
-
brwbrmeterprogresscanvasembedobjectaudioiframeimgvideoframeframesetinputtextareaselect -
display: contents 计算为 display: none。
-
legend -
根据 HTML 规范,
legend设置 display: contents 时,不再是已渲染 legend, 因此不会有特殊的显示行为。 (所以它对 display: contents 的反应是常规的。) -
buttondetailsfieldset -
这些元素没有特殊行为;display: contents 仅移除它们的主盒, 其内容按常规渲染。
- 其他任何 HTML 元素
-
对 display: contents 的行为与常规一致。
SVG 元素
- 具有 CSS 盒布局的
svg元素 (包括所有父元素为 HTML 元素的svg以及文档根元素) -
display: contents 计算为 display: none。
- 其他所有同时属于 容器元素 和 可渲染元素 的 SVG 元素
- SVG 文本内容子元素
use - SVG 文本内容子元素
-
display: contents 会将元素从格式化树中移除, 并将其内容提升至原位置渲染。 这些内容包括
use的 shadow-DOM 内容。 - 其他任何 SVG 元素
-
display: contents 计算为 display: none。
例如,SVG 的文本内容和文本格式化元素
需要
text
元素上下文;
如果移除了
text,
其子文本内容和元素将不再有效。
因此,display: contents 应用于
text
会阻止整个 text 元素被渲染。
相比之下,任何在
tspan
或
textPath
内的有效内容,在父文本格式化上下文内也是有效内容,
因此这些元素适用内容提升行为。
同样,如果内容提升会将子元素从 不可渲染元素(如
pattern
或
symbol
内的形状)
转变为 可渲染元素(如直接作为
svg
的子元素的形状),
那这就是无效的渲染上下文变更。
因此,永不渲染的容器元素不能通过 display: contents “去盒化”。
当元素从格式化树中移除时, 该元素上用于控制布局和视觉格式的 SVG 属性在渲染内容时会被忽略。 但 SVG 表现属性(映射到 CSS 属性) 仍影响属性值计算与继承 [CSS-CASCADE-3]; 因此这些属性可以通过影响后代元素上的 CSS 属性值, 影响其布局和视觉表现。
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 提出的反馈。
变更记录
自 Level 3 以来的新增内容
自 CSS Display Module Level 3 以来新增的特性有:
-
reading-flow 属性 (Issue 8589)
-
display 属性的动画能力
隐私注意事项
本规范未引入新的隐私注意事项。
安全注意事项
本规范未引入新的安全注意事项。