bem 修饰符不能包含断点标识(如 --mobile、--sm),必须仅表达语义状态;响应式逻辑须由 @media 显式控制,修饰符命名应为“动词+范围”结构(如 --hidden-below-md),且断点需统一定义与管理。

直接说结论:BEM 修饰符里不能塞断点标识(如 --mobile、--sm、--hidden@md),所有响应式逻辑必须由 @media 规则显式控制,修饰符只表达语义状态。
为什么 --mobile 这类修饰符名是错的
这类命名看似直观,实则破坏 BEM 的核心原则——修饰符应描述「组件处于什么状态」,而不是「在什么条件下生效」。浏览器根本不会识别 @md 或 --sm,它们只是普通字符串,和 CSS 规则完全无关。
-
.card--mobile不明确:是“仅在手机显示”,还是“在手机上隐藏”?协作时容易误用 - 断点值一改(比如从
768px改成744px),就得同步改三处:HTML 类名、JS 控制逻辑、CSS 文件里的@media——漏一就出 bug - 服务端渲染(SSR)时无法获取
window.innerWidth,JS 动态加类会和 SSR 输出不一致,引发 FOUC 或 layout shift -
.grid--mobile-2col这种混合命名不可枚举,后续加平板断点就变成--mobile-tablet-2col,维护爆炸
正确的修饰符命名方式:动词 + 范围结构
修饰符要表达意图,不是设备。范围(如 below-md)必须基于团队统一定义的断点变量(例如 Sass 中 $breakpoint-md: 768px),而非硬编码像素值。
- 推荐:
nav-menu--hidden-below-md、card--stacked-above-lg、list--compact-below-sm - 禁止:
nav-menu--mobile、card--stacked-mobile、button--lg@desktop - 所有断点定义必须收口到统一文件(如
_breakpoints.scss),禁止在组件样式里直接写@media - 对应 CSS 必须显式包裹在媒体查询中:
@media (max-width: 767px) { .nav-menu--hidden-below-md { display: none; } }
React + CSS Modules 场景下怎么安全切换类名
JS 层不拼接、不硬编码、不监听 resize。修饰符开关由 window.matchMedia 主动控制,且首次加载必须检查一次,避免闪屏。
- ✅ 正确:
clsx('nav-menu', isMobileView && 'nav-menu--hidden-below-md') - ❌ 禁止:
className={`nav-menu nav-menu--${size}@${breakpoint}`} - ❌ 禁止:
className="nav-menu nav-menu--mobile"(硬编码,无法随断点动态更新) - ESLint 必须启用自定义规则拦截非语义类名拼接,否则很快失控
最容易被忽略的细节
很多人以为写了 @media (max-width: 768px) { .card--stacked { flex-direction: column; } } 样式就自动生效,却忘了 HTML 里压根没加 card--stacked 这个类——媒体查询不会自动往 DOM 上塞类名。Modifier 是钩子,不是触发器。必须靠 JS 主动增删,或服务端根据 UA/viewport 宽度注入,否则移动端永远不响应。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











