发布于 2026-01-06 2 阅读
0

CSS容器查询 什么是容器查询 如何使用容器查询 如何影响规范 结束

CSS容器查询

什么是容器查询?

如何使用容器查询

影响规格

结束

CSS 领域即将迎来一些令人兴奋的新变化,我之所以说“即将到来”,是因为它目前尚未被任何浏览器支持,规范也尚未最终定稿(截至撰写本文时)。尽管如此,Chrome 的下一个版本已经引入了这项功能,我相信不久之后所有“现代”浏览器都会支持它。

什么是容器查询?

容器查询与媒体查询类似,但有一个主要且关键的区别。媒体查询会查询整个文档,并根据查询结果修改内容。例如,如果文档宽度超过 1025 像素,您可能希望将内容分成两列而不是一列。代码大致如下。

main.content {
  column-count: 1;
  column-gap: 2em;
}

@media screen and (min-width: 1025px) {
  main.content {
    column-count: 2;
  }
}
Enter fullscreen mode Exit fullscreen mode

容器查询遵循相同的原理,但它们不是查询整个文档,而是查询容器。

他们如何帮助开发者

想象一下这样的场景:你有一个联系卡片,想在网站的各个位置显示。有些地方它位于主要内容区域,而有些地方你决定将其显示在侧边栏中。在同一个媒体查询中,侧边栏的宽度可能是 250 像素,而主要内容区域的宽度可能是 700 像素,这就导致卡片的显示效果需要有所不同。解决方法很简单,只需为卡片设置不同的类和媒体查询即可,但还有更好的方法……那就是使用容器查询!

如何使用容器查询

要使用容器查询,我们必须告诉容器(我们要应用查询的元素的父元素)我们关心它的尺寸,我们通过新的contain属性来实现这一点。

`none`
表示元素正常渲染,不应用任何包含规则。`strict`
表示
除样式外的所有包含规则都应用于该元素。这等价于 `contain: size layout paint`。`content`
表示
除大小和样式外的所有包含规则都应用于该元素。这等价于 `contain: layout paint`。`size`
表示
可以调整元素的大小,而无需检查其后代元素的大小。`layout`
表示
元素外部的任何内容都不会影响其内部布局,反之亦然。`style`
表示
对于可能影响多个元素(而不仅仅是元素及其后代)的属性,这些影响不会超出包含元素的范围。请注意,此值在规范中被标记为“有风险”,可能并非所有地方都支持。`paint`
表示
元素的后代元素不会显示在其边界之外。如果包含框位于屏幕外,浏览器无需绘制其包含的元素——这些元素也必须位于屏幕外,因为它们完全包含在该框内。如果子元素超出包含元素的边界,则该子元素将被裁剪到包含元素的边框内。

目前 Mozilla 上的相关文档略显不足,这种情况比较少见。我们想使用inline-sizeMozilla 其他地方描述的属性,如下所示:

当我们使用媒体查询时,大多数时候我们关心的是可用宽度(或inline-size)。

实际案例

让我们以前面提到的联系人卡片为例,编写一些代码来描述它。

<div class="site">
  <main class="content">
    <div class="contact-card">
      <img class="contact-card__profile-image" src="profile.png" alt="profile" />
      <div class="contact-card__profile-information">
        <h1>Both Names</h1>
        <p>Some info about me</p>
      </div>
    </div>
  </main>
  <aside class="side-panel">
    <div class="contact-card">
      <img class="contact-card__profile-image" src="profile.png" alt="profile" />
      <div class="contact-card__profile-information">
        <h1>Both Names</h1>
        <p>Some info about me</p>
      </div>
    </div>
  </aside>
</div>

Enter fullscreen mode Exit fullscreen mode

HTML 代码虽然很简单,但我认为它表达清楚了我们有一个联系卡,它在两个地方,宽度可能差别很大。

/* Just some simple css to get it started */
.site {
  display: flex;
  max-width: 800px;
  margin: 0 auto;
}

main.content {
  width: 60%;
  background: #ccc;
}

aside.side-panel {
  width: 40%;
  background: tomato;
}

/* Real css starts here */
main.content, aside.side-panel {
  container: layout / inline-size;
}

.contact-card {
  display: flex;
  flex-direction: column;
  align-items: center;
  width: 200px;
  background-color: white;
  padding: 2em;
  box-sizing: border-box;
  border-radius: 2px;
  margin: 1em;
  box-shadow: 0 1px 3px rgba(0, 0, 0, 0.2), 0 1px 1px rgba(0, 0, 0, 0.4)
}

.contact-card__profile-image {
  height: 50px;
  width: 50px;
  border-radius: 50px;
  border: 1px solid black;
}

.contact-card__profile-information {
  margin-left: 0.5em;
}

.contact-card__profile-information h1 {
  text-align: center;
  margin: 0;
  font-size: 1.2em;
}

.contact-card__profile-information p {
  text-align: center;
  margin: 0.5em 0 0 0;
}

@container layout (min-width: 450px) {
  .contact-card {
    width: 300px;
    flex-direction: row;
    align-items: flex-start;
  }

  .contact-card__profile-information h1 {
    text-align: left;
  }

  .contact-card__profile-information p {
    text-align: left;
  }
}
Enter fullscreen mode Exit fullscreen mode

这段 CSS 代码中,我们先设置了卡片的样式contact-card,然后使用容器查询,当宽度设置为 450px 时,容器会改变卡片的样式。正如你所看到的,它本质上与媒体查询相同,但它是基于容器的。

以下是代码的渲染效果(希望不久的将来我们能在更多浏览器中进行测试)。这是实际运行后的代码,jsfiddle

例子

影响规格

正如我一开始所说,规范尚未最终定稿,如果您想了解大家的建议,或者想提出自己的建议,现在还来得及。请前往git issues 看板查看。

结束

我对此感到非常兴奋,我主要使用 React,我非常期待组件能够根据其父组件的大小而改变。

一段非常激动人心的时光

好了,就到这里,帖子到此结束。如果你有任何问题,欢迎在评论区留言。我可能无法立即回答所有问题,但我们一起来学习吧。如果你愿意,也可以在推特上找到我。

非常感谢您的阅读❤️🧠🧠❤️🦄🦄🧠❤️🧠

文章来源:https://dev.to/link2twenty/css-container-queries-1205