按钮组件根类名用btn,状态修饰符为btn--primary,内部图标为btn__icon;BEM通过块、元素、修饰符明确职责,避免语义与结构混淆,禁用跨块组合,双下划线表从属元素,双短横线表自身变体。

怎么用BEM给按钮组件写可维护的类名
直接说结论:按钮组件的根元素用 btn,修饰状态加 --primary,内部图标用 __icon,不嵌套多层、不依赖上下文。BEM不是为了“看起来规范”,而是让别人(包括三个月后的你)一眼看懂这个类名在组件里扮演什么角色。
常见错误是把语义和结构混在一起,比如写成 header-btn 或 user-card-button——这类名字一换场景就得重写,根本没法复用。
-
btn是块(Block),代表独立可复用的UI单元 -
btn--disabled是修饰符(Modifier),只描述当前状态,不带逻辑(比如不用btn--is-disabled) -
btn__text是元素(Element),必须依附于btn存在,不能单独使用 - 禁止跨块写组合类名,例如
btn user-avatar__btn是反模式,应该用 JavaScript 控制行为,CSS 只管视觉
BEM里双下划线和双短横线容易写反吗
非常容易,而且一旦写错,样式就失效或意外覆盖。核心区别就一条:双下划线 __ 连接的是「属于这个块的子节点」,双短横线 -- 是「这个块自身的变体」。
典型翻车现场:btn--icon 看起来像有图标的按钮,但其实是定义了一种叫“icon”的按钮类型;而真正要给按钮里的图标加样式,得写 btn__icon。前者是修饰符,后者是元素。
- 写成
btn--icon→ 浏览器会找 class="btn btn--icon" 的元素,但你可能只想改里面那个 - 写成
btn__icon--large→ 合法,表示“按钮内图标的大号变体”,修饰符可以叠加在元素上 - 不允许
btn__icon--primary和btn--primary__icon混用,后者语法无效,BEM 解析器直接忽略 - 构建工具如 PostCSS BEM 插件能帮你校验,但别依赖它——手写时盯住分隔符比什么都管用
CSS-in-JS 或 Tailwind 项目还要用 BEM 吗
要看团队协作成本。Tailwind 项目通常放弃 BEM 类名,因为原子类已解决命名问题;但如果你用 CSS Modules 或全局 .css 文件,BEM 依然是防止样式泄漏最轻量的方案。
关键不是“用不用”,而是“有没有明确的类名作用域”。比如 React 中一个 Button 组件,即使用了 CSS Modules,也建议导出 button、buttonIcon、buttonText 这样的变量名,本质上还是 BEM 思维——只是把 __ 换成了驼峰。
- 用
styled-components?可以保留 BEM 命名习惯,比如const Button = styled.button.attrs({ className: 'btn' }) - 用
tailwindcss+@apply?建议只对高频组合抽成@layer components { .btn { @apply px-4 py-2 rounded font-medium; } },别硬套btn__text这种结构 - 多人共用同一份 CSS 文件?BEM 几乎是刚需,否则很快会出现
.user-btn、.profile-button、.ctaBtn并存的混乱
为什么 BEM 类名越长,反而越不容易出错
因为长名字强制暴露了层级和职责。比如 search-form__input--error,光看名字就知道:这是 search-form 块里的 input 元素,当前处于 error 状态。它不会被误认为是全局输入框样式,也不会和表单提交按钮的样式冲突。
缩写或简写看似省事,实则埋雷。有人把 btn__icon 缩成 btn-i,结果半年后新加个 btn__image,全队没人记得 i 到底指 icon 还是 image。
- 长度不是问题,语义模糊才是——
btn-primary比btn--primary更短,但前者可能是全局主题色,后者才明确是按钮的一种状态 - 编辑器自动补全对 BEM 友好,VS Code 装 Auto Rename Tag 插件后,改
btn能顺带改掉所有btn__*和btn--* - 生产环境可通过构建工具压缩类名(如 cssnano 的
reduceIdents),开发阶段保持可读性更重要
真正难的不是写对 BEM,而是坚持不让业务逻辑侵入类名——比如不要出现 btn--for-payment,那是组件用途,不是视觉状态。这种边界一旦松动,整个命名体系就慢慢垮掉。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











