@extend %xxx 在 @media 中一定失败,因为 sass 禁止跨指令块扩展,@extend 是编译期静态合并行为,而 @media 作用域隔离导致外部占位符无法安全注入。

@extend 在 @media 中报错,是因为 Sass 明确禁止跨指令块扩展 —— 你不能在 @media 里 @extend 外部定义的占位符(如 %ellipse-two-line),编译器会直接抛出 You may not @extend an outer selector from within @media。
为什么 @extend %xxx 在 @media 里一定失败
Sass 的 @extend 是编译期静态分析行为,它需要把被扩展的选择器和目标选择器“合并输出”。而 @media 是一个独立的 CSS 指令块,它的作用域与外部隔离。一旦 %ellipse-two-line 定义在 @media 外,Sass 就无法安全地把它注入到媒体查询内部的规则中 —— 这不是 bug,是设计限制。
- 错误写法:
@media (max-width: 700px) { .user-name { @extend %ellipse-two-line; } } - 即使
%ellipse-two-line存在且合法,只要不在同一@media块内定义,就必然报错 - 嵌套的
@media(比如在 mixin 里)也不能绕过该限制
替代方案:用 @mixin + @include 替代 @extend
@mixin 不依赖选择器合并,只做样式复用,天然支持任意上下文,包括 @media 内部。
- 把占位符逻辑改写为 mixin:
@mixin ellipse-two-line { display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; text-overflow: ellipsis; } - 在媒体查询中直接调用:
@media (max-width: 700px) { .user-name { margin: rem(10px) rem(8px) 0; font-size: rem(12px); line-height: 1.2; text-align: center; color: $chat-nav-status-off-line; @include ellipse-two-line; } } - 优势:无作用域限制、可传参(如行数)、生成代码更可控
如果必须保留 % 占位符,只能同块定义
极少数场景下你坚持用 %,唯一合法路径是把占位符声明移到 @media 块内部 —— 但它将只对该媒体查询生效,无法复用到其他断点或全局。
- 可行但受限的写法:
@media (max-width: 700px) { %ellipse-two-line-mobile { display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; } .user-name { @extend %ellipse-two-line-mobile; } } - 缺点:重复定义、维护成本高、不同断点间无法共享同一语义
- 注意:不能用
&在@media内扩展父级占位符,&在媒体查询中会展开完整嵌套路径,极易触发选择器爆炸
真正容易被忽略的是:很多人试图用 @at-root “逃出” @media 来绕过限制,但 @at-root 只能提级选择器,不能改变 @extend 的作用域规则 —— 它对这个报错完全无效。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











