bem 原则禁止用--mobile/--desktop等设备修饰符,修饰符应仅表达组件自身语义状态(如card--layout-stack),设备适配交由@media控制;命名须严格遵循块__元素--修饰符格式,状态类优先挂父容器(如is-sidebar-closed),确保块级隔离与样式可预测性。

移动端和桌面端状态不能用--mobile或--desktop修饰符
这类命名直接违反 BEM 原则:修饰符(--)只表达组件自身的意图状态(比如card--layout-stack),不承担设备类型判断。一旦把--mobile写进类名,你就等于让 CSS 类同时管三件事——环境(设备)、状态(当前布局意图)、样式(具体表现)。后续改断点、加小程序平台、换设计稿时,必须同步改 HTML 类名、CSS @media 规则、JS matchMedia 判断逻辑,漏一处就出 bug。
常见错误现象包括:
- 设计师说“小屏改成两列”,你得全局搜索替换
--mobile,再改对应 CSS 和 JS 绑定 - 构建工具(如
postcss-bem-linter)报错card__button--mobile不符合 BEM 语法(因为--mobile不是语义状态) - 轮播图在 WebView 中指示器点击失效,实际是
carousel-indicator这类非标准命名导致事件委托绑不到.carousel__indicator
应该用语义化修饰符当钩子,由@media驱动响应
真正该做的,是把“布局意图”抽成可预测、可复用的修饰符,再交由媒体查询控制表现。例如:card--layout-stack 表示“当前卡片采用堆叠布局”,它本身不带任何尺寸含义;@media (max-width: 768px) 再统一定义这个修饰符在小屏下的行为。
实操建议:
- 修饰符值必须可预测:
card--layout-stack✅,card--v2❌,card--ios-fix❌(后者说明你在用 CSS 修浏览器兼容性,该抽成@supports或 JS 检测) - JS 可通过
window.matchMedia动态增删该类,但类名本身不变,避免多处耦合 - 同一修饰符可在不同断点下有不同表现:
.card-grid--compact在桌面端设gap: 0.5rem,在移动端媒体查询里覆盖为gap: 0.25rem,无需新增--compact-mobile
carousel__indicator这类元素命名必须严格绑定容器块
移动端轮播的 dots 元素常被误写成dot、carousel-indicator 或 carousel__dot。这会导致事件委托失败、样式泄漏、构建工具拦截。
正确做法是:
- 指示器必须是轮播容器的子功能单元 → 类名只能是
carousel__indicator - 激活态用
carousel__indicator--active,不是carousel__indicator-active(后者破坏双下划线语法) - 所有触摸事件(
touchstart)应委托到.carousel__indicator上,命名不统一就绑不准 - 垂直轮播不能写成
carousel--vertical,而应新建独立块carousel-vertical,否则会混淆交互职责
状态类优先挂父容器,别直接操作子元素
比如侧边栏展开收起,不要用 .sidebar--open 直接控制宽度,而应把状态类加在父级容器上,如 。这是 BEM 社区广泛接受的 is- 前缀约定,明确表示“当前处于某种运行时状态”。
原因很实际:
- JS 未加载时页面不会显示异常宽度(避免 FOUC)
- 样式更易隔离:
.is-sidebar-closed .sidebar比.sidebar--closed更利于嵌套控制 - 响应式断点与元素层级解耦:不会出现
.sidebar__trigger--mobile这种把媒体逻辑塞进修饰符的写法
最易被忽略的一点:BEM 的核心不是三段式字符串拼接,而是块级隔离。移动端样式冲突往往隐蔽难查——iOS Safari 伪类不触发、DPR 下 font-size 失准、position: fixed 层级错乱,90% 都源于选择器耦合过深。.header__logo--large 必须永远只管自己,不能被 .card .logo 意外覆盖。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











