窗口宽度为奇数像素时,第二个div为何出现背景渐变漏出?
解决奇数宽度窗口下进度条的绿色异常问题

问题分析
你遇到的绿色小片确实和子像素渲染有关:原代码中用linear-gradient(to left, #ddd 50%, #6ab04c 50%)实现进度切换,当窗口宽度为奇数时,100vw对应的线条宽度是奇数像素,渐变的50%分割线会落在子像素位置。浏览器为了平滑显示,会混合两种颜色的子像素,而第二个线条因为布局位置的计算差异,这种混合效果更明显,最终出现绿色痕迹。另外,background-color和渐变叠加的冗余设置也会加重这个问题。
解决方案
改用transform: scaleX()结合伪元素实现进度动画,同时调整布局逻辑避免视口宽度直接计算,既保持响应式,又彻底解决子像素渲染问题:
修改后的完整代码
HTML
<div class="stage-flow-container"> <div id=1 class="stage-flow-item" onclick="performAction(1)">1</div> <div id=1 class="stage-flow-line"></div> <div id=2 class="stage-flow-item" onclick="performAction(2)">2</div> <div id=2 class="stage-flow-line"></div> <div id=3 class="stage-flow-item" onclick="performAction(3)">3</div> </div>
CSS
.stage-flow-container { display: flex; justify-content: space-between; align-items: center; height: 70px; padding: 0 30px; gap: 0; /* 消除默认间隙,让线条与圆点紧密衔接 */ } .stage-flow-item { width: 70px; height: 70px; min-width: 70px; border-radius: 50%; background-color: #ddd; display: flex; justify-content: center; align-items: center; font-size: 18px; color: #fff; cursor: pointer; z-index: 1; /* 确保圆点显示在线条上方 */ } .stage-flow-item.active { background-color: #ddd; } .stage-flow-item.completed { background-color: #6ab04c; } .stage-flow-line { flex: 1; /* 自动填充两个圆点之间的剩余空间 */ height: 6px; background-color: #ddd; position: relative; overflow: hidden; } .stage-flow-line::after { content: ''; position: absolute; top: 0; left: 0; width: 100%; height: 100%; background-color: #6ab04c; transform: scaleX(0); transform-origin: left; transition: transform .5s ease-out; } .stage-flow-line.lineCompleted::after { transform: scaleX(1); } .stage-flow-line.lineActive::after { transform: scaleX(0); }
JavaScript
let currentStage = 1 function performAction(selectedStage) { currentStage = selectedStage const stages = document.querySelectorAll('.stage-flow-item') const stageLines = document.querySelectorAll('.stage-flow-line') stages.forEach(stage => { const stageId = Number(stage.id) if (stageId > currentStage) { stage.classList.remove('completed') stage.classList.add('active') } else { stage.classList.remove('active') stage.classList.add('completed') } }) stageLines.forEach(stageLine => { const lineId = Number(stageLine.id) if (lineId > currentStage) { stageLine.classList.remove('lineCompleted') stageLine.classList.add('lineActive') } else { stageLine.classList.remove('lineActive') stageLine.classList.add('lineCompleted') } }) }
关键修改点
- 布局优化:用
flex:1替代100vw,让线条自动填充容器剩余空间,彻底避免视口宽度奇数带来的计算问题。 - 动画方式替换:用伪元素+
transform: scaleX()实现进度填充,完全规避渐变的子像素混合问题,动画性能也更优。 - 细节调整:给圆点添加
z-index确保视觉层级正确,将getElementsByClassName替换为querySelectorAll(静态集合更稳定),同时处理id的类型转换避免字符串比较错误。
内容的提问来源于stack exchange,提问作者Connor Ingram
相关产品推荐
相关产品推荐

