用 + ::before 实现语义化步骤条: 天然可访问,图标由伪元素生成,状态通过 data-status 属性控制(done/current/pending),CSS 变量统一管理颜色,响应式采用 flex 布局切换横/纵排列。

怎么用纯 HTML + CSS 实现带图标的步骤条
不需要 JS,也不依赖第三方库,用 <ol></ol> + ::before 伪元素就能做出语义清晰、可访问、易维护的步骤条。关键不是“怎么画圆点”,而是“怎么让每个步骤有状态且不写死图标”。
- 用
<ol></ol>包裹步骤,天然支持语义化和屏幕阅读器(每个<li>是一个步骤) - 图标统一用
::before生成,避免在 HTML 里混入<i></i>或 SVG 标签,便于批量控制状态(如完成/当前/未开始) - 不要给每个
<li>写独立 class(比如step-1-done),改用属性选择器:给当前步骤加data-status="current",CSS 里写[data-status="current"]::before - 图标字体(如 Font Awesome)需确保加载完成后再渲染,否则可能闪白;更稳的方式是用 inline SVG 或系统字体里的 ✅ / ➤ / ○ 等符号
CSS 怎么控制步骤图标的状态样式
核心是三个状态:已完成(✅)、进行中(➤)、未开始(○)。别用三套颜色硬编码,用 CSS 变量统一管理:
:root {
--step-done: #4ade80;
--step-current: #3b82f6;
--step-pending: #9ca3af;
}
<p>.step-item[data-status="done"]::before {
content: "✓";
color: var(--step-done);
}</p><p>.step-item[data-status="current"]::before {
content: "●";
color: var(--step-current);
font-weight: bold;
}</p><p>.step-item[data-status="pending"]::before {
content: "○";
color: var(--step-pending);
}-
content值必须是字符串,不能直接写 Unicode 变量(如var(--check)),要写死或用 JS 注入 - 用
font-weight: bold加粗实心圆比换字体更可靠,避免跨平台渲染差异 - 如果要用 SVG 图标,建议 base64 编码后塞进
content: url("data:image/svg+xml,..."),但注意 IE 不支持
怎么让步骤条响应式不堆叠、线不折断
水平步骤条在小屏上最常出问题:图标挤在一起、连接线断开、文字换行。解决思路不是“隐藏文字”,而是“分层响应”:
将 Markdown 文章转换为微信公众号兼容的纯 HTML 格式。当用户要求"转成微信格式"、"生成公众号文章 HTML"、"排版到微信草稿箱"、"微信粘贴格式"时触发。输出带内联样式的纯 HTML,微信编辑器可直接渲染,无需额外适配。支持标题、段落、列表、粗体、行内代码、表格、引用块、代码块、配图的完整转换。
- 默认用
display: flex布局,flex-wrap: nowrap防止换行 - 连接线用
<div class="step-line"> 放在每个 <code><li>后面(除最后一个),宽度设为calc(100% - 64px)(预留图标+间距) - 小屏(
max-width: 768px)时切为垂直布局:flex-direction: column,align-items: flex-start,线改用border-left模拟 - 文字过长?用
white-space: nowrap; overflow: hidden; text-overflow: ellipsis;,但只对描述文字生效,标题保留完整
为什么用 data-status 而不用 class 控制状态
因为真实项目里步骤状态经常动态变化(比如表单提交后跳转到下一步),用 class 需要 JS 手动增删多个类(step-done、step-current、step-pending),容易漏掉清理;而 data-status 是单值属性,JS 只需更新一处:
立即学习“前端免费学习笔记(深入)”;
// 切换到第 3 步
document.querySelectorAll('.step-item').forEach((el, i) => {
el.dataset.status = i === 2 ? 'current' : i < 2 ? 'done' : 'pending';
});- 浏览器对
dataset更新的重绘效率高于 classList 操作 - 服务端渲染(如 SSR)也能直接输出正确的
data-status,首屏无需等 JS 初始化 - 测试时更容易断言:查
el.dataset.status === 'done'比查是否含某个 class 更明确
真正麻烦的是状态同步时机——比如用户点了“上一步”按钮,但表单校验还没返回,这时候 UI 状态和数据状态就可能错位。得在状态变更前加一层校验钩子,而不是只靠 CSS 控制图标。


















