CSS 容器查询

Avatar of Geoff Graham
Geoff Graham

CSS 容器查询的主要思想是将一个元素注册为“容器”,并在容器元素满足某些条件时对其他元素应用样式。

由 DigitalOcean 提供

DigitalOcean 提供您在任何阶段支持增长的云计算服务。 立即获取 200 美元免费信用额度!

容器查询通常被认为是一种现代的响应式网页设计方法,传统的媒体查询长期以来一直是黄金标准——原因是我们可以创建由对容器宽度响应的元素构成的布局,而不是对视窗宽度响应的布局。

.parent {
  container-name: hero-banner;
  container-type: inline-size;

  /* or container: hero-banner / inline-size; */
}

}

.child {
  display: flex;
  flex-direction: column;
}

/* When the container is greater than 60 characters... */
@container hero-banner (width > 60ch) {
  /* Change the flex direction of the .child element. */
  .child { 
    flex-direction: row;
  }
}

为什么要关注 CSS 容器查询?

  1. 使用容器查询时,我们使元素能够根据其容器的大小而不是视窗的大小进行更改。
  1. 它们允许我们以更可预测的方式定义特定元素的所有样式。
  1. 它们比媒体查询更可复用,因为它们在任何地方使用时都具有相同的行为。因此,如果您要创建包含容器查询的组件,可以轻松地将其放入另一个项目中,它仍然会以相同的可预测方式运行。
  1. 它们引入了新的 CSS 长度单位类型,可以使用这些单位根据容器的大小对元素进行大小调整。

将元素注册为容器

.cards {
  container-name: card-grid;
  container-type: inline-size;

  /* Shorthand */
  container: card-grid / inline-size;
}

此示例注册了一个名为 card-grid 的新容器,可以通过其 inline-size 进行查询,这是一个表示我们在水平书写模式下“宽度”的更正式的说法。它是一个 逻辑属性。否则,“内联”将在垂直书写模式下指的是容器的“高度”。

  • container-name 属性用于将元素注册为容器,该容器根据容器的大小和样式对其他元素应用样式。
  • container-type 属性用于将元素注册为容器,当该元素满足某些条件时,可以对其他元素应用样式。
  • container 属性是一个简写属性,它将 container-namecontainer-type 属性合并到一个声明中。

一些可能的陷阱

查询容器

@container my-container (width > 60ch) {
  article {
    flex-direction: row;
  }
}
  • @container at-规则属性告诉浏览器我们正在使用容器查询,而不是媒体查询(例如,@media)。
  • 其中的 my-container 指的是容器的名称,如容器的 container-name 属性中所声明。
  • article 元素表示容器中的一个项目,无论它是容器的直接子元素还是更远的祖先。无论哪种方式,该元素都必须位于容器中,并且在匹配查询条件时将对其应用样式。

一些可能的陷阱

容器查询属性和值

容器查询属性和值

container-name

container-name: none | <custom-ident>+;
值描述
  • none: 元素没有容器名称。这是默认情况,因此您可能永远不会使用此值,因为它的目的是纯粹设置属性的默认行为。
  • <custom-ident>: 这是容器的名称,可以是任何内容,但不能是为其他功能保留的单词,包括 defaultnoneatnoor。请注意,名称没有用引号括起来。
  • 初始值: none
  • 应用于: 所有元素
  • 继承:
  • 百分比: 不适用
  • 计算值: none 或标识符的排序列表
  • 规范顺序: 根据语法
  • 动画: 不可动画

container-type

container-type: normal | size | inline-size;
值描述
  • normal: 这表示该元素是一个容器,可以通过其样式而不是大小进行查询。 所有元素默认情况下都是容器,因此我们甚至不需要明确地分配 container-type 来定义样式容器。
  • size: 如果我们要根据容器的大小查询容器,无论是内联方向还是块方向。
  • inline-size: 这允许我们根据容器的内联大小查询容器,在标准水平书写模式下等同于 width。这可能是最常用的值,因为我们可以根据元素的大小来建立响应式设计,而不是像通常使用 媒体查询那样根据视窗的大小来建立。
  • 初始值: normal
  • 应用于: 所有元素
  • 继承: 否
  • 百分比: 不适用
  • 计算值: 按关键字指定
  • 规范顺序: 根据语法
  • 动画: 不可动画

container

container: <'container-name'> [ / <'container-type'> ]?
值定义

如果省略了<'container-type'>,它将被重置为其初始值normal,该值定义了一个样式容器而不是大小容器。换句话说,所有元素默认情况下都是样式容器,除非我们显式地将container-type属性值设置为sizeinline-size,这使我们能够查询容器的大小尺寸。

  • 初始值:none / normal
  • 应用于: 所有元素
  • 继承: 否
  • 百分比: 不适用
  • 计算值:如指定
  • 规范顺序: 根据语法
  • 动画: 不可动画

容器长度单位

容器宽度和高度单位

单位名称相当于…
cqw容器查询宽度查询容器宽度的 1%
cqh容器查询高度查询容器高度的 1%

容器逻辑方向

单位名称相当于…
cqi容器查询内联大小查询容器内联大小的 1%,在水平书写模式下为其宽度。
cqb容器查询块大小查询容器内联大小的 1%,在水平书写模式下为其高度。

容器最小和最大长度

单位名称相当于…
cqmin容器查询最小尺寸cqicqb 的值,以较小的那个为准。
cqmax容器查询最大尺寸cqicqb 的值,以较大的那个为准。

容器样式查询

