前端进阶之旅前端进阶之旅
基础篇
进阶篇
高频篇
精选篇
手写篇
面经篇
AI 篇
原理篇
每日一题
小程序题库
知识卡片
  • 场景篇按分类整理的大前端场景考点
  • 历年面经按年份追踪真实考点
  • 算法题库NEW在线编码即时判题
  • 专项自测100 题快速查漏
  • 前端基础
    • HTTP从报文一路讲到 HTTPS
    • 浏览器渲染、事件循环、进程
    • 计算机基础Linux、网络、操作系统
  • 进阶专项
    • 设计模式23 种模式怎么用
    • 前端系统进阶学习大型项目工程化
    • 前端综合文章长期沉淀的实践文
  • 工程与工具
    • Node学习指南从环境搭建到服务端
    • NPM工作流script、依赖与发布
    • Docker容器化部署上手
    • Canvas图形与动画实战
  • 路线与导图
    • 思维导图知识点全景图
    • 学习路线按图索骥不跑偏
  • 动态
    • 公众号动态公众号历史文章
    • 博客动态站长的技术博客
    • 开发者导航常用工具与文档站
  • AI 助手随时提问,即时解析
  • AI 模拟面试模拟真实面试 + 报告
  • AI 知识地图串起全站知识点
  • AI 定制路线按你的简历现排
AI 热点
旧版
基础篇
进阶篇
高频篇
精选篇
手写篇
面经篇
AI 篇
原理篇
每日一题
小程序题库
知识卡片
  • 场景篇按分类整理的大前端场景考点
  • 历年面经按年份追踪真实考点
  • 算法题库NEW在线编码即时判题
  • 专项自测100 题快速查漏
  • 前端基础
    • HTTP从报文一路讲到 HTTPS
    • 浏览器渲染、事件循环、进程
    • 计算机基础Linux、网络、操作系统
  • 进阶专项
    • 设计模式23 种模式怎么用
    • 前端系统进阶学习大型项目工程化
    • 前端综合文章长期沉淀的实践文
  • 工程与工具
    • Node学习指南从环境搭建到服务端
    • NPM工作流script、依赖与发布
    • Docker容器化部署上手
    • Canvas图形与动画实战
  • 路线与导图
    • 思维导图知识点全景图
    • 学习路线按图索骥不跑偏
  • 动态
    • 公众号动态公众号历史文章
    • 博客动态站长的技术博客
    • 开发者导航常用工具与文档站
  • AI 助手随时提问,即时解析
  • AI 模拟面试模拟真实面试 + 报告
  • AI 知识地图串起全站知识点
  • AI 定制路线按你的简历现排
AI 热点
旧版
首页程序员面试题库CSS animation 无限循环 每次循环加延迟
CSS动画与视觉

怎么让无限循环的动画在每两轮之间有一段停顿?

animation-delay 只在第一轮开始之前生效,后续每轮之间不会自动加间隔。想让每轮之间有停顿,做法是把 animation-duration 设得比实际动画长,然后在 @keyframes 里把动作集中在前面一段百分比内,剩余时间元素保持不动,视觉上就像有了间歇。

前端进阶之旅 · 一题精讲更新于 2026.09.29
CSS#动画与视觉#动画
先看核心答案读代码示例
理解线索

用百分比制造停顿的原理

  1. animation-delay只在第一轮之前等待,后续循环之间不起作用
  2. 关键帧百分比把动作写在 0% 到 50%,50% 到 100% 保持不变,等于一半时间在停顿
  3. animation-duration总时长包含了动作时间和停顿时间,拉长它就等于加长间隔

这种方法的缓动函数作用于整个周期,动作段会加速。如果需要精确控制缓动,可以给动作段和停顿段分别用不同的 animation-timing-function。

核心回答

先记住这个答案

CSS 动画的 animation-delay 只在第一轮播放之前生效,之后的循环紧接着上一轮结束就开始。CSS 没有提供「每轮之间加间隔」的属性。通行的做法是把 animation-duration 设成实际动画时长加上想要的停顿时长,然后在 @keyframes 里把动作集中写在前面一部分百分比内,后面的百分比保持不变。这样后半段元素不动,看起来就像在等待。

  • animation-delay 只作用于第一轮
  • 拉长总时长、动作集中在前半段
  • 剩余百分比保持不动当作停顿
  • 也可以用 animationiteration 手动控制

用关键帧百分比制造停顿

假设你想做一个心跳效果:放大再缩回,然后停 1 秒,再重复。实际动画动作需要 1 秒,停顿 1 秒,所以总时长设成 2 秒。动作占前 50% 的时间,后 50% 保持不动。

