直接写媒体查询断点是维护噩梦,因全局替换易遗漏且 min/max 混用导致重叠;应使用 map 存储带单位的 em 断点、@content 注入样式、统一 min-width 向上覆盖实现解耦。

为什么直接写 @media (min-width: 768px) 是维护噩梦
改一个断点值,全项目 grep 替换,漏掉一处就导致某块布局在 iPad 上错位。更糟的是,@media (max-width: 1023px) 和 @media (min-width: 768px) 混用时,768–1023px 区间可能被两个规则同时命中,浏览器按后声明的覆盖,但你本意可能是独占生效——这时还得手动加 and (min-width: 768px),逻辑变重且易错。
@mixin respond-to($breakpoint) 必须配 $breakpoints map
不能用变量或 list 存断点:$md: 768px 或 (576px, 768px) 都会导致 @include respond-to("md") 失效或报 Invalid null operation。必须用键值对 map:
@$breakpoints: ( "sm": 40em, "md": 48em, "lg": 64em );
- 键名用缩写(
sm/md)而非设备名(tablet),语义稳定、协作成本低 - 值必须带单位(
48em,不是48),否则编译失败 - 单位优先选
em:适配缩放和动态根字号,48em≈ 768px @16px 基准
@content 不是可选语法糖,是嵌套能力的分水岭
没有 @content 的 mixin 只能返回字符串,你得自己拼样式块,难读又易出错。加上它,调用时大括号里的内容会被原样注入媒体查询内部:
@mixin respond-to($breakpoint) {
@if map-has-key($breakpoints, $breakpoint) {
@media (min-width: map-get($breakpoints, $breakpoint)) {
@content;
}
}
}
- 调用必须带大括号:
@include respond-to("md") { padding: 1.5rem; }✅;省略{}就失效 ❌ - 支持透传
&:hover、&::before,不破坏父选择器层级 - 不能在
@content外部访问调用作用域的局部变量——这是作用域隔离,不是 bug - 别在同一个
@content块里再嵌套另一个带@content的 mixin,会丢上下文
别封装 for-mobile-down 这类反向断点
写一堆 for-mobile-up、for-mobile-down、for-mobile-only 违反 DRY,且 max-width 和 min-width 混用极易触发重叠或遗漏。统一用 min-width 向上覆盖更可控:
- 默认层写桌面样式(无媒体查询)
- 移动端覆盖全交给
@include respond-to("sm")往上叠加 - 需要区间控制?用两个
respond-to组合,或额外写@mixin between($min, $max) - 如果项目已用 CSS
@container,就另建@mixin container-breakpoint,别让视口断点 mixin 承担容器逻辑
真正卡住人的从来不是写不出断点,而是改断点时不敢动、不敢删、不知道哪段样式实际生效——map + @content + 单向 min-width 这三层结构,把“数值”“查询逻辑”“样式注入”彻底解耦,改一处,全链路自动同步。










