图标字体不能作为独立 Block,必须作为 Block 的 Element(如 btn__icon)存在,以确保样式隔离、伪元素精准控制、PurgeCSS 正确识别;修饰符需正交分离尺寸与状态,禁止嵌套,且应显式用 CSS 变量而非 currentColor 控制颜色。

图标字体不能单独定义 icon 块
直接写 .icon 或 .icon--user 是错的——BEM 要求 Block 必须是独立可复用的功能单元,而图标字体只是视觉符号,没有交互逻辑、不承载业务语义。一旦把它当 Block,就会导致:.icon--red 全局生效,意外覆盖 header__icon--red;CSS 特异性失控,!important 泛滥;主题色无法按组件隔离。
btn__icon 这类元素名才是合法入口
图标必须作为某个 Block 的 Element 存在,比如按钮是 btn,图标就是 btn__icon;用户卡片是 user-card,图标就是 user-card__avatar。这样做的好处是:
- 样式作用域被命名锁死,改
btn__icon不会影响nav__icon - 伪元素注入(如
::before)时,btn__icon::before可精准控制,不污染其他上下文 - PurgeCSS 等工具能识别真实使用路径,不会误删动态添加的
btn__icon--loading
btn__icon--error 修饰符要绑定到具体元素,不能写成 icon--error
颜色、状态这类外观变体必须依附于有明确上下文的 Element,而不是裸奔的全局类。实操中要注意:
-
btn__icon基础类必须声明display: inline-block和font-family: 'iconfont',否则字体图标不渲染 - 修饰符只改
color和fill,不碰font-size或vertical-align,避免干扰尺寸控制逻辑 - 若用伪元素插入图标,修饰符需同步作用于伪元素:
.btn__icon--error::before { color: var(--color-error); } - 禁止多个修饰符互相覆盖:不要在
btn__icon--loading里重复设color,它应只管动画,颜色由btn__icon--error或btn__icon--success单独负责
尺寸与状态修饰符必须正交,并列使用
别写 btn__icon--sm-loading 或 btn__icon--disabled-small——这违反 BEM 修饰符单一职责原则。尺寸是变体(variant),加载/禁用是状态(state),它们互不嵌套、可自由叠加:
- HTML 中最终是:
<i class="btn__icon btn__icon--sm btn__icon--loading"></i> - CSS 分开定义:
.btn__icon--sm { font-size: 16px; }和.btn__icon--loading { animation: spin 1s infinite; } - JS 控制时用布尔映射:
{ 'btn__icon--sm': size === 'sm', 'btn__icon--loading': isLoading }
真正容易被忽略的是:当图标通过伪元素实现时,currentcolor 会继承父级 color,但 SSR 渲染或第三方库 DOM 注入后,这个继承链可能断裂——所以更稳妥的做法是显式用 CSS 变量控制填充色,而非依赖继承。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











