我们仍然处于容器查询的超级早期阶段。对于广泛的浏览器支持来说还为时过早,但 Chromium 已经支持它,Safari 从版本 16 开始支持它,而 Firefox 也可能 不会落后太多。
大多数关于容器查询的早期讨论通常将语法与媒体查询进行比较。
/* Stacked flex container */
.post {
display: flex;
flex-direction: column;
}
/* Change direction when viewport is 600px or wider */
@media(min-width: 600px) {
.post {
flex-direction: row;
}
}
/* Define the container */
.posts {
container-name: posts;
container-type: inline-size;
}
.post {
display: flex;
flex-direction: column;
}
/* Query the container's min-width */
@container posts (min-width: 600px) {
/* Change styles when `posts` container is 600px or wider */
.post {
flex-direction: row;
}
}
这两者都在查询 min-width: 600
。区别在于媒体查询正在查看视窗的宽度以触发这些样式更改,而容器查询正在查看 .posts
元素的计算宽度。很棒!
但在听了 CSS Podcast 第 59 集 之后,Una 和 Adam 探讨了容器查询的未来:**样式查询**!CSS Containment Module Level 3 规范的当前工作草案 定义了容器样式查询
一个 容器样式查询 允许查询 计算值 的 查询容器。它是一个布尔组合,其中包含各个 样式特征 (<style-feature>),每个特征都查询查询容器的单个特定属性。
但目前还没有语法示例 - 只有简短的描述
一个 <style-feature> 的语法与 声明 相同,如果查询容器上给定属性的计算值匹配给定值(该值也相对于查询容器进行计算),则该查询为真,如果属性或其值无效或不受支持,则该查询为未知,否则该查询为假。布尔语法和将 样式特征 组合成一个 样式查询 的逻辑与 CSS 特性查询 相同。(参见 @supports。)
因此,随着时间的推移,我们应该期待实现类似这样的功能
.posts {
container-name: posts;
}
@container posts (background-color: #f8a100) {
/* Change styles when `posts` container has an orange background */
.post {
color: #fff;
}
}
这是一个相当愚蠢的例子。需要注意的是,container-type
不再基于容器的 inline-size
,而是由 style
决定。我们可以像这样声明它
.posts {
container-name: posts;
container-type: style; /* unnecessary */
}
…但 所有容器查询默认情况下都是 style
查询。好吧。至少现在看来是这样的。Miriam Suzanne 有一个很好的 可能出现的问题概述。
在哪些情况下查询容器的样式会派上用场?我目前还不知道!但我的思绪飞到了几个地方
- **自定义属性值:**我们已经看到自定义属性像状态指示器一样使用,例如 Ana 之前介绍的 DRY-切换方法。值发生变化,样式也会发生变化。
- **替代黑暗模式方法:**与其基于更改主体类来重新分配自定义属性值,不如在主体背景颜色发生变化时更改整个调色板。
- **更复杂的查询条件:**例如,我们希望在容器的
size
和style
条件都满足时应用样式。
Una 在 CSS Podcast 中还提到,容器样式查询可以帮助防止一些尴尬的样式情况,例如,如果我们碰巧在一个已经用斜体显示的 blockquote
中包含斜体文本。
blockquote {
container-name: quote;
}
@container quote (font-style: italic) {
em, i, q, address {
font-style: normal;
}
}
似乎不必要地复杂。为什么不
@container .posts (min-width: 600px) {
// 应用于 .posts
}
不是讽刺,真的在寻找逻辑…
这将非常酷而且效率更高。但我也理解,CSS 需要提前知道一些事情,其中之一就是能够将容器声明与明确定义为容器的元素匹配 - 更不用说我们想要的查询类型,无论是容器的大小还是样式。我们必须告诉 CSS 这些信息,这样浏览器才能知道如何进行匹配。
选择器“.posts”理论上可以定位多个 HTML 节点,每个节点都具有设置为 posts 的类属性。在这种情况下,确定查询应该检查哪个容器的宽度将不是显而易见的。
我可以想象,CSS 属性“container-name”用于确保只有一个容器具有给定的名称。
我的猜测是
.post
和container-name: posts;
碰巧在示例中使用了相同的名称,但在现实世界中,情况并非总是如此,相同的container-name
将在多个类选择器中使用。此处的回复涵盖了一些原因。正如 Geoff 所建议的,我们需要明确地建立容器 - 因此即使我们在
@container
语法中使用选择器,也无法避免这一步骤。但是,名称是可选的,可以在不同的元素之间重复使用,并且一个容器可以有多个名称。这增加了很大的灵活性。
您不需要为容器命名,也不需要在查询语法中提及名称。当条件中没有添加名称时,将查询最近的有效祖先容器。如果您只想了解最直接相关的上下文,则省略名称即可。
您可以将相同的名称应用于多个选择器以创建一个容器“类”。因此,您可以将
layout
容器名称添加到主区域、侧边栏、帖子、网格项等。然后,您可以查询最近的layout
容器。您可以将多个名称应用于单个容器,使其成为多个模式的一部分。因此,我们可以说主区域是一个容器,它是我们
layout
模式的一部分,但也可以给它命名为main
和color-context
,因为它应用了独特的配色方案。现在,我们可以编写一些特定于main
区域名称的查询,一些查询最近的layout
,一些查询最近的color-context
- 并且主区域被设置为处理所有这些查询。