1. 简介
高效渲染网站依赖于用户代理能够检测页面的哪些部分正在显示,哪些部分可能会影响当前显示的部分,以及哪些部分可以忽略。
有各种启发式方法可以用来判断某个给定的子树在某种程度上是否独立于页面的其他部分,但它们很脆弱,因此对页面的无害更改可能会无意中使其无法通过此类启发式测试,导致渲染进入慢速代码路径。 还有许多事情值得隔离,但很难或不可能以启发式方式检测到。
为缓解这些问题并允许从页面的其他部分强烈且可预测地隔离子树,本规范定义了一个 contain 属性。
为了进一步优化屏幕外内容,本规范还定义了一个 content-visibility 属性, 使用户代理在不需要时能够完全跳过元素的布局和绘制。
1.1. 模块交互
本文档定义了早期规范中不存在的新特性。此外,它旨在一旦稳定后替换并取代 [CSS-CONTAIN-1]。
1.2. 值定义
本规范遵循 CSS 属性定义约定,来自 [CSS2],并使用 值定义语法,来自 [CSS-VALUES-3]。 未在本规范中定义的值类型在 CSS Values & Units [CSS-VALUES-3] 中定义。 与其他 CSS 模块的结合可能会扩展这些值类型的定义。
除了在定义中列出的特定于属性的值外,本规范中定义的所有属性还接受 CSS 宽泛关键字 作为其属性值。 为了可读性,它们没有被明确重复。
2. 强包含: contain 属性
名称: | contain |
---|---|
值: | none | strict | content | [ size || layout || style || paint ] |
初始值: | none |
适用于: | 参见 下文 |
继承: | 否 |
百分比: | 不适用 |
计算值: | 关键字 none 或 size, layout, paint 中的一个或多个 |
规范顺序: | 按语法顺序 |
动画类型: | 不可动画 |
用户代理应支持在所有媒体(包括非视觉媒体)上使用此属性。
contain 属性允许作者指示一个元素及其内容在尽可能大的程度上与文档树的其余部分独立。 这使得用户代理在正确使用 contain 时能够在渲染页面时利用更强的优化,并使作者可以确信其页面不会因无害的更改而意外地进入慢速代码路径。
- none
- 此值表示该属性没有效果。 元素正常渲染,没有应用任何包含效果。
- strict
- 此值计算为 size layout paint style,因此为该元素开启所有形式的 包含。
- content
-
此值计算为 layout paint style,因此为该元素开启所有形式的 包含,除了 尺寸包含。
注意: contain: content 在广泛应用时是相对“安全”的; 其效果在实际中相对较小,并且大多数内容不会触犯其限制。 然而,由于它不适用于 尺寸包含,因此元素仍然可以响应其内容的大小,这可能导致布局失效传播到树中比预期更远的地方。 在可能的情况下,使用 contain: strict 以获得尽可能多的包含。
- size
- 该值为元素开启 尺寸包含。 这确保了 包含盒 可以布局而不需要检查其后代。
- layout
- 此值为元素开启 布局包含。 这确保了 包含盒 在布局时完全不透明; 外部的任何东西都不能影响其内部布局,反之亦然。
- style
- 此值为元素开启 样式包含。 这确保了对于可能对不仅仅是元素及其后代产生影响的属性,这些影响不会超出元素。
- paint
- 此值为元素开启 绘制包含。 这确保了 包含盒 的后代不会在其边界外显示,因此如果一个元素处于屏幕外或其他不可见的位置,其后代也将保证不可见。
此属性通常适用于所有元素(包括 CSS 伪元素 4 § 4.1 生成内容伪元素:
::before 和 ::after),
尽管某些类型的包含对某些元素没有影响, 详细信息请参见 § 3 包含类型。 此外,对于 [SVG2], contain 属性仅适用于 具有关联CSS布局盒的
svg
元素。
例如,假设一个微帖子社交网络的标记类似于以下内容:
< body >
< aside > ...</ aside >
< section >
< h2 > Messages</ h2 >
< article >
Lol, check out this dog: images.example.com/jsK3jkl
</ article >
< article >
I had a ham sandwich today. #goodtimes
</ article >
< article >
I have political opinions that you need to hear!
</ article >
…
</ section >
</ body >
站点上可能会显示很多消息,但每条消息都是独立的,不会影响站点上的其他内容。 因此,每条消息都可以用 contain: content 标记以将此信息传达给用户代理,以便它可以优化页面并跳过大量屏幕外消息的计算。 如果提前知道每条消息的大小,可以应用 contain: strict 以传达进一步的限制。
此外,当任何 包含 激活在 HTML
html
或
body
元素上时, 从
body
元素向 初始包含块、视口或 画布背景 的属性传播将被禁用。 尤其是,这会影响:
-
writing-mode、direction 和 text-orientation(参见 CSS Writing Modes 3 § 8 主要书写模式)
-
overflow 及其分支(参见 CSS Overflow 3 § 3.5 溢出视口传播)
-
background 及其分支(参见 CSS Backgrounds 3 § 2.11.2 画布背景与HTML <body> 元素)
注意: 设置在
html
元素本身上的属性不会影响其向 初始包含块、视口或 画布背景 的传播。
注意: 除了 contain 之外, 还有几种属性可以为元素开启各种 包含。 这些属性不会影响 contain 的值; 例如,一个元素可以具有 contain: none,但仍然可以通过 content-visibility 为其开启 布局包含。
3. 容器类型
一个元素可能受到几种不同类型的容器的限制,从而以不同方式限制其后代对页面其余部分的影响。容器使用户代理能够进行更强大的优化,并帮助作者将页面组合成功能单元,因为它限制了特定更改对文档的影响范围。
规范作者在引入新属性或机制时需要考虑各种容器类型是否以及如何影响他们所引入的内容,并在规范中包括此处未描述的任何影响。
3.1. 尺寸容器
为一个元素赋予尺寸容器会使其主框成为一个尺寸容器框,并具有以下效果:
-
内在尺寸由尺寸容器框决定,按照按空布局的逻辑处理,好像元素没有任何内容。
注意:这会影响对最小内容或最大内容关键字的显式调用,以及任何依赖于这些测量的计算,例如将大小包含的项目放入网格轨道中,或者在合适内容尺寸的父容器中。
-
布局尺寸容器框及其内容分两个阶段进行:
img
{ width : 100 px ; aspect-ratio : 1 /1 ; contain : size; }
< img src = "https://www.example.com/300x100.jpg" >
然而,当满足以下任意条件时,为一个元素赋予尺寸容器将无效:
注意:内部表格框,不包括表格标题栏,被排除在外,因为表格布局算法不允许框比其流入内容更小。将表格单元格按空布局并在内部布局其内容而不改变尺寸,实际上是未定义的操作。手动将宽度或高度属性设置为0不能使其比内容更小。这一问题不适用于表格标题栏,它们完全可以具有独立于其内容的固定大小。
3.1.1. 可能的尺寸容器优化
本节为非规范性内容。
尺寸容器本身并没有提供太多的优化机会。它自身的主要优势在于,想要基于容器框的大小来布局内容的工具(例如实现“容器查询”概念的JS库),可以这样做而不必担心“无限循环”,即子元素的尺寸响应于容器框的大小,导致容器框的大小也发生变化,从而可能触发对子元素尺寸的进一步更改,可能会再次引发对容器框大小的更改,如此无限循环。
但是,当与布局容器结合使用时,可能启用的优化包括(但不限于):
-
当容器框的后代的样式或内容发生变化时,计算DOM树的哪些部分被“弄脏”并可能需要重新布局,可以在容器框处停止。
3.2. 布局容器
为一个元素赋予布局容器会使其主框成为一个布局容器框,并具有以下效果:
-
如果一个分段容器的分段上下文中至少有一个具有布局容器,或者该分段上下文的至少一个分段容器是一个布局容器框的后代,并且同一分段上下文的至少一个后续分段容器不是具有布局容器的同一元素的后代,那么第一个是布局容器框的元素或是分段容器的祖先元素必须“截留”剩余的分段流:分段不得继续超出布局容器边界,且第一个布局容器边界内的最后一个分段容器被视为其分段上下文中的最后一个分段容器。
如果只有在分段流中还有更多内容时才生成分段上下文中的后续分段容器,那么它们不会生成。如果它们无论如何都存在,它们仍然是分段上下文的一部分,但不会接收任何来自分段流的内容。
注意: 在撰写本文时,没有稳定的规范受此条影响。只有那些使分段上下文的一些(但不是全部)分段容器成为布局容器(或布局容器元素的后代)的规范才会受到影响。这种情况不适用于[CSS-PAGE-3]或[CSS-MULTICOL-1]。尽管如此,仍然包含了这一要求,因为已经考虑了几种可能导致这种情况的机制(例如:[CSS-REGIONS-1],::nth-fragment(),多列的假设选择器……),如果这些机制不遵守这一规则,布局容器旨在提供的保证将无法实现。[CSS-REGIONS-1]详细说明了布局容器如何影响区域。
< article > Lorem ipsum…</ article > < div id = a ></ div > < aside > < div id = b ></ div > < div id = c ></ div > </ aside > < aside > < div id = d ></ div > < div id = e ></ div > </ aside > < div id = f ></ div > article
{ flow-into : foo;} #a, #b, #c, #d, #e, #f{ flow-from : foo;} aside{ contain : layout} 在此[CSS-REGIONS-1]示例中,内容可以从
#a
流向#b
,从#b
流向#c
。然而,由于#c
是第一个布局容器框中的最后一个片段容器,它截留了所有剩余的内容,并且没有任何内容流入#d
、#e
或#f
。 -
强制换行允许在布局容器框中发生,但不会像CSS Fragmentation 3 § 3.1 框之间的换行:break-before和break-after属性中描述的那样传播到父级。
注意:这引入了先前不存在的可能性,即强制换行可能发生在框和其容器之间(参见CSS Fragmentation 3 § 4.1 可能的断点)。
然而,当满足以下任意条件时,为一个元素赋予布局容器将无效:
3.2.1. 可能的布局容器优化
本节为非规范性内容。
布局容器可能启用的优化包括(但不限于):
-
在布局页面时,单独的容器框的内容可以并行布局,因为它们保证不会相互影响。
-
在布局页面时,如果容器框不在屏幕上或被遮挡,并且屏幕上可见部分的布局不依赖于容器框的大小(例如,如果容器框接近块级容器的末尾,而你正在查看块级容器的开头),则容器框内容的布局可以延迟或以较低优先级完成。
(当与尺寸容器配合使用时,此优化可以更广泛地应用。)
3.3. 样式容器
为一个元素赋予样式容器会产生以下效果:
-
counter-increment和counter-set属性必须限定在元素的子树内,并创建一个新的计数器。
-
content属性的open-quote、close-quote、no-open-quote和no-close-quote的效果必须限定在元素的子树内。
注意: 这意味着子树中的引用嵌套深度保持不变,并从其上下文通常暗示的值开始,但这些值在子树内对引用嵌套深度的更改不会影响子树外的引用嵌套深度。
注意: [CSS-REGIONS-1]对样式容器如何影响区域有规范性要求。
-
如果限定在元素上,它必须在评估属性效果时,表现得好像限定元素是文档的根:限定元素外的属性使用对限定元素上或限定元素内的属性使用没有影响,反之亦然。
注意: “限定在元素上”目前未使用。它被定义为供未来规范使用的扩展点。
-
如果限定在子树内,它的效果相同,只不过限定元素本身被视为树外,与文档的其他部分一样,属性对该元素的效果不受限定影响。在考虑限定属性对子树内元素的影响时,子树底部的元素被视为文档的根。
1 1.2:
< div ></ div >
div {
contain : style;
counter-increment : n;
}
div::before, div::after {
content : counters ( n, '.' ) " " ;
}
div::after {
counter-increment : n 2 ;
}
3.3.1. 可能的样式容器优化
本节为非规范性内容。
样式容器可能启用的优化包括(但不限于):
-
当一个具有样式容器的元素的后代元素上的属性发生变化时,计算DOM树的哪些部分被“弄脏”并可能需要重新计算样式,可以在具有样式容器的元素处停止。
3.4. 绘制容器
为一个元素赋予绘制容器会使其主框成为一个绘制容器框,并具有以下效果:
-
元素的内容(包括任何墨水溢出或可滚动溢出)必须剪裁到溢出剪裁边缘的绘制容器框内,考虑[[css-backgrounds-3#corner clipping|角剪裁]]。这不包括创建任何机制来访问或指示被剪裁内容的存在;也不妨碍通过其他属性创建任何此类机制,例如溢出、调整大小或文本溢出。
注意: 此剪裁形状尊重overflow-clip-margin,允许具有绘制容器的元素仍然稍微超出其正常边界。
注意: 本段描述的行为相当于在使用值时将overflow-x: visible更改为overflow-x: clip,并将overflow-y: visible更改为overflow-y: clip,而其他overflow-x和overflow-y的值保持不变。
然而,当满足以下任意条件时,为一个元素赋予绘制容器将无效:
3.4.1. 可能的绘制容器优化
本节为非规范性内容。
绘制容器可能启用的优化包括(但不限于):
-
如果容器框不在屏幕上或被遮挡,UA通常可以跳过尝试绘制其内容,因为它们也保证处于屏幕外/被遮挡状态。
注意: 某 些绘制效果(如blur()滤镜)具有非局部效果。用户代理需要跟踪这些效果,因为当其后代发生变化时,即使它们具有绘制容器且本可以跳过,也可能需要重新绘制带有此类滤镜的元素的部分内容。
-
除非通过其他机制(如溢出、调整大小或文本溢出属性)使剪裁内容可访问,UA可以为该框保留与框大小完全一致的“画布”空间。(在类似的可滚动情况下,如overflow: hidden,可以滚动到当前被剪裁的内容,所以UA通常会预见性地多绘制一些,以便在滚动发生时立即显示内容,而不是在稍后的一帧中显示。)
-
因为它们保证是堆叠上下文,滚动元素可以绘制到单个GPU图层中。
4. 完全抑制元素的内容:content-visibility属性
名称: | content-visibility |
---|---|
值: | visible | auto | hidden |
初始值: | visible |
适用于: | 可以应用布局容器的元素 |
继承: | 否 |
百分比: | 不适用 |
计算值: | 按指定值 |
规范顺序: | 按语法 |
动画类型: | 不可动画 |
content-visibility属性控制元素是否完全渲染其内容,同时强制实施一系列容器,允许用户代理在需要之前省略大量布局和渲染工作。该属性具有以下值:
- visible
-
无效。元素的内容按常规布局和渲染。
- hidden
-
元素跳过其内容。
跳过的内容必须对用户代理功能(例如页面查找、Tab顺序导航等)不可访问,也不可选中或聚焦。
注意: 这类似于将内容设置为display: none。
- auto
-
与跳过的内容必须仍然可以被用户代理功能正常访问,例如页面查找、Tab顺序导航等,并且必须能够正常聚焦和选择。
不同,
用户代理应尽可能避免对跳过的内容进行布局/渲染工作;重度容器和使内容不可见且不可触摸的组合允许进行重度优化。如果某个时刻进行了渲染工作,用户代理应保留先前计算的布局状态,以便稍后可以快速显示跳过的内容。
-
布局容器确保用户代理能够在跳过的子树中省略布局工作,因为这种布局的结果不会影响容器元素外的元素。
-
样式容器确保在跳过的子树中不需要处理计数器,因为它们不会影响容器元素外的计数器。
-
绘制容器确保绘制内容的墨水溢出被剪裁;这反过来意味着用户代理可以可靠地确定元素的可见部分何时接近视口(并且,对于content-visibility: auto,开始绘制它)。
-
尺寸容器确保用户代理能够在跳过的子树中省略布局,因为这种布局的结果不会影响容器元素的大小。
请注意,在content-visibility: auto的情况下,即使元素未被跳过,布局容器、样式容器和绘制容器仍然存在。这是为了防止由于元素进入和退出跳过状态而导致的容器更改所引起的布局变化。
4.1. 使用content-visibility: hidden
本节为非规范性内容。
content-visibility: hidden对元素施加了强大的限制,因此应谨慎使用。它还启用了一些非常有用的场景,通常改进了现有技术,以下是其中一些。
-
如果页面需要对不会被渲染的元素或文本进行一些测量,通常会将要测量的内容定位到屏幕外,使用类似于position: absolute; left: -100000px;,然后调用类似
getBoundingClientRect()
的API。不幸的是,即使页面从未打算显示这些内容,用户代理仍然必须为这些内容执行完整的样式、布局和渲染工作,以防它影响屏幕上的显示。作者也不能保证内容不会意外出现在屏幕上;即使是非常负的left值(如上所述)可能也不足以确保这一点,具体取决于内容。
将这些内容包装在一个content-visibility: hidden容器中解决了所有这些问题。如果包装器没有边框、背景等,那么它和它的跳过的内容保证永远不会渲染到屏幕上,无论它们有多大。因为内容被跳过,用户代理也可以避免对其进行样式处理或布局,直到脚本最终需要时。
-
一个“单页应用程序”通常由几个独立的窗格或“视图”组成,其中只有一个同时显示。
如果作者想要避免为非活动视图支付样式/布局/渲染等成本,他们可以将其完全从文档中移除,或者至少对其应用display:none。不幸的是,这意味着当视图确实需要显示时,所有样式/布局/渲染等工作都需要一次性完成,可能会导致视图实际显示之前的明显延迟。
或者,可以将视图定位到屏幕外。这意味着当需要使用时,它将立即准备好,但它会一直消耗样式/布局/渲染的成本,这可能是显著的,特别是如果有许多非活动视图。非活动视图也可能仍然会出现在辅助工具中,混淆使用屏幕阅读器的用户、使用Ctrl-F进行页面查找的人等。
content-visibility: hidden改进了这两种选项。因为内容被跳过,当它们不活动时,用户代理不会花费时间在它们上。它们也不会对屏幕阅读器、页面查找和其他工具可见。并且因为用户代理应尽可能保留以前的样式/布局工作,如果视图以前已经显示过,重新渲染它可能会非常快。
-
如果作者想让一个元素“不可见”,但仍然在页面中显示以用于布局目的,一个选项是visibility: hidden。然而,visibility: hidden元素的后代可以设置visibility: visible并重新显示,这并不总是直观或预期的。
content-visibility: hidden执行非常类似的功能,但后代无法“关闭”它并开始显示;它们保持“隐藏”,直到祖先关闭它。
因为content-visibility: hidden还将许多容器值应用于容器,它并不总是像visibility: hidden那样可用,但当其限制可以接受时,它可以是一种更可靠、更一致的方式来隐藏元素的内容。
4.2. 使用content-visibility: auto
本节为非规范性内容。
content-visibility: auto比 更复杂;它不是类似于display: none,而是随着元素的内容变得与用户相关时,自适应地隐藏/显示元素的内容。它也不会将其跳过的内容从用户代理中隐藏,因此屏幕阅读器、页面查找和其他工具仍然可以与其交互。
最好将其视为对容器的升级:如果作者有大量内容需要显示,并且这些内容通常会在屏幕外(例如一个可滚动的长列表),并且该内容可以接受重度容器,他们应该考虑使用content-visibility: auto一次性应用所有的容器。这也强烈暗示用户代理可以跳过内容的工作(可能会导致内容进入屏幕时出现小延迟),因为文档中有大量内容,其中大部分内容无论如何都不会被看到。
注意:因此,content-visibility: auto可以替代复杂的“虚拟列表”技术,至少在许多情况下可以如此。
由于content-visibility: auto只有在元素的内容对用户不相关时才会导致元素跳过其内容,因此最好在合理细粒度下使用。
相反,content-visibility应该应用于单个推文,允许它们在离开屏幕时被跳过。
由于content-visibility: auto在元素跳过其内容时会施加尺寸容器,如果元素依赖于其内容来确定其大小,页面布局(或至少,滚动条位置)可能会在元素离开屏幕并开始跳过时“跳动”。
-
将元素设置为固定大小
-
仔细安排布局(例如Grid)以在不依赖内容的情况下确定元素大小
-
使用contain-intrinsic-size来设置元素大小的估计值
-
使用contain-intrinsic-size: auto自动从上次渲染时对元素的确切大小进行“快照”,在它被跳过之前(并提供在其渲染之前要使用的大小估计,以便可以对其大小进行快照)
例如,在Twitter上,平均推文约为200px高,因此contain-intrinsic-size: auto 500px 200px将确保滚动条滑块大致处于正确的大小和位置,即使前面的或后面的推文被跳过,同时仍然允许推文在屏幕上时根据其内容进行调整。只要推文至少被查看过一次(并且在它们跳过时没有改变大小),它们的大小将准确无误地在跳过时被保留,因此滚动条滑块也将如此;只有新加载的推文(例如当你向下滚动时在时间线顶部加载的推文)将不得不依赖200px的高度估计。
4.3. 检测content-visibility: auto状态变化:contentvisibilityautostatechanged事件
当渲染状态发生变化并且元素开始或停止与用户相关时,具有content-visibility:
auto样式的元素上会触发contentvisibilityautostatechanged
事件。
此事件通过在状态变化发生时发布任务来调度。
[Exposed =Window ]interface :
ContentVisibilityAutoStateChangedEvent Event {(
constructor DOMString ,
type optional ContentVisibilityAutoStateChangedEventInit = {});
eventInitDict readonly attribute boolean skipped ; };dictionary :
ContentVisibilityAutoStateChangedEventInit EventInit {boolean skipped =false ; };
ContentVisibilityAutoStateChangedEvent属性描述:
请注意,即使在content-visibility: auto子树中的元素跳过其内容,它们仍然在语义上与元素相关。这意味着使用此信号无限期地跳过被跳过子树中的DOM更新是不合适的。相反,它应该用于降低更新的优先级,但确保内容在语义上保持相关并且合理地保持最新。这对于即使在祖先设置为跳过其内容时仍然使用这些内容的辅助技术尤为重要。
4.4. 限制和澄清
-
从
IntersectionObserver
的角度来看,元素的跳过的内容从不与交叉根相交。即使根和目标元素都在跳过的内容中,这一点也成立。 -
从
ResizeObserver
的角度来看,元素的跳过的内容的大小从不变化。如果这些元素后来变为非跳过状态,则会在新大小与最后一次通知的大小不同的情况下,传递大小调整观察结果。 -
如果元素开始或停止跳过其内容,此更改发生在渲染更改效果的帧的requestAnimationFrame回调运行之后。具体来说,这些更改将在处理模型的更新渲染步骤的步骤13和14之间生效(在“运行动画帧回调”和“运行更新交叉观察步骤”之间)。
可以使用IntersectionObserver的内部版本来确定元素的视口交集。但是,由于这些观察结果是在更新渲染的第14步调度的,因此对跳过(从而绘制)状态的更改直到下一帧的处理才会对用户可见。因此,更新跳过状态(包括包含调整)也推迟到该帧。这确保了脚本访问,例如,在这两个事件之间(内部交叉观察和跳过状态更新)元素的包含值时,将检索与当前绘制状态一致的值,并且不会导致任何强制布局。 -
对于content-visibility: auto的初始可见性判断必须在确定新content-visibility: auto元素存在的同一帧中进行。
当元素首次获得content-visibility: auto时,它可能会或可能不会被定位在屏幕上。此状态的确定以及是否跳过该元素的判断必须在同一帧中完成。如果未完成,则可能会在元素位置产生空白内容,因为可见性检查和跳过状态更新将推迟到下一帧。 -
就滚动操作而言,例如
scrollIntoView()
,具有content-visibility: auto且跳过其内容的元素的大小和位置是在尺寸包含仍然活跃的情况下确定的。注意:一旦滚动到视图中,元素将不再跳过其内容,因此可能不会再具有尺寸包含;如果这改变了元素的大小,它可能不会像请求的那样准确对齐在视口中。
如果一个元素对用户代理功能不可用(例如,由于跳过了一个content-visibility: hidden祖先),则滚动操作不应滚动到该元素,仿佛它没有布局框一样。
-
如果具有content-visibility: auto且跳过其内容的元素被聚焦(或其内容被聚焦),它将在由于聚焦而滚动到视图之前变为与用户相关(因此停止跳过其内容)。
注意:因此,与上一点不同,元素将被正确地调整大小并在视口中对齐。这与
focus()
方法的步骤顺序是一致的。 -
如果一个
iframe
跳过其内容或是元素的跳过内容的一部分,用户代理应该在可能的情况下完全跳过iframe事件循环中的更新渲染步骤。 -
当元素处于跳过状态时,CSS过渡和动画不会更新:
-
即使新应用的样式会启动动画,也不会创建新的动画。
-
现有的动画不会在时间线上前进。
-
元素上的运行动画不会结束。
如果脚本查询跳过元素的样式(引发样式更改事件),以致需要知道动画或过渡的状态才能返回正确信息,则动画和过渡将根据样式更改事件时的样式进行采样:
CSS Animations 2 § 4 动画事件和CSS Transitions 2 § 5 过渡事件定义了对象何时创建,何时触发事件,以及触发的事件数据。
当元素停止跳过状态时,动画和过渡将被采样,然后从该点起正常推进时间线。
注意:总体而言,这类似于当背景标签被带回前台时过渡/动画的行为,使用户代理能够尽可能跳过不必要的动画工作,而不会过度干扰动画在重新变得相关时的表现。
-
-
当元素处于跳过状态时,它不应启动任何过渡,即使样式更改事件影响了其计算样式。
当元素停止跳过状态时,不应由于与其不再处于跳过状态相关联的样式更改事件而启动任何过渡。
注意:这类似于元素从display:none切换到非none值——即使在这种情况下样式技术上在更改(从初始值到层叠的“适当”值),也不会启动任何过渡。
-
如果元素有一个content-visibility: hidden的祖先,并且它被放置在顶层中,则它不会生成任何框,就像它具有display: none一样。
注意:由于其他原因而跳过的元素,例如具有content-visibility: auto祖先,仍将正常生成框,并可能因此变为非跳过状态。
4.5. 无障碍影响
如果用户代理暴露某种形式的“无障碍树”,类似于DOM树但专门用于无障碍用例,例如屏幕阅读器(从而提供与无障碍API相关的元素位置等),那么跳过的内容在content-visibility: hidden元素中也必须类似地在无障碍树中“跳过”(省略)(类似于display: none元素在文档的所有视图中被省略)。
跳过的内容在content-visibility: auto元素中不得暴露用户通过无障碍树与页面交互的事实,而不是通过视觉呈现在屏幕上。特别是,如果用户代理使用content-visibility: auto避免对屏幕上未显示的内容进行布局和绘制工作,那么它也必须避免对无障碍树中未显示的内容进行此类工作。如果这不可能(例如,如果用户代理在无障碍树中表示一个可聚焦元素需要知道其确切位置,因此需要对其及周围内容进行完整布局),那么用户代理必须完全省略无障碍树中的跳过的内容。
注意:此要求旨在保护使用无障碍工具的用户免于通过时间通道的观察被识别和分析;如果用户代理在视觉呈现时可以跳过大量工作,但在呈现给无障碍树时必须完成所有工作,那么作者可以通过观察布局操作的时间来判断用户如何与页面交互。
4.6. 示例
< style > . sv { content-visibility : auto ; min-height : 50 px ; } </ style > < div class = sv > ... some content goes here ...</ div >
.sv 元素的 content-visibility: auto 值允许用户代理管理元素是否被跳过。特别是当此元素接近视口时,用户代理将开始绘制元素。当元素移离视口时,它将停止绘制。此外,当元素被跳过时,用户代理应尽可能跳过渲染工作。
< style > . sv { content-visibility : hidden ; } </ style > < div class = sv > ... some content goes here ...</ div >
在此示例中,无论视口交集如何,元素都被跳过。这意味着唯一能让内容绘制出来的方法是通过脚本更新值以删除content-visibility或更改其值。同样,用户代理应尽可能跳过内容中的渲染工作。
跳过渲染的附加效果是用户代理可以保留内容的布局状态,因此将来删除content-visibility属性时,内容的渲染速度会比使用display: none或类似方式隐藏时更快。
< style > body { margin : 0 ; } . sv { content-visibility : hidden ; position : relative ; left : 10 px ; top : 20 px ; } # child { position : relative ; left : 1 px ; top : 2 px ; width : 100 px ; height : 200 px ; } </ style > < div id = target class = sv > < div id = child ></ div > ... some other content goes here ...</ div > < script > ... // This will force rendering work, including layout, // if the UA previously avoided it. target. firstElementChild. getBoundingClientRect(); ... </ script >
与上一个示例类似,元素被跳过。用户代理应尽可能避免渲染工作。然而,在此示例中,在某个时刻脚本访问了元素内容中的布局值。在这种情况下,用户代理无法避免渲染工作,并且必须处理任何先前跳过的渲染工作,以便向调用者返回正确的值。在此示例中,getBoundingClientRect()
的结果是一个位置为
(11, 22) 且大小为 100x200 的矩形。
请注意,对同一布局值的重复调用不应导致任何额外的渲染工作,因为用户代理应保留最后更新的渲染状态。
还请注意,需要渲染工作的这种情况并不是唯一的。在某些其他情况下,用户代理可能也无法避免渲染工作。
5. 隐私考虑
本规范中的功能没有已知的隐私影响。
6. 安全考虑
本规范中的功能没有已知的安全影响。
像其他任何 CSS 规范一样,它影响文档的渲染,但不会引入任何特殊能力,以之前未通过其他 CSS 模块提供的方式,或者通过格式化文档行为本身误导性地呈现内容。
附录 A. 变更
本附录是说明性的。
自2020-12-16 工作草案以来的变更
-
定义动画和过渡如何作用于被跳过的元素。
-
移除“风险”标记中的样式包含部分。
-
在启用包含时,禁用从 HTML body 元素的传播。
-
澄清 scrollIntoView() 不会滚动到content-visibility:hidden元素的子元素。
-
定义具有content-visibility:hidden祖先的元素不会在顶层生成框。
-
定义在顶层使得元素与用户相关。
-
指出具有非本地效果的绘画效果可能会限制某些优化机会。
-
添加 ContentVisibilityAutoStateChanged 事件。
自2020-06-03 工作草案以来的变更
-
更改了 `contain` 属性的计算值的确定方式。
-
修复了关于 contain: content 的注释中的语法错误。
-
更改术语:将“包含框”替换为“包含盒”(与对第一级的同样改进保持同步)。
-
对大小和绘制包含进行了编辑改进和澄清(与对第一级的同样改进保持同步)。
-
明确指出大小包含会抑制自然纵横比(与对第一级的同样改进保持同步)。
-
将 `content-visibility` 的动画类型从离散更改为不可动画化。
-
在§ 4.4 限制与澄清中,增加了对 `content-visibility: auto` 初始可见性确定时序的约束。
自2019-11-11 工作草案以来的变更
-
添加了content-visibility属性。
自CSS 包含级别 1以来的变更
-
恢复了在第一级中被删除的样式包含。