图标组件必须定义为独立 Block ui-icon,不得依附文字容器命名;复用场景下需隔离样式与行为,通过语义化类名、CSS 变量和基础布局规范保障可维护性与主题响应能力。

图标组件必须独立为 Block,不能依附文字容器命名
图标只要在两个以上上下文复用(比如按钮里、表单项里、弹窗标题里都出现),就必须定义为独立 ui-icon,而不是写成 btn__icon 或 form-item__icon。否则后续要单独控制图标颜色、动画或点击行为时,只能靠 JS 拼 class 或加内联样式,破坏封装性。
常见错误现象:form-item__icon--error 看似合理,但一旦这个图标也要用在 notification-banner 里,就得复制样式或加全局覆盖。
- 块名用语义+上下文,如项目叫「dash」,就用
ui-icon,不用泛泛的icon或svg-icon - 禁止全局类名如
.icon-user——它无法隔离、不可预测、极易被其他样式覆盖 - 只有图标完全绑定单一组件且永不复用时(例如加载中旋转图标永远只出现在某个按钮内部),才考虑降级为
btn__icon,但仍需确保它不对外暴露交互接口
文字容器与图标并列时,各自 Block 平级组合
当一个按钮同时含文字和图标,结构上应是两个独立 Block 并列,而非嵌套:用 btn + ui-icon,不是 btn__icon。它们通过 DOM 顺序和 CSS 布局协同,不靠 BEM 层级耦合。
使用场景:React 中你可能写 <Button icon="search">搜索</Button>,渲染结果应为:
立即学习“前端免费学习笔记(深入)”;
<button class="btn btn--primary"> <span class="ui-icon ui-icon--search"></span> <span class="btn__text">搜索</span> </button>
-
btn__text是btn的元素,只负责按钮内的文字样式,不承担图标职责 -
ui-icon自身控制尺寸、颜色、旋转等,通过 CSS 变量统一响应主题切换 - 避免
btn__icon和btn__text在同一层级下“竞争”对齐逻辑,比如 vertical-align 冲突
混排对齐问题必须由 Block 自身解决,不靠修饰符临时补救
图标和文字高度不一致、基线偏移、行高撑开等问题,根源常在于没给 ui-icon 显式设 font-size 和 vertical-align,而是指望修饰符去“修”。这违反 BEM 原则——修饰符只表达状态,不承担布局修复职责。
错误做法:ui-icon--align-top 里写 vertical-align: top,结果不同容器里要反复叠加多个对齐修饰符。
-
ui-icon基础类必须设:font-size: 1rem; line-height: 1; vertical-align: -0.125em;(-0.125em 是多数图标字体视觉基线经验值) - 尺寸变体用
ui-icon--sm/ui-icon--lg,仅调font-size,保持line-height: 1不变,避免撑高容器 - 旋转修饰符
ui-icon--rotate必须带display: inline-block,因为图标字体本质是inline元素,transform对它默认不生效
状态修饰符必须绑定到 Block 本身,且只表达业务含义
图标的状态(如成功、错误、禁用)应由 ui-icon 自己承载,而不是让父容器(如 btn)代为声明。否则状态逻辑分散,换主题或改交互时难以收敛。
反模式:btn--disabled 里用后代选择器强制改 btn__icon 颜色,或者写 btn__icon--disabled。
- 正确方式:JS 根据业务状态,给图标节点直接加
ui-icon--success或ui-icon--disabled - 每个修饰符只映射一个 CSS 变量,如
.ui-icon--success { color: var(--color-success); },不写死色号 - 禁止
ui-icon--red或ui-icon--16px这类视觉描述型修饰符——换主题就得全局搜替换,且无法响应式
btn__icon,你就默认它永远活在按钮里;而把它升格为 ui-icon,就等于承诺它能独立存在、可配置、可测试——这个边界意识,比语法本身更重要。


















