根本原因不是less编译失败,而是最终css中缺失或结构非法的@media规则;必须用&显式绑定父选择器,避免悬空;变量需预定义数值,不可字符串插值;构建链路中css-loader、压缩工具等可能静默删除@media。

根本原因不是 Less 编译失败,而是最终生成的 CSS 里压根没有 @media 规则,或者规则结构非法导致浏览器直接忽略——你写的嵌套语法,90% 情况下没被正确展开成标准 CSS。
Less 媒体查询嵌套必须显式用 & 绑定父选择器
嵌套写法本身合法,但编译后是否有效,取决于 & 是否出现。没有它,@media 块会“悬空”,生成无选择器的规则,浏览器无视。
-
错误写法:
.nav { @media (max-width: 768px) { display: none; } }→ 编译出@media (max-width: 768px) { display: none; }(无选择器,无效) -
正确写法:
.nav { @media (max-width: 768px) { & { display: none; } } }→ 编译出@media (max-width: 768px) { .nav { display: none; } } - 深层嵌套时,
&只绑定最近一级父选择器,不能跨层引用;想打破层级,得用@at-root
@media 后面不能插值变量,只能引用预定义数值
Less 不允许把整个媒体查询条件当字符串变量塞进去,这种写法看似省事,实则编译直接报错或静默失效。
-
错误写法:
@mq-sm: ~"(max-width: 768px)"; @media @mq-sm { ... }→ 报Invalid CSS after "@media" -
正确写法:
@sm: 768px; @media (max-width: @sm) { ... } - 如需组合断点(比如
min-width+max-width),必须封装为 mixin:.media-between(@min, @max) { @media (min-width: @min) and (max-width: @max) { @content; } }
构建链路中 @media 被删或错位
Less 编译只是第一步,Webpack/Vite 构建流程可能把 @media 干掉——你看到的空或错乱,往往发生在后续环节。
-
css-loader的importLoaders配置不对,会导致它把 Less 编译后的@media当普通规则处理,提取时丢失结构 - 压缩工具(如
cssnano)默认开启discardDuplicates,可能误删“看起来重复”的媒体查询块 - PostCSS 插件(如
autoprefixer)必须作用于 Less 编译后的结果,而不是源.less文件;否则它根本看不到@media - 验证方法:打开最终产出的
.css文件,搜索@media,确认你要的那条规则是否完整存在、是否包裹在花括号内、内部是否有合法选择器
真机不生效但 DevTools 里看着正常
这不是 Less 的问题,是浏览器对非法 CSS 的宽容度差异。Chrome DevTools 模拟器有时会“帮忙修正”错误结构,而 Safari iOS、Android WebView 等原生渲染引擎直接丢弃整块。
- 典型表现:
.search-results { @media (max-width: 900px) { width: 100vw; } }编译出.search-results @media (max-width: 900px) { width: 100vw; }—— 这种结构非法,原生浏览器完全不认 - 检查最终 CSS:如果出现
.class @media或@media块里只有声明没选择器,说明源码写法错误或less-loader配置异常 - 移动端务必确认
<meta name="viewport">存在且位置正确(最顶部),否则视口宽度永远是 980px,@media (max-width: 768px)永远不触发
最容易被忽略的是构建链路中的静默截断——哪怕 @media 在 Less 源码里写得再对,只要 css-loader 或压缩插件配置不当,它就会在你没察觉的情况下从最终 CSS 里消失。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