容器样式查询是 CSS 容器查询拼图的另一个部分。我们不需要根据容器的sizeinline-size来查询容器,而是可以查询容器的 CSS 样式。当容器的样式满足查询条件时,我们可以将样式应用于其他元素。这是我们长期以来在 Web 上想要的“条件”样式:如果这些样式在这里匹配,则在其他地方应用这些其他样式。

CSS 容器样式查询在撰写本文时仅作为现代 Web 浏览器中的实验性功能提供,即使那样,样式查询也只能够评估 CSS 自定义属性(即变量)。

浏览器支持

在撰写本文时,该功能仍然被认为是实验性的,并且不受任何浏览器的支持,除非通过功能标志启用。

此浏览器支持数据来自Caniuse,其中包含更多详细信息。数字表示浏览器在该版本及其更高版本中支持该功能。

桌面

ChromeFirefoxIEEdgeSafari
130127TP

移动/平板

Android ChromeAndroid FirefoxAndroidiOS Safari
12712718.0

注册样式容器

article {
  container-name: card;
}

就是这样!实际上,我们甚至不需要container-name属性,除非我们需要专门定位它。否则,我们可以跳过注册容器。

如果您想知道为什么没有container-type声明,那是因为所有元素都被认为是容器。这很像所有元素默认情况下都是position: relative;不需要声明它。我们声明container-type的唯一原因是,如果我们想要 CSS 容器大小查询而不是 CSS 容器样式查询。

因此,实际上,不需要注册容器样式查询,因为所有元素开箱即用都是样式容器!因此,我们声明container-name的唯一原因仅仅是为了在编写样式查询时帮助按名称选择特定容器。

使用样式容器查询

@container style(--bg-color: #000) {
  p { color: #fff; }
}

在本例中,我们查询任何匹配的容器(因为所有元素默认情况下都是样式容器)。

请注意,语法与传统的媒体查询非常相似?最大的区别是,我们正在编写@container而不是@media。另一个区别是,我们正在调用一个包含匹配样式条件的style()函数。这样,样式查询就与大小查询区分开来,尽管没有相应的size()函数。

在本例中,我们正在检查名为--bg-color的特定自定义属性是否设置为黑色 (#000)。如果变量的值与该条件匹配,那么我们将段落 (p) 文本的color设置为白色 (#fff)。

自定义属性和变量

.card-wrapper {
  --bg-color: #000;
}
.card {
  @container style(--bg-color: #000) {
    /* Custom CSS */
  }
}

嵌套样式查询

@container style(--featured: true) {
  article {
    grid-column: 1 / -1;
  }
  @container style(--theme: dark) {
    article {
      --bg-color: #000;
      --text: #fff;
    }
  }
}

规范

CSS 容器查询在CSS Containment Module Level 3 规范中定义,该规范目前处于撰写本文时的编辑草案状态。

浏览器支持

CSS 容器大小查询的浏览器支持情况很好。只是在撰写本文时,样式查询缺乏支持。

  • Chrome 105 于 2022 年 8 月 30 日发布,支持该功能。
  • Safari 16 于 2022 年 9 月 12 日发布,支持该功能。
  • Firefox 110 于 2023 年 2 月 14 日发布,支持该功能。

此浏览器支持数据来自Caniuse,其中包含更多详细信息。数字表示浏览器在该版本及其更高版本中支持该功能。

桌面

ChromeFirefoxIEEdgeSafari
10611010616.0

移动/平板

Android ChromeAndroid FirefoxAndroidiOS Safari
12712712716.0

演示!

网上有很多例子演示了容器查询是如何工作的。以下例子在说明容器查询的一般概念方面并不独特,因为它们说明了在容器元素满足特定条件时应用样式的一般概念。

您将在本指南末尾的参考资料中找到更多示例,但请查看Ahmad Shadeed 的容器查询实验室,以获取最完整的示例集,因为它也用作巧妙的容器查询用例的集合。

卡片组件

在本例中,“卡片”组件根据其容器中的可用空间量更改其布局。

号召性用语面板

这个例子很像那些用来订阅电子邮件通讯的小面板。请注意布局如何根据容器中可用的空间大小变化三次。这就是 CSS 容器查询如此强大的原因:你可以将这个面板放到任何项目中,布局都会按照预期进行响应,因为它是基于它所处的空间而不是浏览器视窗的大小。

步进器组件

此组件显示一系列“步骤”,就像时间线一样。在较宽的容器中,步进器会水平显示步骤。但是,如果容器变得足够小,步进器就会调整布局,使步骤垂直堆叠。

图标按钮

有时我们喜欢用图标装饰按钮,以用更多含义和上下文来突出显示按钮的标签。有时我们不知道这个按钮在任何给定上下文中会有多宽,这使得很难知道何时隐藏图标或在空间变得有限时重新排列按钮的样式。在这个例子中,只要有空间容纳图标和按钮标签,图标就会显示在按钮的右边缘。如果空间不足,按钮就会变成一个正方形,将图标堆叠在标签之上。请注意,border-radius是如何以 **容器查询单位** 4cqi 设置的,它等于容器内联大小(即宽度)的 4%,并且随着按钮尺寸增大,边角变得更圆。

分页

分页是一个很好的例子,它可以从 CSS 容器查询中获益,因为根据我们拥有的空间量,我们可以选择显示指向各个页面的链接,或者隐藏它们,只显示两个按钮,一个用来翻页到较旧的内容,另一个用来翻页到较新的内容。

文章和教程

一般信息

容器尺寸查询教程

容器样式查询

参考