Modifier必须紧贴所属Block或Element,不跨级、不传递、不继承;应语义化命名、独立书写、避免响应式断点混用。

Modifier类名必须紧贴Block或Element,不能跨级
很多人写 btn--primary 没问题,但一到嵌套就出错,比如在 card__header 里写 card__header--large 是对的,而写成 card--header-large 或 card__header__title--bold 就违反BEM语义——Modifier只修饰它直接所属的Block或Element,不传递、不继承、不跳级。
常见错误现象:Uncaught TypeError: Cannot read property 'classList' of null 虽然不是CSS报错,但JS常因类名不匹配导致元素查不到,根源常是Modifier命名混乱引发的选择器失效。
-
card__image--rounded✅(修饰card__image) -
card--featured__image❌(Modifier--featured错误地“挂”在Block上却试图影响子Element) -
form__input--error--disabled❌(多个Modifier连写,语义模糊且难以维护)
Modifier值推荐用语义化单词,而非样式描述
写 btn--small 看似直观,但“小”是尺寸结果,不是用户意图;换成 btn--compact 或 btn--icon-only 更能表达设计目的。一旦设计调整(比如“small”按钮实际变高了),类名就变成谎言。
使用场景差异明显:表单控件常用状态型Modifier(input--valid / input--invalid),而布局组件倾向意图型(sidebar--collapsed / sidebar--pinned)。
立即学习“前端免费学习笔记(深入)”;
- 避免:
text--14px、bg--#f0f0f0、flex--col - 推荐:
text--caption、bg--muted、stack--vertical - 性能影响:语义化命名不改变CSS体积,但显著降低团队沟通成本和重构风险
多个Modifier共存时,必须独立书写,禁止连缀或缩写
一个按钮同时需要“主要”和“加载中”状态,应写成 btn btn--primary btn--loading,而不是 btn--primary-loading。后者看似简洁,实则破坏BEM原子性,丧失组合灵活性,也阻碍CSS-in-JS或Tailwind式条件拼接。
容易踩的坑:用Sass/SCSS生成连缀类(如 @each $mod in $modifiers { .btn--#{$mod} { … } }),再手动拼出 btn--primary-loading ——这等于放弃BEM的可预测性。
- ✅ 正确组合:
<button class="btn btn--primary btn--disabled"> - ❌ 错误合并:
<button class="btn--primary-disabled"> - 兼容性注意:IE11及以下对多类名选择器支持完好,无需担心
Modifier不应用于响应式断点,那是Media Query的事
写 nav--mobile 或 table--sm 是典型误区。BEM Modifier描述的是组件的**固有状态或变体**,不是视口条件。响应式行为应通过媒体查询控制已有类名的样式,或配合JS切换类(如监听 resize 后加 nav--is-mobile),但这个类仍需符合状态语义,而非设备标签。
为什么这样做:把断点逻辑混入类名,会导致HTML随屏幕尺寸反复重写,违背关注点分离;也使组件无法被Storybook等工具正确预览不同状态。
- ❌ 错误:
header--tablet、grid--md - ✅ 正确:
header--has-breadcrumbs+ 在@media (max-width: 768px)中调整header__breadcrumb布局 - 额外提醒:Tailwind类如
md:hidden属于实用工具类体系,与BEM不冲突,但不应把它们当BEM Modifier用


