心跳动画:1 秒跳动 + 1 秒停顿CSS
@keyframes heartbeat {
  0%   { transform: scale(1); }
  25%  { transform: scale(1.3); }
  50%  { transform: scale(1); }
  100% { transform: scale(1); } /* 50%~100% 保持不动,充当停顿 */
}

.heart {
  animation: heartbeat 2s ease-in-out infinite;
}

50% 到 100% 这段时间元素保持 scale(1) 不动,视觉上就是每跳一次停 1 秒。想让停顿更长,把 animation-duration 拉大,同时把动作部分的百分比压缩。比如总时长 4 秒、动作占 25%,停顿就变成了 3 秒。

调整停顿时长的计算方式

假设动作本身需要 T 秒,想在两轮之间停顿 P 秒。总时长设成 T + P 秒,动作占比是 T / (T + P),换算成百分比写到 @keyframes 里。

比如动作 0.5 秒、停顿 2 秒:总时长 2.5 秒,动作占 20%。@keyframes 里 0% 到 20% 写动作,20% 到 100% 保持结束状态。

动作 0.5 秒 + 停顿 2 秒CSS
@keyframes blink {
  0%   { opacity: 1; }
  10%  { opacity: 0; }
  20%  { opacity: 1; }
  100% { opacity: 1; }
}

.cursor {
  animation: blink 2.5s linear infinite;
}

要注意 animation-timing-function 作用于整个周期而不只是动作段。如果用了 ease-in-out,停顿前后会有加速减速的感觉。想让动作段有缓动、停顿段完全静止,可以在关键帧里单独写 animation-timing-function。

用 JavaScript 在每轮之间加真正的延迟

如果不想用百分比技巧,也可以用 JavaScript 监听 animationiteration 事件,在每轮结束时暂停动画,过一段时间再恢复。

监听 animationiteration 手动加延迟JavaScript
const el = document.querySelector('.box');
el.addEventListener('animationiteration', () => {
  el.style.animationPlayState = 'paused';
  setTimeout(() => {
    el.style.animationPlayState = 'running';
  }, 1000); // 停顿 1 秒
});

这种方式可以精确控制停顿时长,也不用重新算百分比。缺点是依赖 JavaScript,纯 CSS 方案做不到这一点。

回答前,多想一步

容易答错的地方

以为 animation-delay 每轮都会生效
animation-delay 只作用于动画的第一次启动。设了 infinite 之后,从第二轮开始就没有延迟了。很多人以为每轮之间都会等一下,实际上后续的循环是无缝衔接的。
把停顿段的关键帧值写错
停顿段的样式必须和动作段的结束样式一致。比如动作段最后是 scale(1),停顿段从头到尾也要是 scale(1)。如果写成了别的值,「停顿」期间元素会慢慢过渡到那个值,就不是真正的停顿了。
试着用自己的话回答

面试官还会怎么问?

能不能用两个动画叠加来实现停顿?

可以,但比较绕。一个动画负责实际效果,另一个动画用 steps() 在特定时间段把元素藏起来。实际项目里用关键帧百分比更直观,代码也更好维护。

停顿期间想让元素完全消失再出来,怎么做?

把停顿段的样式改成 opacity: 0 或 visibility: hidden,动作段开头再恢复。不过要注意 visibility 不支持平滑过渡,opacity 可以,看你要不要有淡入淡出的效果。

为什么不用 animation-delay 配合 animationend 重新播放?

这样做可以,但需要在 animationend 回调里先移除动画、用 requestAnimationFrame 或 offsetHeight 触发重排、再加回去,代码比较啰嗦。而且 infinite 动画不会触发 animationend,这个方案就不适用了。

从一道题,走向一组知识

把知识连起来

动画与视觉

animation-direction 的 alternate 和 reverse 有什么区别?

alternate 方向下动画来回播放,配合停顿技巧可以做「弹跳后停一下再弹回来」的效果。

动画与视觉

cubic-bezier 四个参数分别控制什么?

停顿期间的 animation-timing-function 决定了过渡是线性还是有缓动,想让停顿开始和结束更自然可以用贝塞尔曲线。

参考资料

  • animation-delay CSS property

示例用于理解所注明的运行环境与边界;延伸学习可结合原文中的更多案例。

本题目录
  1. 先记住这个答案
  2. 用关键帧百分比制造停顿
  3. 调整停顿时长的计算方式
  4. 用 JavaScript 在每轮之间加真正的延迟
  5. 容易答错的地方
  6. 面试官还会怎么问
  7. 把知识连起来
读懂,再试着讲出来

先看核心答案,再读代码。最后展开追问,检查自己有没有遗漏边界。

试着回答追问
浏览全部面试题理解原理,也关注真实的使用场景。回到顶部 ↑