用 css 计数器可实现步骤序号自动编号:在容器设 counter-reset,子项用 counter-increment,::before 中 content: counter() 输出数字;进度线用 flex 布局对齐;状态通过 .step--done 等类控制样式,避免干扰计数逻辑;ie11 建议改用 data-step 属性方案。

用 ::before + counter-increment 实现步骤序号自动编号
纯 CSS 做步骤条,最怕手动写 1/2/3 —— 改顺序就得全改,还容易漏。用 CSS 计数器能彻底甩开数字硬编码。
关键不是“怎么加序号”,而是「让每个步骤项自己知道它是第几个」。靠的是 counter-reset 在容器上初始化,再用 counter-increment 在每个子项触发累加,最后用 ::before 的 content: counter(stepper) 把数字吐出来。
-
counter-reset必须设在步骤容器(如.steps)上,不能设在li或div上,否则每次重置,序号全归零 - 如果步骤是
div而非ol/li,记得给每个步骤元素显式加counter-increment: stepper,ol会自动做这事,但div不会 - 别用
counter(stepper, lower-roman)这类格式直接塞进content——老版本 Safari 对非decimal格式支持不稳定,优先用decimal,样式靠字体或伪元素微调
`.steps { counter-reset: stepper; }
.steps > .step { counter-increment: stepper; }
.steps > .step::before {
content: counter(stepper);
/* 其他样式 */
}`进度线怎么对齐到数字中间,又不依赖固定宽度
常见做法是给数字加 position: relative,再用 ::after 绝对定位画线——但一旦数字宽度变(比如中英文混排、字号缩放),线就偏。
真正稳的方案:把进度线抽成独立元素,和数字同级,用 Flex 布局控制间距。数字用 flex: 0 0 auto,线用 flex: 1,自然撑满剩余空间,且始终居中对齐。
立即学习“前端免费学习笔记(深入)”;
- 别给线元素设固定
width或max-width,Flex 的flex: 1才能响应容器变化 - 如果步骤只有 2 个,中间那根线会消失——因为没“中间”了。得额外加一层包裹或用
:not(:last-child)控制线的显示逻辑 - 移动端横屏时,Flex 可能换行,加
flex-wrap: nowrap到容器上,再配合overflow-x: auto滚动更安全
`.step { display: flex; align-items: center; }
.step-number { flex: 0 0 auto; }
.step-line { flex: 1; height: 2px; background: #e0e0e0; }`当前步骤高亮和已完成状态,只靠 CSS 类控制就行
不需要 JS 操控伪元素内容,也不用动态插入 data- 属性。CSS 类足够干净地表达状态:.step--active 表示正在执行,.step--done 表示已完成。
重点在「状态样式不污染计数逻辑」。序号编号和颜色/背景/边框是两套规则,分开写,避免用 .step--done::before 覆盖整个伪元素导致序号消失。
-
.step--done::before只负责改颜色和背景,content保持不变;否则 Safari 下可能闪一下空白 - 别用
opacity: 0.5做未激活态——它会让整个元素(包括线和文字)变灰,应该只调color和border-color - 圆角、阴影、图标等装饰建议统一用
::after实现,和::before(序号)解耦,方便单独开关
`.step--done .step-number::before { background: #4caf50; color: white; }
.step--active .step-number::before { border: 2px solid #2196f3; }`IE11 兼容性下 counter() 的坑与替代思路
IE11 支持 counter-increment 和 counter(),但有两个致命限制:不支持嵌套计数器,且 content 中的 counter() 不能带空格或符号(比如 counter(stepper) "." 会整个不渲染)。
如果项目必须兼容 IE11,宁可放弃自动编号,改用 data-step 属性 + 简单 CSS 选择器,也比掉进 counter() 兼容黑洞强。
- 写成
[data-step="1"]::before { content: "1"; },虽然多几行,但 100% 可控 - JS 初始化时顺手补上
data-step,后续增删步骤只要更新属性值,CSS 规则不动 - 别试图用
@supports (counter-reset: foo)做特性检测——IE11 会误判为支持,结果还是挂
真要保 IE11,计数器就别碰。现代浏览器里它很香,但一落地就卡在那个小数点上。










