可二次定制的bem实践要求修饰符仅声明css变量、block命名脱离上下文、element单层、modifier绑定实体且可叠加、目录与block一一对应。

修饰符只设变量,不写具体样式
直接在 .button--primary 里写 background: #007bff 是最常见错误——这会让后续主题定制、运行时切换、CSS-in-JS 注入全部失效。真正可二次定制的写法,是让修饰符只负责“开关”或“注入变量”,把样式逻辑收口到基础块规则中。
-
.button--primary应只声明:--button-bg: #007bff; --button-color: #fff; -
.button__label内部统一用:color: var(--button-color); - 禁止在修饰符类中出现
padding、font-size、border等具体值 - 若需覆盖第三方库(如 Element Plus),优先用 wrapper 类 + CSS 变量,而非硬写
!important
Block 命名必须脱离上下文和视觉描述
写 .header-search 或 .blue-card 看似直观,但会锁死复用路径:前者无法用在侧边栏搜索,后者换色就得重命名。支持二次定制的前提,是 Block 名能脱离位置、颜色、尺寸等临时属性独立存在。
- 合法 Block 名:
search-form、card、product-grid - 非法 Block 名:
top-header-search、blue-card、big-button - Element 必须严格单层:
search-form__input✅,search-form__wrapper__field❌ - 所有 Block 根节点应预留
:host或:root可覆盖的变量入口,比如--search-form-input-padding
Modifier 必须绑定到具体实体,且可叠加
写 .button--loading--disabled 没问题,但前提是这两个修饰符彼此无依赖、不冲突、权重一致。很多项目卡在这里:一个修饰符重置了 pointer-events,另一个又试图改 opacity,结果样式打架。
- 每个 Modifier 必须作用于明确目标:
.button__trigger--disabled(禁用触发区)、.button__spinner--visible(显示加载动画) - 禁止跨级修饰:
.button--primary__label--uppercase违反 BEM 扁平原则,也破坏选择器可预测性 - 布尔型 Modifier(如
--disabled)只靠类存在生效,不带值;键值型(如--size-large)值必须语义化,不用数字或单位 - 用
stylelint-selector-bem-pattern强制校验,比人工 review 更可靠
目录结构必须与 Block 一一对应
组件文件夹不是为了“好看”,而是让开发者一眼看出:这个 Block 是否已存在、能否直接复用、修改后会影响哪些页面。目录错位,等于契约失效。
- 正确结构:
/components/search-form/search-form.css(只含.search-form及其 __ / -- 类) - 禁止把
search-form__input的样式拆到/components/input/下——它不是独立 Block,只是 search-form 的一部分 - 若真需复用输入逻辑,应抽离为
input-fieldBlock,再由search-form组合使用 - 所有 Modifier 对应的变量定义,应集中放在 Block 根 CSS 文件顶部,方便下游直接覆盖
BEM 不是让类名变长,而是让每个类名都承担明确职责。真正难的不是命名规则,而是每次加新修饰符前,想清楚它是否真的需要独立存在、能否被变量接管、会不会和其他状态叠加失效。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











