
CSS 状态检测革命:样式查询与滚动状态查询实战指南
2026/4/3css
在 Web 开发中,我们一直依赖 JavaScript 来检测和响应 UI 状态变化。但随着 CSS 的演进,现在我们有了原生解决方案:样式查询和滚动状态查询。这两个特性让纯 CSS 状态检测成为现实,彻底改变了我们构建响应式 UI 的方式。
样式查询:基于 CSS 属性值的状态检测
它解决了什么问题?
传统上,当我们需要根据组件内部状态改变样式时,必须使用 JavaScript:
// 传统 JavaScript 方案
if (element.hasAttribute('data-active')) {
element.classList.add('active-style');
}这导致样式逻辑分散在 CSS 和 JavaScript 中,维护困难且性能不佳。样式查询的出现,让状态检测和样式响应统一在 CSS 中。
核心语法与用法
样式查询通过 @container style()检测 CSS 自定义属性的值变化:
/* 1. 定义状态变量 */
.alert {
--severity: info; /* 状态变量:info, warning, error */
container-type: normal; /* 必需:声明为容器 */
}
/* 2. 查询状态并响应 */
@container style(--severity: warning) {
.alert {
border-color: #ff9800;
background: #fff3e0;
}
/* 可以修改任意样式 */
.alert-icon::before { content: "⚠️"; }
}
@container style(--severity: error) {
.alert {
border-color: #f44336;
background: #ffebee;
}
.alert-icon::before { content: "❌"; }
}实战:主题切换系统
/* 定义主题变量 */
.theme-provider {
--theme: light;
--primary-color: #2196f3;
container-type: normal;
}
/* 暗色主题 */
@container style(--theme: dark) {
.theme-provider {
--primary-color: #90caf9;
background: #121212;
color: #ffffff;
}
.card {
background: #1e1e1e;
border: 1px solid #333;
}
}
/* 高对比度主题 */
@container style(--theme: high-contrast) {
.theme-provider {
--primary-color: #ffff00;
background: #000000;
color: #ffffff;
}
.card {
border: 3px solid yellow;
}
}
/* 应用主题色 */
.button {
background: var(--primary-color);
color: white;
}组合多个状态查询
.dialog {
--state: closed; /* closed, open, minimized */
--priority: normal; /* normal, important */
container-type: normal;
}
/* 打开的重要对话框 */
@container style(--state: open) and style(--priority: important) {
.dialog {
box-shadow: 0 0 0 3px #f44336;
z-index: 9999;
}
.dialog::after {
content: "重要!";
color: #f44336;
}
}
/* 最小化的对话框 */
@container style(--state: minimized) {
.dialog {
width: 60px;
height: 60px;
overflow: hidden;
}
.dialog-content { display: none; }
}动态改变状态
<!-- HTML -->
<button onclick="toggleSeverity()">切换状态</button>
<div class="alert" id="myAlert">这是一条消息</div>
<script>
function toggleSeverity() {
const alert = document.getElementById('myAlert');
const current = alert.style.getPropertyValue('--severity') || 'info';
const next = current === 'info' ? 'warning' :
current === 'warning' ? 'error' : 'info';
alert.style.setProperty('--severity', next);
}
</script>滚动状态查询:专门检测滚动和粘滞状态
它解决了什么问题?
检测滚动状态(如粘性导航是否粘住)一直是前端难题:
// 传统的 JavaScript 方案
window.addEventListener('scroll', () => {
const rect = element.getBoundingClientRect();
if (rect.top <= 0) {
element.classList.add('sticky');
} else {
element.classList.remove('sticky');
}
});这种方法有性能问题(频繁触发滚动事件)和时序问题(可能不同步)。滚动状态查询让浏览器原生处理这些检测。
核心语法与用法
/* 1. 声明滚动状态容器 */
.sticky-header {
position: sticky;
top: 0;
container-type: scroll-state; /* 关键:启用滚动状态查询 */
}
/* 2. 检测粘滞状态 */
@container scroll-state(stuck: top) {
.sticky-header {
/* 粘在顶部时的样式 */
background: rgba(255, 255, 255, 0.95);
backdrop-filter: blur(10px);
box-shadow: 0 4px 20px rgba(0, 0, 0, 0.1);
}
/* 可以添加状态指示器 */
.sticky-header::after {
content: "已固定";
color: #666;
}
}
/* 3. 检测未粘滞状态 */
@container scroll-state(stuck: none) {
.sticky-header {
background: transparent;
box-shadow: none;
}
}实战:智能粘性侧边栏
.sidebar {
position: sticky;
top: 20px;
container-type: scroll-state;
height: fit-content;
transition: all 0.3s ease;
}
/* 粘在顶部 */
@container scroll-state(stuck: top) {
.sidebar {
top: 0;
padding-top: 20px;
max-height: 100vh;
overflow-y: auto;
}
/* 添加返回顶部按钮 */
.sidebar::before {
content: "回到顶部";
display: block;
padding: 10px;
background: #f5f5f5;
cursor: pointer;
}
}
/* 粘在底部 */
@container scroll-state(stuck: bottom) {
.sidebar {
box-shadow: 0 -2px 10px rgba(0,0,0,0.1);
}
}
/* 接近边界时提示 */
@container scroll-state(stuck-proximity: top < 50px) {
.sidebar {
border-top: 2px solid #ff9800;
}
.sidebar::after {
content: "接近顶部";
color: #ff9800;
}
}检测滚动方向和位置
.scroll-aware-element {
container-type: scroll-state;
position: sticky;
top: 0;
transition: transform 0.3s ease;
}
/* 向上滚动时显示 */
@container scroll-state(scrolling: up) {
.scroll-aware-element {
transform: translateY(0);
opacity: 1;
}
}
/* 向下滚动时隐藏 */
@container scroll-state(scrolling: down) {
.scroll-aware-element {
transform: translateY(-100%);
opacity: 0;
}
}
/* 检测在视口中的可见比例 */
@container scroll-state(visibility: 0% to 30%) {
.scroll-aware-element {
opacity: 0.3;
}
}
@container scroll-state(visibility: 30% to 70%) {
.scroll-aware-element {
opacity: 0.7;
}
}
@container scroll-state(visibility: 70% to 100%) {
.scroll-aware-element {
opacity: 1;
}
}实战:阅读进度指示器
.progress-tracker {
container-type: scroll-state;
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 3px;
background: #e0e0e0;
z-index: 1000;
}
/* 根据滚动进度改变颜色 */
@container scroll-state(visibility: 0% to 25%) {
.progress-tracker::before {
content: "";
display: block;
height: 100%;
width: var(--scroll-progress);
background: #4caf50; /* 绿色:开始 */
}
}
@container scroll-state(visibility: 25% to 75%) {
.progress-tracker::before {
background: #2196f3; /* 蓝色:中间 */
}
}
@container scroll-state(visibility: 75% to 100%) {
.progress-tracker::before {
background: #f44336; /* 红色:接近完成 */
}
}
/* 接近底部时提示 */
@container scroll-state(stuck-proximity: bottom < 100px) {
.progress-tracker::after {
content: "接近底部";
position: absolute;
right: 20px;
top: 10px;
background: #333;
color: white;
padding: 5px 10px;
border-radius: 4px;
}
}组合使用:样式查询 + 滚动状态查询
真正的强大之处在于组合使用这两种技术:
.smart-navbar {
--variant: normal; /* normal, transparent, solid */
position: sticky;
top: 0;
container-type: scroll-state style;
}
/* 透明变体 + 粘滞状态 */
@container scroll-state(stuck: top) and style(--variant: transparent) {
.smart-navbar {
background: rgba(255, 255, 255, 0.95);
backdrop-filter: blur(10px);
}
/* 滚动时改变链接颜色 */
.nav-link { color: #333; }
}
/* 实心变体 + 向上滚动 */
@container scroll-state(scrolling: up) and style(--variant: solid) {
.smart-navbar {
transform: translateY(0);
box-shadow: 0 2px 20px rgba(0,0,0,0.1);
}
}
/* 实心变体 + 向下滚动 */
@container scroll-state(scrolling: down) and style(--variant: solid) {
.smart-navbar {
transform: translateY(-100%);
}
}浏览器支持与渐进增强
当前浏览器支持情况:
- 样式查询:Chrome 111+,Edge 111+,其他浏览器跟进中
- 滚动状态查询:Chrome 133+,Edge 133+,最新特性
渐进增强策略
/* 1. 基础样式(所有浏览器) */
.sticky-header {
position: sticky;
top: 0;
background: white;
}
/* 2. 检测滚动状态支持 */
@supports (container-type: scroll-state) {
.sticky-header {
container-type: scroll-state;
}
@container scroll-state(stuck: top) {
.sticky-header {
/* 现代浏览器的增强样式 */
backdrop-filter: blur(10px);
}
}
}
/* 3. 回退方案(旧浏览器) */
.sticky-header.stuck {
/* 通过 JavaScript 添加的类 */
box-shadow: 0 2px 10px rgba(0,0,0,0.1);
}
/* 4. 检测样式查询支持 */
@supports (container-type: style) {
.component {
container-type: style;
}
}总结:为什么这是 CSS 的革命?
样式查询的核心价值:
- 状态与样式统一:状态逻辑不再分散在 JavaScript 和 CSS 中
- 性能优化:浏览器原生优化状态检测,避免 JavaScript 性能开销
- 维护性提升:组件状态自包含,易于理解和调试
滚动状态查询的核心价值:
- 滚动性能革命:浏览器原生处理滚动检测,60fps 保证
- 开发体验简化:告别复杂的 IntersectionObserver 和滚动事件监听
- 时序问题解决:状态检测与渲染同步,避免视觉闪烁
最佳实践建议:
- 语义化状态名:使用
--state-前缀,如--state-active、--state-visible - 渐进增强:始终为不支持新特性的浏览器提供回退
- 组合使用:样式查询定义业务状态,滚动状态查询处理滚动行为
- 性能优化:避免在状态查询中做昂贵操作,保持简单
这两种技术代表了 CSS 从样式描述语言向状态响应系统的转变。通过掌握它们,你可以创建更高效、更优雅的 Web 界面,同时减少对 JavaScript 的依赖。
现在就开始尝试:从简单的粘性头部或主题切换开始,体验纯 CSS 状态检测的强大能力。这不仅是技术的进步,更是开发范式的转变。

