
无需 javascript,仅用纯 css 即可实现三个箭头依次滑入(1→2→3)、再反向滑出(3→2→1)并无限循环的加载动画效果。
无需 javascript,仅用纯 css 即可实现三个箭头依次滑入(1→2→3)、再反向滑出(3→2→1)并无限循环的加载动画效果。
在构建加载指示器(loading spinner)时,常需营造“流动感”或“序列感”,比如三个箭头逐个入场、再逐个退场的视觉节奏。许多开发者误以为必须依赖 JavaScript 控制 animation-name 切换来实现复杂序列,但其实 CSS 动画本身完全支持多阶段时间轴控制与精确延迟调度,只需合理设计关键帧百分比和 animation-delay,即可优雅达成目标。
✅ 核心思路:为每个箭头定义独立动画时间线
本方案摒弃了对单个 slideIn/slideOut 动画的反复切换逻辑,转而为 .arrow:nth-child(1)、.arrow:nth-child(2)、.arrow:nth-child(3) 分别编写专属 @keyframes(arrow1 / arrow2 / arrow3),每个动画完整描述其自身从“未出现 → 入场 → 停留 → 退场”的全过程,并通过百分比关键帧精准控制透明度(opacity)与水平位移(left)的变化时机。
例如 arrow1 的关键帧逻辑如下:
@keyframes arrow1 {
from { opacity: 0; left: -10px; } /* 起始:左侧隐藏 */
12.5%, 75% { opacity: 1; left: 0; } /* 入场并停留(占总时长62.5%)*/
87.5%, to { opacity: 0; left: 10px; } /* 退场至右侧消失 */
}
整个动画周期设为 3.5s,则:
- 箭头1 在
0s开始入场,0.44s(12.5% × 3.5s)完成入场并停留至2.625s(75% × 3.5s); - 箭头2 比箭头1 晚
0.44s启动(对应animation-delay: 0.44s),形成错峰入场; - 箭头3 再延后
0.44s,最终实现「1→2→3 滑入」→「3→2→1 滑出」的无缝循环。
? 完整可运行代码(含 HTML + CSS)
<style>
html, body {
height: 100%;
margin: 0;
padding: 0;
display: flex;
align-items: center;
justify-content: center;
background-color: #f4f4f4;
color: #EE4036;
font-family: Arial, sans-serif;
font-weight: bolder;
font-size: xx-large;
}
.arrows {
display: flex;
justify-content: start;
align-items: start;
padding-left: 6px;
gap: 3px;
}
.arrow {
position: relative;
width: 10px;
height: 10px;
background: #EE4036;
border-top-right-radius: 30%;
transform: rotate(-60deg) skewX(-30deg) scale(1, .866);
rotate: 90deg;
opacity: 0;
}
.arrow::before,
.arrow::after {
content: "";
position: absolute;
width: inherit;
height: inherit;
background: #EE4036;
border-top-right-radius: inherit;
}
.arrow::before {
transform: rotate(-135deg) skewX(-45deg) scale(1.414, .707) translateY(-50%);
}
.arrow::after {
transform: rotate(135deg) skewY(-45deg) scale(.707, 1.414) translateX(50%);
}
/* 三个独立动画,周期统一为 3.5s */
@keyframes arrow1 {
from { opacity: 0; left: -10px; }
12.5%, 75% { opacity: 1; left: 0; }
87.5%, to { opacity: 0; left: 10px; }
}
@keyframes arrow2 {
0%, 12.5% { opacity: 0; left: -10px; }
25%, 62.5% { opacity: 1; left: 0; }
75%, to { opacity: 0; left: 10px; }
}
@keyframes arrow3 {
0%, 25% { opacity: 0; left: -10px; }
37.5%, 50% { opacity: 1; left: 0; }
62.5%, to { opacity: 0; left: 10px; }
}
.arrows .arrow:nth-child(1) { animation: arrow1 3.5s infinite; }
.arrows .arrow:nth-child(2) { animation: arrow2 3.5s infinite; }
.arrows .arrow:nth-child(3) { animation: arrow3 3.5s infinite; }
</style><section><div class="loading">Loading</div>
<section class="arrows"><div class="arrow"></div>
<div class="arrow"></div>
<div class="arrow"></div>
</section></section>
⚠️ 注意事项与优化建议
-
避免
transform与left混用冲突:原问题中同时使用transform: translateY(...)和left属性,易导致渲染异常。本方案统一采用left控制水平位移,保持定位逻辑清晰;若需更优性能,可改用transform: translateX()替代left。 -
动画周期需严格对齐:三个动画总时长必须一致(如均为
3.5s),且各阶段百分比按等分逻辑(如12.5% = 1/8)推算,才能保证循环节奏稳定。 -
语义化与可维护性:推荐将
.arrow_1/.arrow_2/.arrow_3类名简化为无序列表结构(即直接用:nth-child),减少冗余 HTML,提升 CSS 可读性。 -
兼容性提示:
rotate和skewX/skewY属于现代 CSS 属性,主流浏览器均支持;如需兼容 IE,需添加-ms-transform等前缀(但 IE 已不推荐用于新项目)。
通过本方案,你不仅实现了预期动画效果,更掌握了 CSS 动画高级编排的核心方法——以时间为坐标轴,用百分比关键帧雕刻每一帧行为,再借 nth-child 实现元素级动画解耦。这是构建专业级加载动画、进度指示器乃至交互动画的基础能力。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











