1. 引言
这是一个相较于 CSS Containment Level 2 的差异规范。 它目前是一个探索性工作草案: 如果您正在实施任何内容,请使用第 2 级作为参考。 一旦达到 CR,我们将把第 2 级文本合并到此草案中。
1.1. 模块交互
本文件定义了在早期规范中不存在的新特性。 此外,它旨在替代并取代 [CSS-CONTAIN-1],一旦稳定。
1.2. 值定义
本规范遵循 CSS 属性 定义规范,参考 [CSS2],使用 值定义语法,参考 [CSS-VALUES-3]。 本规范未定义的值类型在 CSS 值与单位 [CSS-VALUES-3] 中定义。 与其他 CSS 模块的组合可能会扩展这些值类型的定义。
除了在其定义中列出的特定属性值外, 本规范定义的所有属性 也接受 CSS-wide 关键字 作为其属性值。 为了可读性,它们未被明确重复。
2. 强包含性:contain 属性
CSS Containment 2 § 2 强包含性:contain 属性
名称: | contain |
---|---|
新值: | layout || style || paint || [ size | inline-size ] |
- inline-size
-
此值为元素启用 inline-size 包含。
这防止了其 inline-size 的 主框
直接依赖于其内容。
注意: 仍然可能存在间接依赖, 见 § 3.1 Inline-Size Containment。
3. 包含类型
3.1. 行内大小包含
给元素应用 行内大小包含 将 大小 包含 应用于其 行内轴 的 主要框 的尺寸。 这意味着 行内轴 固有 尺寸 被确定为好像该元素没有内容。 然而,内容仍然会如常影响框的 块轴 固有尺寸, 并且框可以在 块轴 中正常 分割。
例如,如果引入了滚动条, 它们不会被移除, 即使随后的 块大小 小到不需要它们; 或者如果一个框的逻辑高度与一个位置较低的浮动相冲突,并且被清除到 也有更多可用的行内空间,因此变得短到不会冲突, 它不会被移回到其先前有问题的大小和位置。
因此,尽管 行内大小包含 防止 框的内容直接影响其 行内 大小 通过其 行内轴 固有 尺寸, 其 行内大小 仍然可能通过其内容的影响 间接依赖于其 块 大小。
一般来说, 元素的行内大小与块大小之间的关系 是不可预测和非单调的, 块大小可以在行内大小变化时任意上下移动。 无限循环被防止 通过确保布局不会回退到先前(已知有问题)状态, 即使对约束的天真分析允许这种情况; 换句话说,布局始终“向前移动”。 我们相信当前的 CSS 布局规范已纳入此类规则, 但如果有任何遗漏, 请 通知 CSSWG 以便这些错误可以被 更正。
< section style = "width: 200px; border: solid; display: flow-root;" > < div style = "float: left; width: 50px; height: 80px; background: blue;" ></ div > < div style = "float: right; width: 50px; height: 80px; background: blue;" ></ div > < div style = "float: left; width: 160px; height: 80px; background: navy;" ></ div > < article style = "border: solid orangered; display: flow-root; min-width: min-content" > < div style = "background: orange; aspect-ratio: 1/1;" > Article</ div > </ article > </ section >
块布局算法首先会放置浮动框,前两个框分别位于容器的左下角和右下角,第三个框由于过宽而被推到它们下面。
接下来,article
将被布局。由于它是 display:
flow-root,它不能与任何浮动框交叉,因此在确定自身的大小和位置时,必须考虑它们。
布局引擎首先尝试将 article
与容器顶部对齐,结果为 100px 宽,足以容纳其 最小内容大小。然而,由于其子元素的 宽高比,这将导致 article
高度也为 100px,与下面的第三个浮动框交叉,因此这个布局机会被丢弃。
然后,它尝试将 article
与第三个浮动框顶部对齐,在它右侧窄 40px 宽的空间内。然而,由于
article
的 最小宽度
使它太大,无法适应旁边的 40px 宽空间,因此它也被推到下面,形成一个 200px
的正方形,位于所有浮动框的下面。
如果从 article
中移除 最小宽度,或者在 article
或 header
上添加 行内大小包含(使得 最小宽度: 最小内容 解析为零),那么 article
将适应为 40px
的正方形,位于最后一个浮动 div
旁边(可能会有部分内容溢出)。
此时,article
的宽度和高度(各为 40px)将可以重新适应回第一个考虑的位置,与容器顶部对齐。然而,该框不会返回到先前的位置,因为布局引擎已经知道,这个位置会导致无效布局。
给一个元素 行内大小包含 没有任何效果,如果以下任何条件为真:
-
如果该元素不生成 主要框(例如 display: contents 或 display: none)
4. 容器查询
虽然 媒体查询 提供了一种查询文档显示的用户代理或设备环境 的方法(如视口尺寸或用户偏好),容器查询 允许测试文档内元素的某些方面 (如盒子尺寸或计算样式)。
默认情况下,所有元素都是 查询容器,用于 容器样式查询, 并可以通过使用 container-type 属性 (或 container 简写)来指定额外的查询类型, 以使其成为 查询容器,用于 容器大小 查询。应用于 查询容器 的样式规则 可以通过查询条件来调整, 使用 @container 条件分组规则。
main, aside{ container : my-layout / inline-size; } .media-object{ display : grid; grid-template : 'img' auto'content' auto /100 % ; } @container my-layout( inline-size >45 em ) { .media-object{ grid-template : 'img content' auto / auto1 fr ; } }
主区域和侧边栏中的媒体对象将响应各自的容器上下文。
对于带有伪元素的选择器,可以通过 包含阴影的包容祖先 来建立查询容器, 这是 最终 来源元素 的。
-
伪元素本身不能是查询容器
-
::before、 ::after、 ::marker 和 ::backdrop 查询其 来源元素
-
::first-letter 和 ::first-line 查询其来源元素, 即使 虚构标签序列 可能将
::first-line
推过其他元素以便于 继承和渲染 -
多个伪元素不允许伪元素成为其他伪元素的查询容器。例如,主机,但不是
::part()
,可以 成为::before
在host::part()::before
中的查询容器。 同样,::before
不能成为::marker
在div::before::marker
中的查询容器 -
::slotted() 选择器可以查询阴影树中的容器, 包括插槽本身
-
::part() 选择器可以查询其来源主机,但不能查询 阴影树内部的查询容器
-
::placeholder 和 ::file-selector-button 可以查询输入 元素,但如果输入元素 是通过阴影树实现的,则不会暴露任何内部容器
< style > # container { width : 100 px ; container-type : inline - size ; } @ container ( inline-size < 150px ) { # inner :: before { content : "BEFORE" ; } } </ style > < div id = container > < span id = inner ></ span > </ div >
< div id = host style = "width:200px" > < template shadowroot = open > < style > # container { width : 100 px ; container-type : inline - size ; } @ container ( inline-size < 150px ) { :: slotted ( span ) { color : green ; } } </ style > < div id = container > < slot /> </ div > </ template > < span id = slotted > Green</ span > </ div >
4.1. 创建查询容器: container-type 属性
名称: | container-type |
---|---|
值: | normal || [ size | inline-size ] |
初始: | normal |
适用: | 所有元素 |
继承: | 否 |
百分比: | 不适用 |
计算值: | 关键字 normal 或一个或多个 size,inline-size |
规范顺序: | 根据语法 |
动画类型: | 不可动画 |
container-type 属性将元素定义为 查询容器,用于需要显式包含的 容器查询 (例如 容器大小查询),允许 样式规则 来样式化其后代,以查询其大小和布局的各个方面,并做出相应的响应。
除非另有说明,所有元素都是 查询容器,用于不需要显式包含的 容器查询 (例如 容器样式查询),无论指定的 container-type 如何。
值具有以下含义:
- size
- 建立一个 查询容器,用于 容器大小查询,适用于 行内 和 块轴。 应用 布局包含、样式包含,以及 大小包含 到 主盒子。
- inline-size
- 建立一个 查询容器,用于 容器大小查询,适用于容器的自身 行内轴。 应用 布局包含、样式包含,以及 行内大小包含 到 主盒子。
- normal
- 该元素不是任何 查询容器,对于 容器大小查询, 但仍然是 查询容器 对于 容器样式查询。
aside, main{ container-type : inline-size; } h2{ font-size : 1.2 em ; } @container ( width >40 em ) { h2{ font-size : 1.5 em ; } }
section{ container-type : style; } @container ( --cards: small) { article{ border : thin solid silver; border-radius : 0.5 em ; padding : 1 em ; } }
4.2. 命名查询容器:container-name 属性
名称: | container-name |
---|---|
值: | none | <custom-ident>+ |
初始值: | none |
适用对象: | 所有元素 |
继承: | 否 |
百分比: | 不适用 |
计算值: | 关键字 none,或有序的 标识符 列表 |
规范顺序: | 按语法 |
动画类型: | 不可动画 |
container-name 属性 指定一组 查询容器名称。 这些名称可以被 @container 规则 用来过滤目标 查询 容器。
- none
- 查询容器 没有 查询 容器名称。
- <custom-ident>
- 指定一个 查询容器名称,作为一个 标识符。 关键字 none、和、not、以及 或 被排除在此 <custom-ident> 之外。
main{ container-type : size; container-name : my-page-layout; } .my-component{ container-type : inline-size; container-name : my-component-library; } @container my-page-layout( block-size >12 em ) { .card{ margin-block : 2 em ; } } @container my-component-library( inline-size >30 em ) { .card{ margin-inline : 2 em ; } }
4.3. 创建命名容器:container 简写
名称: | container |
---|---|
值: | <'container-name'> [ / <'container-type'> ]? |
初始值: | 见各个属性 |
适用于: | 见各个属性 |
继承: | 见各个属性 |
百分比: | 见各个属性 |
计算值: | 见各个属性 |
动画类型: | 见各个属性 |
标准顺序: | 按语法 |
container 简写属性 同时设置 container-type 和 container-name 在同一声明中。 如果省略了 <'container-type'>, 它会重置为其初始值。
main{ container : my-layout / size; } .grid-item{ container : my-component / inline-size; }
4.4. 容器查询:@container 规则
该 @container 规则 是一个 条件组规则,其条件是 一个 容器查询, 这是一个布尔组合的 容器大小查询 和/或 容器样式查询。 在 <样式表> 块中的样式声明 在 @container 规则中 仅在 容器查询 对其元素的 查询容器 为真时生效。
该 @container 规则的语法是:
@container [ <container-name> ]? <container-condition> { <stylesheet> }
其中:
<container-name> = <custom-ident> <container-condition> = not <query-in-parens> | <query-in-parens> [ [ and <query-in-parens> ]* | [ or <query-in-parens> ]* ] <query-in-parens> = ( <container-condition> ) | ( <size-feature> ) | style( <style-query> ) | <general-enclosed> <style-query> = <style-condition> | <style-feature> <style-condition> = not <style-in-parens> | <style-in-parens> [ [ and <style-in-parens> ]* | [ or <style-in-parens> ]* ] <style-in-parens> = ( <style-condition> ) | ( <style-feature> ) | <general-enclosed>
关键字 none、和、not 和 或 被排除在上面的 <custom-ident> 之外。
对于每个元素, 要查询的 查询容器 是从元素的祖先 查询容器 中选择的,这些查询容器 被确认为所有 容器特性 的有效 查询容器 在 <container-condition> 中。 可选的 <container-name> 过滤考虑的 查询容器 集合,仅限于那些具有匹配的 查询容器名称。
一旦为一个元素选择了一个合格的 查询 容器, 在 <container-condition> 中的每个 容器特性 都会针对该 查询容器 进行评估。 如果没有祖先是合格的 查询容器, 那么该元素的 容器查询 将是 未知 的。
@container card( inline-size >30 em ) andstyle ( --responsive: true) { /* 样式 */ }
上述样式仅在存在名为 "card" 的祖先容器,并且满足 inline-size 和 样式 条件时应用。
在多个嵌套的 容器查询 中定义的样式规则,仅在所有包装的 容器查询 对该元素为真时应用。
注意: 嵌套的 容器查询 可以相对于不同的容器进行评估, 因此并不总是可以将单个 <container-condition> 合并 为一个单一的查询。
@container card( inline-size >30 em ) { @container style ( --responsive: true) { /* 样式 */ } }
上述样式仅在存在名为 "card" 的祖先容器,并且满足 inline-size 条件时应用, 以及满足 样式 条件的祖先容器。
全局、命名定义的 at-rules 如 @keyframes 或 @font-face 或 @layer 定义在 容器查询 内部时,不受 容器查询 条件的限制。
4.5. 动画容器
对容器查询的评估变化必须是样式变化事件的一部分, 即使变化是由于动画效果引起的。
main{ display : flex; width : 300 px ; } #container{ container-type : inline-size; flex : 1 ; } /* 初始解析宽度为200px,但随着过渡的进行而改变。 */ #inner{ transition : 1 s background-color; background-color : tomato; } /* 当此容器查询开始(或停止)应用时,#inner的background-color上必须开始一个过渡。 */ @container ( width <=150 px ) { #inner{ background-color : skyblue; } } #sibling{ width : 100 px ; transition : width1 s ; } #sibling:hover{ width : 200 px ; }
< main > < div id = container > < div id = inner > Inner</ div > </ div > < div id = sibling > Sibling</ div > </ main >
由计算值引起的变化容器查询长度单位 也必须是样式变化事件的一部分。
5. 容器特性
A container feature 查询特定方面的查询容器。
5.1. 尺寸容器特性
A container size query 允许查询 查询 容器的 主要盒子的大小。 它是单个 尺寸特性 (<size-feature>) 的布尔组合,每个查询特定的维度特性 查询容器。 <size-feature> 的语法与媒体特性相同: 一个特性名称、一个比较器和一个值。 [mediaqueries-5] 将尺寸特性组合成一个尺寸查询的布尔语法和逻辑与CSS特性查询相同。 (参见@supports。[CSS-CONDITIONAL-3])
如果查询容器 没有主要盒子, 或主要盒子不是布局包含盒子, 或者查询容器在相关轴上不支持容器大小查询, 则评估尺寸特性的结果未知。
相对长度单位 (包括容器查询长度单位) 在容器查询 条件中 根据计算值 进行评估,评估基于查询容器。
注意:这与相对单位在媒体查询中的处理不同。
aside, main{ container-type : inline-size; } aside{ font-size : 16 px ; } main{ font-size : 24 px ; } @container ( width >40 em ) { h2{ font-size : 1.5 em ; } }
查询条件中使用的40em值 相对于相关计算值的font-size在相关的查询容器上:
-
对于任何在aside内的h2,查询条件在640px以上为真。
-
对于任何在main内的h2,查询条件在960px以上为真。
5.1.1. 宽度: width 特性
名称: | 宽度 |
---|---|
适用于: | @container |
值: | <长度> |
类型: | 范围 |
5.1.2. 高度: height 特性
名称: | 高度 |
---|---|
适用于: | @container |
值: | <长度> |
类型: | 范围 |
5.1.3. 行内大小: inline-size 特性
名称: | 行内大小 |
---|---|
适用于: | @container |
值: | <长度> |
类型: | 范围 |
该行内大小 容器特性 查询大小的 查询容器的内容框 在查询 容器的行内轴中。
5.1.4. 块大小: block-size 特性
名称: | block-size |
---|---|
适用于: | @container |
值: | <长度> |
类型: | 范围 |
block-size 容器特性 查询 大小 的 查询容器 的 内容框 在 查询 容器 的 块轴 中。
5.1.5. 纵横比: aspect-ratio 特性
名称: | aspect-ratio |
---|---|
适用于: | @container |
值: | <ratio> |
类型: | 范围 |
该aspect-ratio 容器特性 定义为宽度 容器特性与高度 容器特性的比值。
5.1.6. 方向: orientation 特性
名称: | orientation |
---|---|
适用于: | @container |
值: | portrait | landscape |
类型: | 离散 |
- portrait
- 当高度 容器特性 大于或等于宽度 容器特性时,方向 容器特性 为portrait。
- landscape
- 否则方向 为landscape。
5.2. 样式容器特性
一个 容器样式查询 允许查询 计算值 的 查询容器。 它是个布尔组合,包含单独的 样式特性 (<style-feature>) 每个查询一个特定属性的 查询容器。 <style-feature> 的语法与 声明 [CSS-SYNTAX-3] 相同, 当给定属性在 查询容器 上的 计算值 与给定值匹配时,其查询为真 (该值也相对于 查询容器 计算), 当属性或其值无效或不支持时为未知, 其他情况为假。 布尔语法和逻辑将 样式特性 组合成 样式查询 的方法与 CSS 特性查询 相同。 (请参见 @supports。 [CSS-CONDITIONAL-3])
样式特性 查询一个 简写属性 时,如果 计算值 对于每个 长属性 匹配,则为真, 否则为假。
级联依赖关键字,例如 revert 和 revert-layer, 在 样式特性 中作为值无效, 并导致 容器样式查询 为假。
注意: 剩余的非级联依赖 CSS广泛 关键字 在 计算 时相对于 查询容器, 与其他值相同。
6. 容器相对长度: cqw, cqh, cqi, cqb, cqmin, cqmax 单位
容器查询长度单位指定相对于查询容器的长度。 使用容器查询长度单位的样式表可以更容易地将组件从一个查询容器移动到另一个。
容器查询长度单位有:
单位 | 相对于 |
---|---|
cqw | 查询容器的宽度的1% |
cqh | 查询容器的高度的1% |
cqi | 查询容器的内联大小的1% |
cqb | 查询容器的块大小的1% |
cqmin | 较小的 |
cqmax | 较大的 |
对于每个元素,容器查询长度单位被评估为在相关轴(或轴)上进行容器大小查询。 每个轴的查询容器是最近的接受该轴上的容器大小查询的祖先容器。 如果没有合格的查询容器可用,则使用该轴的小视口大小。
注意: 在某些情况下,同一元素上的cqi和cqb单位将相对于不同的查询容器进行评估。 类似地,cqmin和cqmax单位表示cqi和cqb单位中的较大或较小值,即使这些维度来自不同的查询容器。
子元素不会继承其父元素指定的相对值; 它们继承计算值。
/* 回退值不依赖于包含 */ h2{ font-size : 1.2 em ; } @container ( inline-size >=0 px ) { /* 仅在可用内联大小容器时应用 */ h2{ font-size : calc ( 1.2 em +1 cqi ); } }
7. API
7.1.
CSSContainerRule
接口
CSSContainerRule
接口表示一个 @container 规则。
[Exposed =Window ]interface :
CSSContainerRule CSSConditionRule { };
conditionText
类型为CSSOMString
(CSSContainerRule 特定于 CSSConditionRule 的属性定义)conditionText
属性(定义在CSSConditionRule
父规则上), 在获取时,必须返回指定的条件, 而不进行任何逻辑简化, 以便返回的条件在任何符合本规范的实现中 (包括实现本规范中允许的未来扩展的实现) 都会评估为与指定条件相同的结果。 换句话说, 允许令牌流简化 (例如将空格减少为一个空格 或在已知为可选的情况下省略它), 但不允许逻辑简化(例如删除不必要的括号, 或基于结果评估进行简化)。
为 CSSContainerRule 添加 CSSOM API [问题 #7033]
Container Queries 应该具有
matchContainer
方法。
这将基于 matchMedia()
和 MediaQueryList
接口建模,
但应用于元素而不是窗口。
在测量布局大小时,它的行为类似于 resizeObserver
,
但提供了额外的 Container Query 语法和功能。 [问题 #6205]
8. 完全抑制元素内容:content-visibility 属性
CSS Containment 2 § 4 完全抑制元素内容:content-visibility 属性
9. 隐私和安全考虑
CSS Containment 2 § 5 隐私和 安全考虑
附录 A. 变更
本附录为信息性。
自 2021 年 12 月 21 日首次公开工作草案以来的变更
自2021 年 12 月 21 日首次公开工作草案以来的重大变更包括:
-
允许container-name的计算值 包含重复标识符。 (问题 7181)
-
使<'container-name'>在container简写中为必需。 (问题 7142)
-
澄清简写属性在container 样式查询中的处理。 (问题 7095)
-
级联依赖关键字不允许作为样式特性中的值, 并导致container 样式查询为假。 (问题 7080)
-
将container-type的初始值更改为style。 (问题 6393)
-
从container-type中移除块尺寸值, 因为当前无法进行单轴块尺寸包含。 (问题 1031)
-
从<string>选项中移除container-name语法。 container 名称必须是<custom-ident>。 (问题 6405)
-
在<'container-name'> 和<'container-type'>在container简写属性中反转顺序, 两者都是可选的。 (问题 6393)
-
允许在<general-enclosed>语法中使用<container-condition>, 以便于向后兼容。 (问题 6396)
-
从<size-feature>查询中移除尺寸函数语法。 (问题 6870)
-
更新查询 container选择过程, 以考虑必要的container-types, 并删除了显式类型选择语法。 (问题 6644)
-
移除状态查询特性,这些特性已被推迟。 (问题 6402)
从 CSS Containment Level 2 的变更
-
引入行内尺寸包含。
-
定义了Container Queries所需的术语、属性、单位和 at-rule。
致谢
感谢以下人员的评论和先前的工作: Adam Argyle, Amelia Bellamy-Royds, Anders Hartvoll Ruud, Brian Kardell, Chris Coyier, Christopher Kirk-Nielsen, David Herron, Elika J. Etemad (fantasai), Eric Portis, Ethan Marcotte, Geoff Graham, Gregory Wild-Smith, Ian Kilpatrick, Jen Simmons, Kenneth Rohde Christiansen, L. David Baron, Lea Verou, Martin Auswöger, Martine Dowden, Mike Riethmuller, Morten Stenshorne, Nicole Sullivan, Rune Lillesveen, Scott Jehl, Scott Kellum, Stacy Kvernmo, Theresa O’Connor, Una Kravets, 以及其他许多人对本规范的贡献。