多年来,“如何在 CSS 中做 X?“的答案是”用 JavaScript”。2026 年这个答案对大多数情况都不再适用。三个特定功能重新绘制了浏览器设计的版图。
目录
容器查询:响应容器,而非屏幕
媒体查询响应的是 viewport 的宽度。问题在于:一个组件可能根据父布局存在于窄列或宽列中。容器查询解决了这个问题。
/* 声明容器 */
.card-wrapper {
container-type: inline-size;
container-name: card;
}
/* 组件响应其容器 */
@container card (min-width: 400px) {
.card {
display: grid;
grid-template-columns: 200px 1fr;
}
.card__image {
grid-row: 1 / 3;
}
}
@container card (max-width: 399px) {
.card {
display: flex;
flex-direction: column;
}
}card.css
<!-- 同一组件在任何上下文中都能工作 -->
<aside class="card-wrapper" style="width: 300px">
<article class="card">...</article>
<!-- 垂直布局 -->
</aside>
<main class="card-wrapper" style="width: 700px">
<article class="card">...</article>
<!-- 水平布局 -->
</main>card.html
容器查询单位
查询也暴露了相对于容器的单位:
.card__title {
font-size: clamp(1rem, 4cqi, 2rem); /* cqi = 容器查询内联大小 */
}typography.css
:has() 伪类——我们一直想要的父选择器
:has() 根据元素的后代来选择它。这是 CSS 数十年来拒绝的”父选择器”。
/* 有必填字段为空的表单 */
form:has(input:required:invalid) .submit-btn {
opacity: 0.5;
pointer-events: none;
}
/* 包含图片的 Card:不同布局 */
.card:has(img) {
display: grid;
grid-template-columns: 150px 1fr;
}
.card:not(:has(img)) {
padding: 1.5rem;
}
/* 导航菜单打开时:禁用 body 滚动 */
body:has(.nav-menu[aria-expanded="true"]) {
overflow: hidden;
}styles.css
:has()自 2023 年起被所有现代浏览器支持。你今天可以在生产环境中使用它,无需 polyfills。
锚点定位:无 JavaScript 的工具提示和弹出框
在锚点定位之前,将工具提示相对于其触发器放置需要用 JavaScript 计算位置。现在不需要了:
/* 声明锚点 */
.btn-trigger {
anchor-name: --mi-boton;
}
/* 相对于锚点定位工具提示 */
.tooltip {
position: absolute;
position-anchor: --mi-boton;
bottom: calc(anchor(top) + 8px);
left: anchor(center);
transform: translateX(-50%);
/* 如果放不下则自动翻转 */
position-try-fallbacks: flip-block;
}tooltip.css
<button class="btn-trigger" popovertarget="tip">Hover me</button>
<div id="tip" class="tooltip" popover>
这个工具提示自己定位,无需 JS。
</div>tooltip.html
position-try-fallbacks:声明式碰撞逻辑
.tooltip {
position-try-fallbacks:
flip-block,
/* 如果下方放不下则尝试上方 */ flip-inline,
/* 如果右方放不下则尝试左方 */ flip-start; /* 组合两者 */
}tooltip.css
支持情况如何?
| 功能 | Chrome | Firefox | Safari |
|---|---|---|---|
| 容器查询 | 105+ ✓ | 110+ ✓ | 16+ ✓ |
:has() | 105+ ✓ | 121+ ✓ | 15.4+ ✓ |
| 锚点定位 | 125+ ✓ | 131+ ✓ | 18+ ✓ |
到 2026 年,根据当前的浏览器分布,你可以对大多数项目在生产环境中使用这三个功能。只有当你的受众包含非常老的浏览器时才考虑 polyfills。
今天的 CSS 是声明式的和表达性的
CSS 的静默革命不是 Grid 也不是 Flexbox。是思维模式的转变:浏览器推理约束,你声明期望的结果。容器查询、:has() 和锚点定位是这种范式的巅峰。