学BEM要从具体组件入手,如button或card,用块(如user-card__submit)、元素(btn__icon)、修饰符(btn--primary)三类名一次跑通;块名须带业务语义,元素限直系,修饰符平级叠加,HTML必须显式体现BEM层级,嵌套组件应升格为独立Block。

别从“BEM是什么”开始学,先盯住一个能立刻上手的组件,比如 button 或 card,用它把块、元素、修饰符三类名字一次性跑通。
从一个按钮写起,而不是从概念背起
初学者最容易卡在“block该叫什么”,其实答案就藏在你正在写的组件里。不是想“我要命名一个块”,而是问:“这个按钮在页面里承担什么角色?”如果它出现在用户卡片里提交资料,就叫 user-card__submit;如果是全局操作栏里的主动作,就叫 action-bar__primary-btn。
- 块名必须带业务语义,
btn可以(行业通用缩写),button不行(和原生标签冲突) - 元素只写直系组成部分:
btn__icon✅,btn__icon__spinner❌(禁止三层) - 修饰符平级叠加:
btn--primary btn--large✅,btn--primary-large❌(后者无法单独开关尺寸)
HTML结构必须同步体现BEM层级
BEM不是CSS写法,是HTML+CSS协同契约。光写 .card__title 没用,HTML里必须同时出现 class="card" 和 class="card__title",否则这个元素就失去了上下文归属。
- 删掉
card类后,card__title还能独立存在吗?不能 → 它就是元素,必须共存 - 当前页的面包屑节点要加状态?必须写
breadcrumb__item--current作用于<li>,不能只加在<a>上 - 用 SCSS 时禁止写
.card { &__title { ... } }生成嵌套选择器——BEM 只认类名,不认 DOM 层级深度
遇到嵌套组件,立刻升格为独立 Block
当你发现某个 __element 本身还带加载态、空状态、响应式逻辑,比如 card__list 里还要渲染分页和骨架屏,说明它早就不只是“卡片列表”这个元素了,而是一个具备完整生命周期的模块。
立即学习“前端免费学习笔记(深入)”;
- 立刻停手,把它定义为新 Block:
card-list - 内部用
card-list__item、card-list--loading命名 - HTML 中显式嵌套:
<div class="card"><div class="card-list"></div></div> - 禁止在
card.css里写.card .card-list—— 这等于把两个模块的样式耦合在一起
真正难的不是记住双下划线和双短横,而是每次加一个类名前,都得确认它属于哪个 Block、能否脱离上下文复用、有没有被当成“视觉位置”而非“语义角色”来命名。这些判断没法靠查文档解决,只能在改三次样式、修两次 JS 查询、被同事 grep 出来问“这个类到底管谁”之后才真正长进脑子里。


















