如何创建支持自适应与动态变色的自定义CSS节点进度条
需求说明
我需要用HTML5创建一个进度控件,参考下图:
控件需要满足以下要求:
- 随所在页面自适应调整尺寸
- 进度变化时可修改节点圆圈的颜色
- 进度变化时可修改节点间连接桥的颜色
我尝试了以下代码,但效果不好,很难匹配带编号圆圈的位置,而且定位维护起来很麻烦:
<div class="row" style="margin-top: 15px; margin-bottom: 15px;"> <div class="col-md-12"> <svg height="24" width="24" style="float: left!important;"> <circle cx="12" cy="12" r="10" stroke="black" stroke-width="3" fill="blue" /> <text x="9" y="9" fill="white">1</text> </svg> <svg height="24" width="24" style="float: left!important; margin-left: 25%"> <circle cx="12" cy="12" r="10" stroke="white" stroke-width="3" fill="white" /> <text x="9" y="9" fill="black">2</text> </svg> <svg height="24" width="24" style="float: left!important; margin-left: 25%"> <circle cx="12" cy="12" r="10" stroke="white" stroke-width="3" fill="white" /> <text x="9" y="9" fill="black">3</text> </svg> <svg height="24" width="24" style="float: left!important; margin-left: 25%"> <circle cx="12" cy="12" r="10" stroke="white" stroke-width="3" fill="white" /> <text x="9" y="9" fill="black">4</text> </svg> <svg height="24" width="24" style="float: right!important;"> <circle cx="12" cy="12" r="10" stroke="white" stroke-width="3" fill="white" /> <text x="9" y="9" fill="black">5</text> </svg> <progress value="20" max="100" style="width: 100%; height: 24px; display:block;" /> </div> </div>
解决方案
推荐用单个SVG容器实现,这样更容易控制布局和自适应,同时用CSS类控制状态变化,维护成本更低。
实现代码
<div class="progress-tracker"> <svg viewBox="0 0 100 20" class="progress-svg"> <!-- 节点间连接桥 --> <line x1="10" y1="10" x2="30" y2="10" class="bridge bridge-1" /> <line x1="30" y1="10" x2="50" y2="10" class="bridge bridge-2" /> <line x1="50" y1="10" x2="70" y2="10" class="bridge bridge-3" /> <line x1="70" y1="10" x2="90" y2="10" class="bridge bridge-4" /> <!-- 带编号的节点圆圈 --> <circle cx="10" cy="10" r="8" class="node node-1 completed" /> <text x="10" y="13" text-anchor="middle" fill="white" class="node-text">1</text> <circle cx="30" cy="10" r="8" class="node node-2" /> <text x="30" y="13" text-anchor="middle" fill="#333" class="node-text">2</text> <circle cx="50" cy="10" r="8" class="node node-3" /> <text x="50" y="13" text-anchor="middle" fill="#333" class="node-text">3</text> <circle cx="70" cy="10" r="8" class="node node-4" /> <text x="70" y="13" text-anchor="middle" fill="#333" class="node-text">4</text> <circle cx="90" cy="10" r="8" class="node node-5" /> <text x="90" y="13" text-anchor="middle" fill="#333" class="node-text">5</text> </svg> </div> <style> .progress-tracker { width: 100%; padding: 0 20px; box-sizing: border-box; } .progress-svg { width: 100%; height: auto; } .bridge { stroke: #ddd; stroke-width: 3; transition: stroke 0.3s; } .node { stroke: #ddd; stroke-width: 2; fill: #fff; transition: fill 0.3s, stroke 0.3s; } .node-text { font-size: 10px; font-family: Arial, sans-serif; } /* 已完成状态样式 */ .node.completed { fill: #007bff; stroke: #0056b3; } .bridge.completed { stroke: #007bff; } </style> <script> // 更新进度的函数,参数为当前完成的节点数(1-5) function updateProgress(completedNodes) { // 重置所有状态 document.querySelectorAll('.node').forEach(node => node.classList.remove('completed')); document.querySelectorAll('.bridge').forEach(bridge => bridge.classList.remove('completed')); // 设置已完成的节点和连接桥 for(let i = 1; i <= completedNodes; i++) { document.querySelector(`.node-${i}`).classList.add('completed'); if(i < 5) { document.querySelector(`.bridge-${i}`).classList.add('completed'); } } } // 示例:设置完成2个节点 updateProgress(2); </script>
方案优势
- 自适应布局:SVG使用
viewBox属性,配合容器的width:100%,能自动适配父容器宽度,无需手动计算位置。 - 状态易维护:通过CSS类控制节点和连接桥的颜色,修改状态只需调用
updateProgress函数,无需操作SVG元素的属性。 - 布局精准:单个SVG内的元素坐标相对固定,不会出现多个SVG定位偏移的问题。
内容的提问来源于stack exchange,提问作者Kelvin McKisic
相关产品推荐
相关产品推荐

