@container 和 :has():Chromium 105 中两种强大的全新自适应 API

容器查询和 :has() 是在自适应天堂中进行匹配的。幸运的是,Chromium 105 同时提供了这两项功能。这是一个巨大的版本,包含两项开发者迫切需要的功能,可实现响应式界面!

容器查询:简明摘要

借助容器查询,开发者可以向父选择器查询其尺寸和样式信息,这样无论子元素位于网页上的什么位置,都可以拥有其自适应样式逻辑。

开发者现在还可以查询页内元素的大小,而不依赖于视口来设置输入(例如可用空间)的样式。此功能意味着组件拥有自己的自适应样式设置逻辑。这使组件更具弹性,因为无论它出现在页面的什么位置,样式逻辑都附着在组件上。

使用容器查询

如需使用容器查询进行构建,您必须先在父元素上设置包含关系。您可以通过在父级容器上设置 container-type 来实现此目的。您可能会看到一张包含图片和一些文字内容的卡片,如下所示:

单列两列的卡片。

如需创建容器查询,请在卡片容器上设置 container-type

.card-container {
  container-type: inline-size;
}

container-type 设置为 inline-size 会查询父项的内嵌方向尺寸。在英语等拉丁语言中,该值为卡片的宽度,因为文本从左到右以内嵌方式排列。

现在,我们可以使用该容器通过 @container 将样式应用于其任何子级:

.card {
  display: grid;
  grid-template-columns: 1fr 1fr;
}

@container (max-width: 400px) {
  .card {
    grid-template-columns: 1fr;
  }
}

:has() 父级选择器

借助 CSS :has() 伪类,开发者可以检查父元素是否包含具有特定参数的子元素。

例如,p:has(span) 表示段落 (p) 选择器,其中包含 span。你可以使用此方法设置父段落本身的样式,设置父段落内任何内容的样式。一个实用示例是,使用 figure:has(figcaption) 为包含图片说明的 figure 元素设置样式。如需详细了解 :has(),请参阅 Jhey Tompkins 的这篇文章

容器查询和 :has()

您可以将 :has() 的父级选择能力与容器查询的父级查询能力相结合,创建一些真正动态的固有样式。

我们来看一下第一个包含火箭卡的示例。如果您的卡片没有图片,该怎么办?您或许想增加标题的大小,并将网格布局调整为单列,以便在没有图片的情况下看起来更有目的性。

卡片上不含图片的较大文本,并以列的形式显示。

在此示例中,包含图片的卡片采用两列网格模板,而不含图片的卡片采用单列布局。此外,不含该图片的卡片具有较大的标题。如需使用 :has() 编写此代码,请使用以下 CSS。

.card:has(.visual) {
  grid-template-columns: 1fr 1fr;
}

您要查找一个类为 visual 的元素,以应用上面的两列样式。另一个简洁的 CSS 函数是 :not()。此规范与 :has() 属于同一规范,但存在时间较长,且浏览器支持更完善。您甚至可以结合使用 :has():not(),如下所示:

.card:not(:has(.visual)) h1 {
  font-size: 4rem;
}

在上面的代码中,您编写了一个选择器,用于在不包含 visual 类的卡片内设置 h1 的样式。通过这种方式,您可以非常清晰地调整字体大小。

综合应用

上面的演示展示了 :has():not()@container 的组合,但当您可以在多个位置看到同一元素时,容器查询的确大放异彩。我们来添加一些样式,并以网格形式并排展示这些卡片。

现在,您可以切实感受到现代 CSS 的强大功能。我们能够使用有针对性的样式编写清晰的样式,基于逻辑构建逻辑并创建非常强大的组件。随着这两个强大的功能在 Chromium 105 中推出并迅速获得跨浏览器支持,当一名界面开发者面临着非常激动的时刻!