跳到主要内容
HTML+CSS 实现 7 个小球转圈圈加载动画教程 | 极客日志
HTML / CSS 大前端
HTML+CSS 实现 7 个小球转圈圈加载动画教程 如何使用纯 HTML 和 CSS 实现七种不同风格的小球旋转加载动画。内容涵盖基础结构搭建、核心动画属性(transform-origin、animation-delay)的应用、七种变体效果(跳跃、渐隐、颜色流动等)、性能优化建议及上线前检查清单。旨在帮助开发者提升用户体验,避免常见坑点。
暖阳 发布于 2026/4/6 更新于 2026/5/20 24 浏览
先搞清楚我们要做啥,别瞎折腾
加载动画的本质不是炫技,是用户体验的基本功。用户在点击按钮后如果页面卡住且无反馈,会误以为网站故障。七个转圈小球的作用是给用户'定心丸',告知数据正在加载,服务器正常但响应较慢。经典、轻量、兼容性好。
HTML 骨架怎么搭才不翻车
不要直接写 CSS,先明确结构。建议使用 ul 或 div 包裹 7 个元素。虽然加载动画本质是装饰性元素,但仍需注意无障碍访问(Accessibility)。给容器加 aria-hidden="true",避免屏幕阅读器重复朗读。务必将动画包在容器中,方便控制显示隐藏及复用,避免切页时动画仍在后台运行消耗性能。
<div class ="loading-container" aria-label ="正在加载数据" role ="status" >
<div class ="loading-wrapper" aria-hidden ="true" >
<div class ="dot" > </div >
<div class ="dot" > </div >
<div class ="dot" > </div >
<div class ="dot" > </div >
<div class ="dot" >
加载中,请稍候...
</div >
<div class ="dot" >
</div >
<div class ="dot" >
</div >
</div >
<span class ="sr-only" >
</span >
</div >
sr-only 类用于视觉隐藏但对屏幕阅读器可见。dot 元素加了 aria-hidden,防止重复朗读。
CSS 动画核心三件套 核心属性:transform-origin 定旋转中心、animation 控制节奏、@keyframes 画轨迹。关键在于 animation-delay 错开时间启动,制造波浪感。
假设动画周期 1.4 秒,每个球延迟 0.2 秒启动(1.4 ÷ 7),形成接力效果。
.loading-wrapper {
position : relative;
width : 60px ;
height : 60px ;
transform : translate3d (0 , 0 , 0 );
}
.dot {
position : absolute;
width : 12px ;
height : 12px ;
background : #3498db ;
border-radius : 50% ;
transform-origin : 30px 30px ;
transform : rotate (0deg ) translateY (-25px );
animation : rotate 1.4s ease-in-out infinite;
}
.dot :nth-child (1 ) { animation-delay : 0s ; }
.dot :nth-child (2 ) { animation-delay : 0.2s ; }
.dot :nth-child (3 ) { animation-delay : 0.4s ; }
.dot :nth-child (4 ) { animation-delay : 0.6s ; }
.dot :nth-child (5 ) { animation-delay : 0.8s ; }
.dot :nth-child (6 ) { animation-delay : 1.0s ; }
.dot :nth-child (7 ) { animation-delay : 1.2s ; }
@keyframes rotate {
0% {
transform : rotate (0deg ) translateY (-25px ) scale (1 );
opacity : 1 ;
}
50% {
transform : rotate (180deg ) translateY (-25px ) scale (0.6 );
opacity : 0.5 ;
}
100% {
transform : rotate (360deg ) translateY (-25px ) scale (1 );
opacity : 1 ;
}
}
使用 ease-in-out 缓动函数模拟自然运动,避免 linear 的机械感。
七种变体效果
跳跃式 适合活泼页面。原理是在旋转基础上叠加 scale 和 translateY 变化。
.dot-jump {
position : absolute;
width : 10px ;
height : 10px ;
background : #e74c3c ;
border-radius : 50% ;
transform-origin : 30px 30px ;
animation : jump 1.4s ease-in-out infinite;
}
@keyframes jump {
0% , 100% {
transform : rotate (0deg ) translateY (-25px ) scale (1 );
}
25% {
transform : rotate (90deg ) translateY (-35px ) scale (1.3 );
}
50% {
transform : rotate (180deg ) translateY (-25px ) scale (0.8 );
}
75% {
transform : rotate (270deg ) translateY (-30px ) scale (1.1 );
}
}
渐隐渐现 适合严肃商务场景。核心玩 opacity,像呼吸灯。
.dot-fade {
position : absolute;
width : 12px ;
height : 12px ;
background : #95a5a6 ;
border-radius : 50% ;
transform-origin : 30px 30px ;
animation : fade 1.2s linear infinite;
opacity : 0.2 ;
}
@keyframes fade {
0% , 100% {
opacity : 0.2 ;
transform : rotate (0deg ) translateY (-25px ) scale (1 );
}
50% {
opacity : 1 ;
transform : rotate (180deg ) translateY (-25px ) scale (1.2 );
}
}
颜色流动 配合 CSS 变量或 filter: hue-rotate(),让颜色随转动过渡。
.dot-color {
position : absolute;
width : 12px ;
height : 12px ;
background : hsl (calc (var (--i) * 51 ), 70% , 50% );
border-radius : 50% ;
transform-origin : 30px 30px ;
animation : colorFlow 2s ease-in-out infinite;
}
@keyframes colorFlow {
0% {
transform : rotate (0deg ) translateY (-25px );
filter : hue-rotate (0deg );
}
50% {
transform : rotate (180deg ) translateY (-25px );
filter : hue-rotate (180deg );
}
100% {
transform : rotate (360deg ) translateY (-25px );
filter : hue-rotate (360deg );
}
}
弹性拉伸 适合游戏页面。用 cubic-bezier 调弹性曲线。
.dot-elastic {
position : absolute;
width : 10px ;
height : 10px ;
background : #e91e63 ;
border-radius : 50% ;
transform-origin : 30px 30px ;
animation : elastic 1.5s cubic-bezier (0.68 , -0.55 , 0.265 , 1.55 ) infinite;
}
@keyframes elastic {
0% {
transform : rotate (0deg ) translateY (-25px ) scale (1 );
}
25% {
transform : rotate (90deg ) translateY (-25px ) scaleX (1.5 ) scaleY (0.6 );
}
50% {
transform : rotate (180deg ) translateY (-25px ) scaleX (0.6 ) scaleY (1.5 );
}
75% {
transform : rotate (270deg ) translateY (-25px ) scaleX (1.3 ) scaleY (0.7 );
}
100% {
transform : rotate (360deg ) translateY (-25px ) scale (1 );
}
}
反向旋转 .dot-reverse :nth-child (odd) {
background : #3498db ;
animation : rotateCW 2s linear infinite;
}
.dot-reverse :nth-child (even) {
background : #2ecc71 ;
animation : rotateCCW 2s linear infinite;
}
@keyframes rotateCW {
from { transform : rotate (0deg ) translateY (-25px ); }
to { transform : rotate (360deg ) translateY (-25px ); }
}
@keyframes rotateCCW {
from { transform : rotate (360deg ) translateY (-25px ); }
to { transform : rotate (0deg ) translateY (-25px ); }
}
大小交替 .dot-breathe :nth-child (odd) {
background : #9b59b6 ;
animation : breatheBig 1.4s ease-in-out infinite;
}
.dot-breathe :nth-child (even) {
background : #f39c12 ;
animation : breatheSmall 1.4s ease-in-out infinite;
}
@keyframes breatheBig {
0% , 100% {
transform : rotate (0deg ) translateY (-25px ) scale (1.5 );
opacity : 0.8 ;
}
50% {
transform : rotate (180deg ) translateY (-25px ) scale (0.8 );
opacity : 0.4 ;
}
}
@keyframes breatheSmall {
0% , 100% {
transform : rotate (0deg ) translateY (-25px ) scale (0.6 );
opacity : 0.4 ;
}
50% {
transform : rotate (180deg ) translateY (-25px ) scale (1.2 );
opacity : 0.9 ;
}
}
暂停呼吸 .dot-pause {
position : absolute;
width : 12px ;
height : 12px ;
background : #1abc9c ;
border-radius : 50% ;
transform-origin : 30px 30px ;
animation : rotate 1.4s ease-in-out infinite;
animation-play-state : running;
transition : transform 0.3s ease;
}
.loading-wrapper :hover .dot-pause {
animation-play-state : paused;
transform : scale (1.2 ) !important ;
}
常见坑点与优化 移动端性能杀手
低端安卓机可能卡顿。原因可能是 transform-origin 配合 filter 导致重绘。解决办法:开启硬件加速,给容器加 transform: translate3d(0, 0, 0) 或 will-change: transform。注意用完取消 will-change 防内存泄漏。
动画结束后残留
加载完成后若 JS 隐藏 loading,小球可能停在奇怪位置。建议加 animation-fill-mode: forwards 控制结束状态。
小球对不齐
不要用手动 margin,使用 Flexbox 或 Grid 居中。
.loading-wrapper {
display : flex;
justify-content : center;
align-items : center;
position : relative;
}
颜色改不动
抽成 CSS 变量,方便统一修改和主题切换。
:root {
--dot-base-color : #3498db ;
--dot-size : 12px ;
--animation-duration : 1.4s ;
}
.dot {
width : var (--dot-size);
height : var (--dot-size);
background : var (--dot-base-color);
animation-duration : var (--animation-duration);
}
上线前必查清单
容器隔离 :不要直接在 body 塞动画,挂载到特定 div,路由切换时销毁节点。
处理 FOUC :默认 opacity: 0 或 display: none,JS 准备好后再淡入。
最大显示时间 :配合 JS 限制 Loading 时长,超时提示重试。
深色模式适配 :使用 currentColor 或媒体查询适配深色背景。
避免等待过久 :Loading 只是缓兵之计,终极方案是优化接口速度或骨架屏。超过 300ms 再显示 Loading。
进阶骚操作 随机延迟
用 calc() 加点随机性,看起来更有机。
.dot :nth-child (2 ) {
animation-delay : calc (var (--base-delay) * 1 + 0.05s );
}
Hover 炸开聚拢
配合 transition 比 animation 更柔和。
.dot-interactive {
transition : transform 0.5s cubic-bezier (0.175 , 0.885 , 0.32 , 1.275 );
}
.loading-wrapper :hover .dot-interactive :nth-child (1 ) {
transform : rotate (0deg ) translateY (-40px ) scale (1.5 );
}
.loading-text ::after {
content : '...' ;
animation : dots 1.5s steps (4 , end) infinite;
}
@keyframes dots {
0% , 20% { content : '.' ; }
40% { content : '..' ; }
60% { content : '...' ; }
80% , 100% { content : '' ; }
}
相关免费在线工具 Base64 字符串编码/解码 将字符串编码和解码为其 Base64 格式表示形式即可。 在线工具,Base64 字符串编码/解码在线工具,online
Base64 文件转换器 将字符串、文件或图像转换为其 Base64 表示形式。 在线工具,Base64 文件转换器在线工具,online
Markdown转HTML 将 Markdown(GFM)转为 HTML 片段,浏览器内 marked 解析;与 HTML转Markdown 互为补充。 在线工具,Markdown转HTML在线工具,online
HTML转Markdown 将 HTML 片段转为 GitHub Flavored Markdown,支持标题、列表、链接、代码块与表格等;浏览器内处理,可链接预填。 在线工具,HTML转Markdown在线工具,online
JSON 压缩 通过删除不必要的空白来缩小和压缩JSON。 在线工具,JSON 压缩在线工具,online
JSON美化和格式化 将JSON字符串修饰为友好的可读格式。 在线工具,JSON美化和格式化在线工具,online