bem修饰符不能含断点标识(如--sm、@md),因其违背“只表达状态、不表达条件”原则;正确做法是用语义化修饰符(如--stacked)配合外部@media规则统一控制生效条件。

媒体查询里不能直接写 BEM 修饰符的“生效逻辑”,修饰符本身只是类名,它是否起作用,取决于你是否在 HTML 中加了这个类,以及对应的 CSS 规则是否被媒体查询包裹生效。
修饰符类名不能包含断点关键词(如 --sm、@md)
像 .button--primary@md 或 .card--hidden-sm 这种写法看似直观,但实际是反模式:类名里塞断点信息,会让语义混乱、无法静态分析、破坏可预测性。浏览器不会识别 @ 或 -sm 的特殊含义,它只当普通字符串;更严重的是,这类命名会误导团队以为“加了这个类就能响应式”,而忽略真正的控制权在媒体查询规则上。
-
--sm、--mobile-only等后缀违反 BEM 修饰符应表达「状态/意图」而非「触发条件」的原则 - 一旦设计调整断点值(比如把
768px改成744px),所有含--sm的类名和使用处都要批量替换,不可维护 - 工具链(如 stylelint-selector-bem-pattern、clsx 类型推导)无法识别这种非标准修饰符格式,失去校验能力
正确做法:用语义化修饰符 + 外部 @media 包裹声明
修饰符负责说“我要什么状态”,@media 负责说“这个状态在什么条件下可见”。二者解耦,才能复用、测试、调试。
- 定义清晰意图的修饰符,如
.card--stacked(表示“堆叠布局”)、.nav--collapsed(表示“导航收起”) - 在 CSS 文件末尾统一组织媒体查询块,只在里面写这些修饰符的具体样式表现
- 确保基础 Block 规则(如
.card)始终存在,修饰符规则必须后置,避免层叠被覆盖
.card {
display: grid;
grid-template-columns: repeat(3, 1fr);
}
<p>.card--stacked {
/<em> 默认不生效,仅作类名钩子 </em>/
}</p><p>@media (max-width: 768px) {
.card--stacked {
grid-template-columns: 1fr;
}
}</p>
多个断点共用同一修饰符时,如何避免重复声明?
一个修饰符(如 .header--sticky)可能在桌面端生效,在平板端禁用,在手机端又启用——这不是修饰符的问题,是媒体查询组合逻辑的问题。不要试图用多个修饰符(--sticky-on-desktop、--sticky-on-mobile)来拆分,而应在一个修饰符下,用多段媒体查询精准控制。
- 优先按“最小断点向上覆盖”组织
@media,例如先写(max-width: 768px),再写(min-width: 769px),最后写(min-width: 1200px) - 避免在不同媒体查询块里重复写同一修饰符的相同属性(如都设
position: fixed),容易漏改 - 若某修饰符需在多个不连续断点生效,用逗号分隔的媒体查询:
@media (max-width: 480px), (min-width: 1024px)
最容易被忽略的细节:修饰符的层叠顺序与文件组织
BEM 不是写了类名就完事,CSS 层叠规则会直接影响修饰符是否生效。尤其在多人协作或 SCSS 拆分文件时,顺序错一点,--disabled 就可能被基础 .button 的 color 覆盖掉。
- 所有修饰符样式声明必须放在对应 Block 基础样式之后,不能穿插在中间
- 媒体查询块建议统一放在单个 SCSS 文件末尾,或独立的
_breakpoints.scss中,禁止分散在各组件文件里 - 禁止在修饰符内部再嵌套媒体查询(如 SCSS 中
&--large { @media {...} }),这会生成冗余选择器且破坏可读性
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











