BEM 修饰符不能嵌入断点标识(如 --mobile、--hidden@lg),因其仅为语义钩子,响应行为须由独立 @media 规则控制;应使用语义化命名(如 --hidden-below-md)并统一断点变量收口至 _breakpoints.scss。

不能在 BEM 修饰符类名里塞断点标识(比如 --mobile、--hidden@lg),浏览器根本不识别,这类写法等于给类名加了无意义注释。
为什么 --mobile 这类修饰符名会失效
修饰符是语义钩子,不是媒体查询开关。写 card--mobile 或 nav--fixed@sm,CSS 引擎只当它是普通字符串,不会触发任何响应行为。真正起作用的是 @media 规则本身。
- 类名中嵌入断点值(如
@md)违反 BEM “修饰符只表达状态、不表达条件”的原则 - 重构断点数值时,得同步改 HTML、JS、CSS 三处,漏一处就出 bug
- 不同组件对
sm理解可能不一致:有的指640px,有的指768px,协作成本飙升 - 服务端渲染(SSR)无法获取视口宽度,JS 动态加类会导致 FOUC 或 layout shift
正确写法:语义化修饰符 + 外部 @media 包裹
修饰符负责说“我要什么状态”,@media 负责说“这个状态在什么条件下生效”。两者必须解耦。
- 用动词 + 范围结构命名:如
nav-menu--hidden-below-md、card--stacked-above-lg - 所有断点数值统一收口到
_breakpoints.scss,例如:$bp-md: 768px - CSS 中必须显式用媒体查询包裹修饰符规则:
@media (max-width: 767px) {
.nav-menu--hidden-below-md {
display: none;
}
}
- HTML 只需静态写:
- React 中用状态控制,而非拼接字符串:
clsx('nav-menu', isHidden && 'nav-menu--hidden-below-md')
React + CSS Modules 场景下最容易踩的坑
很多人以为组件自己管响应式更灵活,结果断点逻辑散落各处,后期根本没法全局调控。
- 禁止字符串拼接类名:
className={`button button--${size}@${breakpoint}`❌ - 禁止硬编码断点修饰符:
className="card card--mobile"❌ - 禁止在组件样式文件里直接写
@media,必须全部收口到_breakpoints.scss - ESLint 必须启用自定义规则拦截非语义类名拼接
- JS 层不该监听
resize,应优先用matchMedia做精准匹配
媒体查询写法必须统一,否则样式不可预测
混用 max-width 和 min-width 是最隐蔽的坑。比如同时存在 @media (max-width: 768px) 和 @media (min-width: 768px),在精确 768px 宽度下两者都命中,最终生效的是源码顺序靠后的规则——这完全不可控。
- 全项目推荐统一用
min-width,断点设为768px、992px、1200px这类逻辑宽度 - 确保
已声明,否则移动端永远按桌面宽度渲染 -
@media条件中不能用 CSS 变量:@media (min-width: var(--bp-md))是无效语法 - 所有
@media块必须放在样式文件末尾,且只包裹修饰符声明,不混入基础 Block 样式
最常被忽略的一点:媒体查询写法必须统一,且所有断点变量必须收口到单一文件——这不是风格偏好,而是避免样式覆盖冲突的底线。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











