媒体查询断点不能写入BEM类名,必须统一收口到_breakpoints.scss中管理;修饰符应采用语义化命名如nav-menu--hidden-below-md,并在CSS中用@media显式包裹,避免硬编码和JS动态控制。

媒体查询断点不能塞进 BEM 类名里,比如 card--hidden@md 或 nav--fixed-sm,这类写法浏览器根本不认,也不符合 BEM 原则——修饰符只表达状态意图,不负责“何时生效”。
为什么类名里写 @md、--sm 会失效
浏览器解析 CSS 时,card--hidden@md 就是个普通字符串,和 card--hiddenxyz 没区别。真正控制响应行为的是 @media 规则本身,不是类名里的符号或后缀。常见后果包括:
- 写了
header--sticky@lg,但小屏没 sticky,因为没配对应的@media (min-width: ...) - 多个组件都用
--mobile,一处用max-width: 768px,另一处用max-width: 640px,样式互相覆盖且难以排查 - 重构断点值(比如从 768px 改成 744px),得同步改 HTML、JS、CSS 三处,漏一个就出 bug
断点数值必须统一收口到 _breakpoints.scss
所有断点值禁止硬编码在类名、JS 字符串或媒体查询中。统一定义在 _breakpoints.scss,例如:
$bp-xs: 480px;<br>$bp-sm: 640px;<br>$bp-md: 768px;<br>$bp-lg: 1024px;<br>$bp-xl: 1280px;
这样改一处,全项目生效;工具链(如 stylelint、VS Code 插件)也能识别和跳转。如果用 CSS 自定义属性方案,也需同样集中管理,避免散落在各组件文件里。
修饰符命名要用语义化动词 + 范围结构
修饰符名要让人一眼看懂“它想干什么”,而不是“它在哪个设备上起作用”。推荐格式:block--{verb}-{range},例如:
-
nav-menu--hidden-below-md✅ 表达“在中屏以下隐藏”,不绑定设备 -
card--stacked-above-lg✅ 表达“大屏以上堆叠”,意图清晰 -
card--mobile❌ 模糊:“mobile” 是指仅显示?仅隐藏?还是样式变小? -
card--sm❌ “sm” 指尺寸、状态、还是断点?团队理解成本高
对应 CSS 必须显式包裹在媒体查询中:
@media (max-width: $bp-md - 1) {<br> .nav-menu--hidden-below-md { display: none; }<br>}
React + CSS Modules 场景下最容易踩的坑
这类组合最容易把断点逻辑写散,导致后期无法全局调控。典型错误包括:
- 在 JSX 中硬拼类名:
className={`card card--${size}@${breakpoint}`❌ - 用 JS 监听
resize动态加--mobile类 ❌ —— SSR 不一致、FOUC、节流难控 - 在组件样式文件里直接写
@media (max-width: 768px)❌ —— 断点规则分散,无法统一维护
正确做法是:HTML 写静态语义类名,JS 只控制是否启用该修饰符(如用 clsx('card', isStacked && 'card--stacked-above-lg')),而所有 @media 块统一收口到 _breakpoints.scss 或全局媒体查询入口文件。
最常被忽略的一点是:@media 规则的组织顺序。混用 max-width 和 min-width 在临界宽度(如恰好 768px)会导致不可预测的层叠结果——必须统一采用“最小断点向上覆盖”策略,比如先写 (max-width: 767px),再写 (min-width: 768px),最后 (min-width: 1024px),才能确保行为可推演。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











