BEM命名中steps__item--active与steps__item--finish须严格区分且不可混用;状态修饰符必须作用于元素级而非块级,子元素也应带对应状态类名(如steps__icon--finish),JS需确保active唯一、finish连续并做越界防护。

Steps组件的BEM命名必须严格区分状态语义
当前进行(active)和已完成(finish)不能混用同一类名前缀,否则无法独立控制样式。BEM要求状态修饰符必须挂载在元素层级,而非块级;也就是说,steps__item 是块元素,而 steps__item--active 和 steps__item--finish 才是合法的状态修饰符。
常见错误是写成 steps--active 或 steps__item-active(少了双横线),这会破坏BEM约束,导致样式复用困难、CSS权重混乱。
-
steps__item:每个步骤项的基础类名 -
steps__item--finish:已成功完成的步骤(含图标、文字、连接线三者都应响应) -
steps__item--active:当前正在执行的步骤(通常只有一项,且不能与--finish同时存在) - 未开始的步骤默认无修饰符,或可加
steps__item--wait(非必需,但建议统一收口)
如何避免 active 与 finish 样式互相覆盖?
关键在于 CSS 声明顺序和选择器权重一致。BEM 不允许用后代选择器强行提升权重(如 .steps__item--active .steps__icon),而应直接为子元素定义带状态的类名。
推荐做法是让每个子元素也携带状态修饰符:
立即学习“前端免费学习笔记(深入)”;
-
steps__item--finish .steps__icon→ 改为steps__icon--finish -
steps__item--active .steps__title→ 改为steps__title--active - 连接线(
steps__line)同样需要steps__line--finish类,由 JS 控制是否添加
这样所有状态样式都平权,不会因嵌套深度不同而意外覆盖。
JS 动态切换类名时的边界条件
前端框架中(如 React/Vue),容易忽略「active 必须唯一」和「finish 必须连续」这两个业务逻辑约束,仅靠 CSS 类名无法保证。
例如:当 current=2(索引从 0 开始),第 0、1 项应为 --finish,第 2 项为 --active,第 3+ 项为 --wait。若后端返回乱序数据(如 finish: [0,2]),需在渲染前 normalize。
- 永远用
Math.min(current, steps.length - 1)防止越界 - 不要用
itemIndex 判定 finish —— 应该是 <code>itemIndex (因为 current 项是 active,不是 finish) - 服务端可能返回
status: "process"字符串,需映射为--active,避免硬编码字符串比较
兼容性与性能注意点
大量使用 --finish / --active 类名本身无性能问题,但若每个 steps__item 都绑定一堆事件监听器或动画帧,就会卡顿。
真正容易被忽略的是伪元素连接线(::after)的渲染表现:
- 用
steps__line元素显式控制比用steps__item::after更可控 -
steps__line--finish应设transform: scaleX(1)而非width: 100%,避免重排 - IE11 不支持
transform: scaleX()的 transition,需 fallback 到opacity或 JS 控制 class 切换时机
状态类名只是样式入口,背后的数据流、DOM 更新节奏、以及浏览器对 transform 的优化程度,才是真正影响体验的地方。


















