You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何实现长度无关、移动速度恒定的CSS进度条?

实现宽度无关的恒定速度不确定进度条

我用以下代码实现了一个不确定进度条,但发现它的移动速度会随容器宽度变化——容器越长,动画在固定时长内需要跨越的实际距离越大,视觉上速度就越快。我希望这个进度条既能用于网站顶部的全局宽进度条,也能用于组件内的小型进度条,因此需要解决速度恒定的问题。


原实现代码

CSS

.progress-bar-short,
.progress-bar-long {
  animation-duration: 2.2s;
  animation-iteration-count: infinite;
  animation-delay: 200ms;
  will-change: left, right;
}

.progress-bar-short {
  animation-name: indeterminate-short-ltr;
}

.progress-bar-long {
  animation-name: indeterminate-ltr;
}

@keyframes indeterminate-ltr {
  0% {
    left: -90%;
    right: 100%;
  }
  60% {
    left: -90%;
    right: 100%;
  }
  100% {
    left: 100%;
    right: -35%;
  }
}

@keyframes indeterminate-short-ltr {
  0% {
    left: -200%;
    right: 100%;
  }
  60% {
    left: 107%;
    right: -8%;
  }
  100% {
    left: 107%;
    right: -8%;
  }
}

HTML

<div style="position: relative; width: 100%; height: 4px;">
  <div class="progress-bar-long" style="left: 0%; right: 100%; top: 0; bottom: 0; position: absolute; background-color: red;"></div>
  <div class="progress-bar-short" style="left: 0%; right: 100%; top: 0; bottom: 0; position: absolute; background-color: red;"></div>
</div>

解决方案:基于固定速度的动态动画时长

核心思路是让动画时长随容器宽度动态计算,确保进度条的移动速度(像素/秒)恒定。具体实现如下:

修改后的CSS

/* 定义全局默认变量 */
:root {
  --speed: 300px/s; /* 恒定速度:每秒移动300像素 */
  --container-width: 100%; /* 默认容器宽度,可通过内联样式覆盖 */
}

.progress-bar-short,
.progress-bar-long {
  animation-iteration-count: infinite;
  animation-delay: 200ms;
  animation-timing-function: linear; /* 强制匀速移动 */
  will-change: transform; /* 优化动画性能 */
  position: absolute;
  top: 0;
  bottom: 0;
  background-color: red;
}

/* 长进度条:总移动比例为190%(从-90%到100%) */
.progress-bar-long {
  width: 90%;
  animation-name: indeterminate-ltr;
  animation-duration: calc( (1.9 * var(--container-width)) / var(--speed) );
}

/* 短进度条:总移动比例为307%(从-200%到107%) */
.progress-bar-short {
  width: 100%;
  animation-name: indeterminate-short-ltr;
  animation-duration: calc( (3.07 * var(--container-width)) / var(--speed) );
}

/* 改用transform实现位移,性能更优且计算更直观 */
@keyframes indeterminate-ltr {
  0% {
    transform: translateX(-100%);
  }
  60% {
    transform: translateX(-100%);
  }
  100% {
    transform: translateX(calc(100% / 0.9)); /* 等价于从-90%位移到100%的总距离 */
  }
}

@keyframes indeterminate-short-ltr {
  0% {
    transform: translateX(-200%);
  }
  60% {
    transform: translateX(calc(107% + 8%)); /* 对应原动画的目标位置 */
  }
  100% {
    transform: translateX(calc(107% + 8%));
  }
}

修改后的HTML(不同宽度容器示例)

<!-- 全局宽进度条 -->
<div style="position: relative; width: 100%; height: 4px; --container-width: 100vw;">
  <div class="progress-bar-long"></div>
  <div class="progress-bar-short"></div>
</div>

<!-- 小型组件进度条 -->
<div style="position: relative; width: 200px; height: 4px; --container-width: 200px;">
  <div class="progress-bar-long"></div>
  <div class="progress-bar-short"></div>
</div>

关键说明

  • animation-timing-function: linear:确保动画全程匀速,避免默认缓动效果导致的速度波动
  • 动态计算animation-duration:通过calc()将总移动距离除以固定速度,保证不同宽度容器下的移动速度一致
  • 改用transform: translateX():相比修改left/right,transform动画的性能更优,且位移计算更直观

内容的提问来源于stack exchange,提问作者Mitar

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.08 21:50:24