bem通过类名嵌入归属、角色、状态三重语义,使新人30秒内理解样式用途;块名须为业务词、文件名与块名严格一致、修饰符仅限可枚举状态、工具链需在保存时校验命名。

因为BEM把“这个样式属于谁、是什么、当前什么状态”三个问题直接塞进类名里,新人打开一个CSS文件,30秒内就能判断出它负责什么、能怎么用、有哪些合法状态变体——不需要查HTML、不翻Git历史、不靠同事口述。
看到 user-card__avatar--loading 就比看到 .avatar 更快理解
人脑处理无上下文字符串成本很高。.avatar 出现在审查元素里,得跳转HTML才能知道它属于哪个模块;而user-card__avatar--loading 自带三重语义:归属(user-card)、角色(avatar)、状态(loading)。这种信息密度让新人不用猜。
- 常见错误现象:
card-title和product-card__title并存,新人改了前者却发现购物车页没生效——因为实际生效的是后者,但没人告诉过他“title”到底属于哪个块 - 块名必须是业务词,禁用
big-box、left-panel这类视觉描述 - 元素名不能脱离块独立存在:
__avatar合法,.avatar或__image都不行
user-card.css 文件名与块名严格一致,IDE搜索即见全部逻辑
每个BEM块对应一个独立CSS文件,且文件名与块名完全一致。例如button.css里只允许出现button、button__icon、button--primary等类名。这种硬性约束带来两个直接好处:
- 新人在IDE里按
user-card.css搜索,ctrl+click跳转即见全部样式逻辑,无须全局grep - 团队无需口头约定“按钮样式在
common.scss第127行”,文件系统本身就成了导航地图 - 禁止跨文件定义同一块的样式:比如
form.css里写user-card__footer是违规的
修饰符只表达可枚举的状态,不是尺寸或颜色值
BEM要求修饰符必须关联可触发的行为或明确的业务状态,而不是随意加的外观描述。这样新人在写classList.toggle()时,目标类名天然具备上下文,不会写出btn-red-big-hover这类无法维护的组合名。
-
user-card--compact✅(紧凑模式,由用户设置触发) -
user-card__avatar--loading✅(头像加载中,由JS控制class切换) -
user-card__avatar--small❌(--small是尺寸,不是稳定状态;响应式下可能失效) -
button--width-200px❌(把具体值塞进类名,换单位或加媒体查询就得新增一堆类)
工具链必须在保存时就报错,不能靠Code Review拦
靠人工Review拦不住拼写错误,必须让违规在保存时就暴露。BEM的解析逻辑完全依赖__和--作为唯一分隔符。写成user_name或card-element,stylelint、PostCSS插件、VS Code BEM Helper都会无法识别结构——正则匹配失败后直接跳过校验。
- 配置
stylelint-selector-bem-pattern,启用strict模式,注册所有合法块名如['user-card', 'search-form'] - 设
allowMultipleDashes: false,否则button--primary--loading不报错,而BEM明令禁止修饰符链式叠加 - VS Code安装 “BEM Helper”,输入
user-card回车自动补全user-card__和user-card-- - CI流程中跑
npx stylelint "**/*.css",把命名校验变成门禁
真正难的不是写对第一个 button__icon--disabled,而是坚持不让临时需求破坏这个映射关系——比如产品经理说“首页按钮要加个脉冲动画”,别把它塞进 home.css,而是去 button.css 里补 button--pulsing,哪怕只被用一次。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











