容器查询现已推出!
好消息:开发者最常请求的功能之一已开始在 Web 浏览器中推出!从 Chromium 105 和 Safari 16 开始,您现在可以在这些浏览器中创建基于大小的容器查询并使用容器查询单位值。为了让基于尺寸的容器查询和 cq
单位更易于使用,Chrome 的 Aurora 团队一直在努力更新容器查询多填充,以支持更多浏览器和用例,让您可以放心地使用这项强大的功能。
什么是容器查询?
容器查询是一项 CSS 功能,可让您编写样式逻辑,以定位父元素的功能来为其子元素设置样式。您可以通过查询父级的尺寸来创建真正基于组件的自适应设计。与仅提供视口大小信息的媒体查询等相比,这些信息更加精细且实用。
借助容器查询,您可以编写可重复使用的组件,这些组件的显示方式会因其在网页中的位置而异。这样一来,它们在不同页面和模板中的弹性和响应能力会大大提高。
使用容器查询
假设您有以下 HTML:
<!-- card parent -->
<div class=”card-parent”>
<div class=”card>
<!-- card contents -->
…
</div>
</div>
如需使用容器查询,您首先需要对要跟踪的父元素设置包含关系。为此,您可以设置 container-type
属性,也可以使用 container
简写形式同时设置容器类型和容器名称。
.card-parent {
/* query the inline-direction size of this parent */
container-type: inline-size;
}
现在,您可以使用 @container
规则根据最近的父元素设置样式。对于上图所示的设计(其中卡片可能会从一列变为两列),请编写如下代码:
@container (min-width: 300px) {
.card {
/* styles to apply when the card container (.card-parent in this case) is >= 300px */
/* I.e. shift from 1-column to 2-column layout: */
grid-template-columns: 1fr 1fr;
}
}
为了更加简洁明确,请为父元素容器指定一个名称:
.card-parent {
container-type: inline-size;
/* set name here, or write this in one line using the container shorthand */
container-name: card-container;
}
然后,将之前的代码重写为:
@container card-container (min-width: 300px) {
.card {
grid-template-columns: 1fr 1fr;
}
}
容器查询单元
为了让容器查询更实用,您还可以使用基于容器的单位值。下表显示了可能的容器单位值及其与容器大小的对应关系:
单位 | 相对于 |
---|---|
cqw | 查询容器宽度的 1% |
cqh | 查询容器高度的 1% |
cqi | 查询容器内嵌大小的 1% |
cqb | 查询容器块大小的 1% |
cqmin | cqi 或 cqb 中的较小值 |
cqmax | cqi 或 cqb 中的较大值 |
基于容器的单位的使用方式之一是响应式排版。基于视口的单位(例如 vh
、vb
、vw
和 vi
)可用于调整屏幕上任何元素的大小。
.card h2 {
font-size: 15cqi;
}
此代码会将字号设为容器内嵌大小的 15%,这意味着随着内嵌大小(宽度)的增加,字号会变大,随着内嵌大小的缩小,字号会变小。如需进一步优化,请使用 clamp()
函数为排版设置最小和最大尺寸限制,并根据容器大小自适应调整其尺寸:
.card h2 {
font-size: clamp(1.5rem, 15cqi, 3rem);
}
现在,标题绝不会大于 3rem
或小于 .5rem
,但会占用容器内嵌大小的 15%。
此演示进一步改进了宽度较大的卡片,使其在 2 列视图中显示时尺寸范围更小。
容器查询 polyfill
由于容器查询是一项非常强大的功能,因此我们希望您能够轻松地将其纳入到您的项目中,并且了解浏览器支持对此至关重要。因此,我们一直在努力改进容器查询多填充。此 polyfill 在以下平台中获得了广泛支持:
- Firefox 69 及更高版本
- Chrome 79 及更高版本
- Edge 79 及更高版本
- Safari 13.4 及更高版本
压缩后的大小小于 9kb,并将 ResizeObserver 与 MutationObserver 结合使用,以支持稳定版浏览器中目前提供的完整 @container 查询语法:
- 离散查询 (
width: 300px
和min-width: 300px
)。 - 范围查询 (
200px < width < 400px
和width < 400px
)。 - 属性和关键帧中的容器相对长度单位 (
cqw
、cqh
、cqi
、cqb
、cqmin
和cqmax
)。
使用容器查询 polyfill
如需使用此 polyfill,请将以下脚本标记添加到文档的标头中:
<script type="module">
if (!("container" in document.documentElement.style)) {
import("https://unpkg.com/container-query-polyfill@^0.2.0");
}
</script>
您还可以使用服务根据 User-Agent
有条件地提供 polyfill,或在自己的源代码中自行托管 polyfill。
为了提供最佳用户体验,建议您最初仅对底部内容使用 polyfill,并使用 @supports
查询将其暂时替换为加载指示器,直到 polyfill 准备好显示为止:
@supports not (container-type: inline-size) {
.container,
footer {
display: none;
}
.loader {
display: flex;
}
}
在网络和设备速度足够快的情况下,或者在原生支持容器查询的设备上,系统绝不会显示此加载指示器。
新的 Polyfill 功能
更新后的 polyfill 支持:
- 嵌套
@container
规则。 - 支持将
@container
规则嵌套在@supports
和@media
查询下,反之亦然。 - 在 polyfill 加载后,
@supports (container-type: inline-size)
等条件 CSS 将通过。 - 全面支持 CSS 语法(在语法上有效的任何位置添加注释都不会再出现任何问题)。
- 纵向写入模式(通过 writing-mode)。
- 查询条件、属性声明和动画关键帧支持容器相对单位 (
cqw
、cqh
等)。 查询条件支持rem
和em
。 - 展开后的容器查询语法:
- 范围语法(例如
(200px < width < 400px)
)。 - 等式查询(例如
(width = 200px)
)。
- 范围语法(例如
::before
和::after
等伪元素。- 通过可选的权宜解决方法,系统支持不支持
:is(...)
/:where(...)
的浏览器 orientation
和aspect-ratio
功能查询。- 正确根据功能过滤查询(例如,在横向写入模式下,系统会正确禁止对
container: inline-size
查询height
)。 - DOM 变异(例如,在运行时移除
<style>
和<link>
元素)。
多填充限制和警告
如果您使用的是容器查询 polyfill,请注意以下缺少的功能:
- 尚不支持 Shadow DOM。
@media
查询条件不支持容器相对单位(例如cqw
和cqh
)。- Safari:15.4 之前的动画关键帧不支持容器相对单位。
- 查询条件中尚不支持
calc()
、min()
、max()
或其他数学函数。 - 此 polyfill 仅适用于内嵌 CSS 和同源 CSS。不支持跨源样式表和 iframe 中的样式表(除非手动加载了 polyfill)。
layout
和style
容器需要底层浏览器支持:- Safari 15.4 及更高版本
- Firefox 目前不支持样式嵌套,但正在努力实现该功能。
警告
- 为避免影响 FID 和 CLS,该 polyfill 不保证何时会发生首次布局,即使同步加载也是如此,但会尝试避免不合理地延迟 LCP。换句话说,您绝不应依赖于它来实现首次绘制。
- 生成
ResizeObserver Loop Errors
。原始 polyfill 也会执行此操作,但值得注意。之所以会出现这种情况,是因为container-type: inline-size
的块大小在评估查询后可能会发生变化,但ResizeObserver
无法告知它我们不关心块大小的变化。 - 此 polyfill 已通过 Web 平台测试,通过率达到 70%,因为 JavaScript API 等某些功能未进行 polyfill,因此通过率故意设为接近 70%。
- 2.23% 使用低于以下版本的浏览器的用户需要使用
:where()
权宜解决方法:- Safari 14
- Chromium 88
- Edge 88
- Samsung Internet 15
- Firefox 78