图标不能作为独立block,必须依附于功能组件(如btn__icon),因其无交互逻辑、易致样式污染、主题无法隔离,且违反bem层级契约。

不能单独定义 icon 块,必须绑定到具体功能组件下,否则类名会失效、冲突、不可维护。
为什么 icon 不能作为 Block 使用
图标本身不是独立功能单元——它没有交互逻辑、不承载业务语义,强行设为 icon Block 会导致样式全局污染、跨组件覆盖、主题无法隔离。比如你写 .icon--error,它可能意外影响 header__icon--error 或 form__icon--error 的颜色继承;PurgeCSS 还可能删掉动态添加的 icon--loading 类,因为 HTML 中没提前出现。
真实项目中,图标总是依附于某个上下文:btn__icon、user-card__avatar、nav-item__icon。BEM 要求修饰符必须挂载在有明确归属的 Block 或 Element 上,而不是裸奔的 icon。
- 禁止:
<i class="icon icon--24 icon--primary"></i> - 正确:
<button class="btn"><i class="btn__icon btn__icon--24 btn__icon--success"></i>提交</button> - 基础类
btn__icon必须声明display: inline-block、font-size和font-family(字体图标)或width/height(SVG)
btn__icon--rotate 不生效的常见原因和修复
直接加 transform: rotate() 没反应,大概率是因为图标元素是 inline,而 CSS transform 对纯内联元素默认不触发重排。这不是 BEM 命名问题,是渲染行为缺失。
- 错误写法:
.btn__icon--rotate { transform: rotate(90deg); }(无display声明,无效) - 正确写法:
.btn__icon--rotate { display: inline-block; transform: rotate(90deg); } - 更稳妥做法:在基础类
btn__icon就统一设display: inline-block和vertical-align: -0.125em,所有修饰符只管状态,不重复布局声明 - 若用 SVG,确保
<path></path>使用fill="currentColor",并让.btn__icon--error只改color,不碰font-size或width
尺寸、颜色、状态修饰符必须正交分离
一个修饰符只表达一个维度:尺寸是尺寸,颜色是颜色,加载状态是状态。混写如 btn__icon--24-error-loading 破坏可组合性,也违背 BEM 修饰符单一职责原则。
- 尺寸类:
btn__icon--sm、btn__icon--lg—— 控制font-size或width/height,不改颜色或动画 - 颜色类:
btn__icon--primary、btn__icon--danger—— 只设color/fill,基于设计系统语义,不用red、blue这类字面值 - 状态类:
btn__icon--loading、btn__icon--success—— 只负责旋转动画、路径切换或 visibility,不控制尺寸或主题色 - HTML 中可叠加:
class="btn__icon btn__icon--sm btn__icon--danger btn__icon--loading" - CSS 中必须分别定义规则,避免互相覆盖(例如两个修饰符都写
font-size,后声明的会生效)
SVG 图标在 BEM 下如何真正响应父级状态
内联 SVG 容易被父级 font-size 放大、被 color 隐式影响,但又不能靠 JS 动态改 fill——BEM 要求样式由类名驱动,而非运行时操作 DOM。
- 基础类
btn__icon必须显式设font-size: 1rem(防继承放大),并用color: currentColor作为兜底 - 所有
<path></path>必须写fill="currentColor",禁用硬编码fill="#333" - 颜色修饰符如
.btn__icon--primary只需写color: var(--color-primary),其余交给继承 - 切换形态(如箭头展开/收起)不要用
display: none控制多个<path></path>,而是用<use href="#icon-chevron-down"></use>并 JS 替换href值
最容易被忽略的一点:BEM 的 -- 和 __ 是契约,不是装饰。写成 btn__icon--rotate 是对的,写成 btn--icon-rotate 或 btn-icon--rotate 就破坏了层级归属,后续任何工具链或团队协作都会出问题。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











