原生CSS不支持媒体查询嵌套,但通过PostCSS插件(如postcss-nested)可将.card { @media (max-width: 768px) { ... } }转译为标准CSS;Chrome 119+等新浏览器支持@nest语法,但需显式声明且&必须紧贴最左;纯<style>标签中直接写会报错。

媒体查询不能真正嵌套,但现代 CSS 支持嵌套语法中的 @media 规则
原生 CSS 本身不支持嵌套(比如在 .card 里直接写 @media),但借助 nest 语法(CSS Nesting Module Level 3)和主流构建工具(如 PostCSS、Vite、Webpack + postcss-nested),你可以写出视觉上嵌套的媒体查询。关键不是“能不能”,而是“用什么环境支持、怎么写才有效”。
如果你直接在浏览器中写 .card { @media (max-width: 768px) { ... } },会报错:Unexpected token '@' —— 因为原生 CSS 解析器根本不认识这种写法。
- ✅ 真正起作用的是构建时转换:PostCSS 插件(如
postcss-nested)会把嵌套结构展开成标准 CSS - ✅ 新版 Chrome/Firefox/Safari 已支持
nest语法(需开启实验性功能或搭配构建流程) - ❌ 不要指望纯 HTML +
<style>标签里写嵌套媒体查询能运行
postcss-nested 中的嵌套媒体查询写法
这是目前最通用、兼容性最好的方案,尤其适合 Vue/React 项目或使用 Vite 的前端工程。
示例:
立即学习“前端免费学习笔记(深入)”;
.card {
padding: 1rem;
@media (max-width: 768px) {
padding: 0.5rem;
&__title {
font-size: 1.1rem;
}
}
@media (prefers-reduced-motion: reduce) {
animation: none;
}
}
注意几点:
-
&表示父选择器,&__title展开后是.card__title,不是.card @media ... .card__title - 每个
@media块必须独立缩进,不能跨行混写;否则postcss-nested会解析失败 - 不支持在
@media内再嵌套另一个@media(即“媒体查询套媒体查询”),会报错或被忽略 - 如果用了
postcss-preset-env,它默认包含postcss-nested,无需额外安装
使用 nest 关键字显式声明嵌套(CSS Nesting Level 3)
这是 W3C 正式标准的一部分,Chrome 119+、Safari 17.2+、Firefox 124+ 已部分支持,但需要明确启用嵌套上下文。
正确写法必须带 nest:
.card {
nest: & {
@media (max-width: 768px) {
padding: 0.5rem;
}
};
}
常见误区:
- 漏掉
nest: & { ... };—— 浏览器直接忽略整个块 - 误写成
nest { ... }(缺少&)—— 语法错误 - 以为
nest能替代所有嵌套场景:它只处理选择器层级,不处理@supports或@layer的嵌套逻辑 - 服务端渲染(SSR)或旧版 Node.js 环境下,CSS 运行时无法执行
nest,必须走构建时转换
为什么别用 SCSS 的嵌套媒体查询直接上线
SCSS 允许写 .card { @media { ... } },但它生成的是静态 CSS,和原生嵌套无关。问题在于:SCSS 编译结果不可逆,且容易掩盖响应式逻辑的可维护性问题。
例如这个 SCSS:
.card {
@media (max-width: 768px) {
width: 100%;
.card__body { padding: 0.25rem; }
}
}
编译后变成:
@media (max-width: 768px) {
.card { width: 100%; }
.card .card__body { padding: 0.25rem; }
}
看起来没问题,但隐患是:
- 当多个组件都用相同断点时,CSS 文件里会重复出现同一段
@media,增加体积 - 无法利用现代 CSS 的
@layer控制层叠顺序,调试时难以定位样式来源 - 如果未来想迁移到 CSS-in-JS 或原子化方案,SCSS 嵌套结构反而成了重构负担
真正在意长期维护,就该用构建时支持的 postcss-nested,而不是依赖预处理器黑盒输出。


















