简介:纯CSS3网页加载动画源码包,面向前端初学者与网页设计者,为页面加载环节增添科技感视觉反馈,解决等待页枯燥乏味、缺乏动态引导的问题,全程不依赖JavaScript或其他库。压缩包共2个文件:1个HTML页面负责结构,1个CSS文件负责全部动画与光效,整体约2KB大小,十分轻量,可直接拖入浏览器运行,也方便复制关键代码嵌入真实项目。目前已有1038人学习下载,源码重点演示了关键帧动画的用法:通过0%到100%的旋转帧定义连续转动,配合动画属性设置时长、速度曲线与无限迭代,形成稳定循环;背景部分采用线性渐变从深色向亮色过渡,并利用阴影模糊半径与半透明颜色值模拟光晕,营造出发光渐变的科技氛围。另外还加入性能优化声明与三维渲染提升,确保动画流畅。该方案既是一次完整的技术演示,也是一份可直接上线的加载页模板,适合前端爱好者拆解学习与快速复用。
1. 先别急着解压这个 CSS3 Loading 动画源码,先搞清楚它到底做了什么
这类“网页Loading加载动画特效源码.zip”你在资源站逛久了,基本一眼就能猜出里面是什么:一个 HTML 文件、一个 CSS 文件,打开浏览器就能看到一个不断旋转、并且背景在发光渐变的加载动画。它解决的问题很实在——大多数个人站点和后台系统,在首屏资源加载、接口请求那段“空窗期”里,页面往往是一片白屏,用户不知道是卡死了还是没加载出来。用一个科技感十足的发光渐变背景,配合一个不停转动的圆环,把等待时间变成体验的一部分,至少能压住“站点是不是挂了”的疑虑。这套方案特别适合不想为了一个加载动画去引入 jQuery、Lottie 或 Canvas 动画库的人;你只要会改 CSS 颜色和字号,就能把它改到自己网站上用。接下来我会把这类源码背后的 CSS3 原理拆开讲,再给你一套可以直接照抄的最小实现,以及换肤、调参和排查翻车现场的完整路径。
2. 为什么纯 CSS3 做加载动画,反而比 GIF、Canvas 更值得选
2.1 纯 CSS3 不是磨洋工,而是把动画交给 GPU
先说一个容易误会的点:不少人觉得“加载动画嘛,GIF 丢上去就行,代码都不用写”。GIF 在彩色渐变这种场景下会踩大坑——它只有 8 位颜色,渐变过渡会出现明显色带,而且GIF 图像是整帧解码,同样尺寸下体积反而比一段 CSS 大得多。CSS3 动画则是在浏览器合成器线程上运行的,只要动画属性是transform、opacity这类不触发布局重绘的属性,它就能利用 GPU 加速,动画开销极小。
我经常看到新手把动画写在left、top属性上,就像这样:
/* 这样做会每帧触发 layout,很容易卡 */ .loader { left: 0; animation: moveLeft 1s linear infinite; } @keyframes moveLeft { to { left: calc(50% - 35px); } }这会让浏览器每帧都重新计算布局,遇到性能差的手机就会抖动。正确的做法是:元素保持静态定位,只旋转或缩放自己本身。纯 CSS3 的加载动画核心思想就是“元素不动,变换的只有视觉层”:旋转用transform: rotate(),呼吸用transform: scale(),透明度变化用opacity。这三点吃透了,后面所有源码包里的动画你都能看懂。
2.2 背景“发光渐变”是怎么画的:linear-gradient 与 background-size
源码标题里最显眼的其实是“背景发光渐变”,不是那个转圈。背景发光渐变的实现依赖三个 CSS 属性:background-image: linear-gradient(...)负责铺色,background-size负责把渐变放大到超出视口,然后动画去移动background-position,让颜色在画面里“流动”。
有一个反直觉的坑:直接给body写background: linear-gradient(135deg, #0f0c29, #302b63, #24243e),浏览器会默认把背景尺寸设为容器大小,渐变是静态铺满的,你再怎么写@keyframes去改background-color都不会有流动感。原因很简单——渐变图是背景图像,不是一个可变的颜色值。你只能移动它,不能一帧一帧地“重画”它。常见做法是先把渐变放大到 200% 甚至 300%,再让位置在 0% 到 100% 之间来回走:
body { min-height: 100vh; background-image: linear-gradient(135deg, #0f0c29, #302b63, #24243e, #00d2ff); background-size: 300% 300%; animation: gradientShift 10s ease infinite; } @keyframes gradientShift { 0% { background-position: 0% 50%; } 50% { background-position: 100% 50%; } 100% { background-position: 0% 50%; } }这里的background-position百分比坐标不是左上角到右下角的二维坐标,它的 0% 和 100% 分别对应背景图左边缘与容器左边缘对齐、背景图右边缘与容器右边缘对齐。所以background-size: 300% 300%给了位置足够的移动空间,动画才有效果。后面调参环节我会专门讲这个百分比怎么用。
2.3 圆环的旋转是“画”出来的,不是“播放”出来的
现在来看 loading 动画的主体:一个不断旋转的圆圈。它本质上不是图形,而是 border。常见的做法是把元素设成正方形,四边边框颜色全部一致,然后把其中一条边框的颜色改成高亮青色,再设置border-radius: 50%,让它变成圆环:
.loader { width: 70px; height: 70px; border: 3px solid rgba(0, 229, 255, 0.2); border-top-color: #00e5ff; border-radius: 50%; animation: spin 1s linear infinite; } @keyframes spin { to { transform: rotate(360deg); } }因为border-top-color和其余三边颜色不同,整个圆环就有一条“亮度缺口”,旋转到任意角度都能看出明显的方向感,人眼才会觉得它像在转。如果四边颜色完全一样,很多角度下无法分辨是否转动。此处的“发光”不是靠 border 本身实现的,而是给这个动画元素加一层蓝色的光晕,推荐用filter: drop-shadow(0 0 6px #00e5ff)。这里还有个细节:不要用box-shadow直接加在动画元素上,因为box-shadow在圆角矩形的边缘表现不是完全贴合弧线,旋转时会产生不均匀的闪烁;filter: drop-shadow会沿着透明裁切后的形状描边,视觉上更贴合。
2.4 和 GIF、Canvas、Lottie 相比,CSS3 到底赢在哪
选方案之前,我们把这些主流做法放在同一个维度里对比一下,也方便你以后跟同事聊需求时直接给出选型结论。
| 方案 | 文件体积 | 缩放大屏 | 性能开销 | 换主题难度 | 依赖 |
|---|---|---|---|---|---|
| 动图 GIF | 大 | 发虚 | 中 | 高 | 无 |
| Canvas | 小 | 清晰 | 低,但需写JS | 中 | 无 |
| Lottie | 看资源 | 清晰 | 中 | 低 | 动画库+JSON |
| 纯 CSS3 | 极小 | 清晰矢量 | 低,可GPU加速 | 低,改变量 | 无 |
如果项目已经有成熟的 Lottie 流程,用 Lottie 也没什么问题。但很多管理后台、个人作品集、简历页面只是为了在空闲期加一个不太抢眼的加载动画,这时候引入动画库显得太重了。纯 CSS3 最大的优势其实是“确定性”:浏览器只要支持 CSS3 就能跑,不需要等待 JS 框架初始化。这也是我优先建议用源码包里那套 CSS 去做二次开发的原因。
3. 从源码包到浏览器:最小可运行版本的分步拆解
3.1 压缩包内常见文件结构,以及最少需要哪几个文件
源码包名字里带“源码.zip”,解压出来通常是一个项目文件夹,里面最常见的就是 HTML 和 CSS 两个文件。如果为了演示方便,还会有一张预览图,但我们自己复现时只要三个文件就够:一个index.html、一个style.css,勉强再算上README.txt也可以不要。下面是符合这类源码包常规的最小结构:
loader-demo/ ├── index.html └── style.css在浏览器打开index.html,能看到动画,就算跑通了。日常开发我习惯用 VS Code 的 Live Server 看实时效果,因为它启动本地静态服务后,CSS 预览刷新更接近最终部署效果,直接双击文件用file://协议看,部分浏览器对 CSS 动画的滤镜效果会有肉眼感知的差异。
3.2 先写 HTML:加载层与页面层必须分开
不要天真地把加载动画直接怼进页面正文,最后还得想着怎么把它删掉。比较稳妥的结构是:正文内容正常放一个main标签,加载动画单独放进一个占满全屏的覆盖层,两个层级互不干扰。
<!DOCTYPE html> <html lang="zh-CN"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>纯CSS3背景发光渐变Loading</title> <link rel="stylesheet" href="style.css"> </head> <body> <main class="page"> <h1>这里是页面正文</h1> <p>首屏内容、业务模块都放在 main 里面。</p> </main> <div class="loader-wrap" id="loaderWrap"> <div class="loader"> <span class="loader-core"></span> </div> </div> </body> </html>这段结构里,.loader-wrap是覆盖层,用position: fixed把它固定在整个视口上方;.loader是旋转圆环;.loader-core是圆环中心的那个呼吸光点。这样以后想隐藏加载层,只需要控制.loader-wrap的 CSS 类或透明度,不会影响正文布局。
3.3 再写 CSS:让渐变背景、旋转圆环和呼吸光点同时跑起来
这一节直接给你一个能完整运行的最小 CSS。不要小看它,这其实就是很多源码包去掉多余装饰之后剩下的骨架。
* { box-sizing: border-box; margin: 0; padding: 0; } body { font-family: system-ui, sans-serif; min-height: 100vh; display: flex; align-items: center; justify-content: center; background-image: linear-gradient(135deg, #0f0c29, #302b63, #24243e, #00d2ff); background-size: 300% 300%; animation: gradientShift 12s ease infinite; } .loader-wrap { position: fixed; inset: 0; z-index: 9999; display: flex; align-items: center; justify-content: center; background: rgba(0, 0, 0, 0.25); transition: opacity 0.4s ease, visibility 0.4s ease; } .loader { position: relative; width: 70px; height: 70px; border: 3px solid rgba(0, 229, 255, 0.2); border-top-color: #00e5ff; border-radius: 50%; animation: spin 1s linear infinite; filter: drop-shadow(0 0 6px #00e5ff); } .loader-core { position: absolute; top: 50%; left: 50%; width: 12px; height: 12px; background: #fff; border-radius: 50%; box-shadow: 0 0 12px #00e5ff, 0 0 24px #00e5ff; animation: corePulse 1.5s ease-in-out infinite; } @keyframes spin { to { transform: rotate(360deg); } } @keyframes gradientShift { 0% { background-position: 0% 50%; } 50% { background-position: 100% 50%; } 100% { background-position: 0% 50%; } } @keyframes corePulse { 0%, 100% { transform: translate(-50%, -50%) scale(1); opacity: 1; } 50% { transform: translate(-50%, -50%) scale(0.6); opacity: 0.5; } }拆开看几个关键参数:
background-size: 300% 300%控制渐变流动。数值越大,颜色过渡越平缓,动画越像“缓慢扫光”;想更快更跳脱,可以改成200% 200%,但边缘会出现明显的色块分界。border-top-color: #00e5ff制造圆环缺口。把left或right的边框颜色改成高亮色也没问题,只是转起来视觉重心会偏。filter: drop-shadow(0 0 6px #00e5ff)给圆环添加外发光。0 0 6px分别是水平偏移、垂直偏移和模糊半径;这里不需要水平垂直偏移,所以都写 0。.loader-core里的box-shadow用了两层,这是最省事的发光做法。第一层 12px 提供近距离强光,第二层 24px 负责把光晕向外晕开。两层之间建议保持 1.5 到 2 倍关系,模拟真实光源的衰减。
3.4 只用 CSS 让加载层自动消失,可行但要认清取舍
许多标着“纯 CSS3”的源码包,确实可以不写一行 JS,仅靠 CSS 动画在指定时间后隐藏覆盖层。方法是在覆盖层身上加一个延迟动画:
.loader-wrap { animation: loaderFadeOut 0.6s ease 2s forwards; pointer-events: none; } @keyframes loaderFadeOut { to { visibility: hidden; opacity: 0; } }2s是动画开始前等待的延迟,forwards表示动画结束后保留visibility: hidden和opacity: 0的最终状态。pointer-events: none是为了防止隐藏之后的覆盖层挡住页面点击。注意,这个方案只适合给演示稿用,因为它不关心真实页面资源到底加载完没有,到了 2 秒就自动消失。真实生产环境里,加载完成时机不可预测,正确的做法还是监听window.load后给覆盖层加一个.hidden类。我们后面会讲到怎么和框架结合,这里先明白自动消失的逻辑是用时间换空间。
4. 参数微调:六个把“科技感”做出来的关键开关
4.1 渐变主色:别只会紫蓝,试试撞色和径向叠加
默认的科技感配色是深紫、藏蓝加电光青,这是最不容易翻车的组合。但如果你不想页面跟别人的后台模板长得一模一样,我建议尝试两组配色:一是“深黑灰 + 霓虹粉 + 电光蓝”,整体偏暗色、局部高亮,发光效果会更突出;二是“墨绿 + 青色 + 荧光黄”,走的是赛博朋克风,但饱和度不要拉满。渐变写法可以改成两段叠加:
body { background-image: radial-gradient(circle at 20% 80%, rgba(0, 229, 255, 0.25), transparent 40%), linear-gradient(135deg, #0f0c29, #302b63, #24243e); background-size: 100% 100%, 300% 300%; }这里把径向渐变用来做局部光斑,线性渐变负责整体流动,两层背景通过background-size分隔,背景图列表顺序是从上到下叠加,所以第一层永远是盖在第二层上面。移动这两层的动画速度时,也只能整体一起动,想分层动需要再加包装结构。
4.2 background-size 决定了颜色流动的速度与层次
很多人调整background-size只知道200%和400%的区别,其实这里藏着“视觉层次”的秘密:尺寸放大得越多,同一段时间内扫过视口的颜色就越少,渐变过渡越柔和;尺寸放得太小,比如100% 100%,背景图与容器完全同宽,background-position怎么移动都看不出变化。常用取值我整理了一下:
| background-size | 视觉效果 | 适合场景 |
|---|---|---|
| 100% 100% | 静态渐变 | 不需要流动效果 |
| 200% 200% | 颜色变化明显,节奏紧凑 | 短等待、强调视觉冲击 |
| 300% 300% | 流动柔和,科技感稳定 | 加载时长 3 秒以上 |
| 400% 400% | 缓慢扫光,几乎不被察觉 | 长时间 loading 或登录背景 |
如果你发现渐变动画卡顿,先怀疑是不是background-size过大导致每帧绘制区域过大。移动端建议别超过 300%。
4.3 box-shadow 的发光强度:三层叠加比单一参数更可控
发光不是只靠调大 blur 半径就行,blur 调太大会让整个圆环糊成一片光雾。我的习惯是切成三层来控:
.loader { filter: drop-shadow(0 0 6px #00e5ff); } .loader-core { box-shadow: 0 0 8px #00e5ff, 0 0 20px rgba(0, 229, 255, 0.8), 0 0 40px rgba(0, 229, 255, 0.3); }第一层负责紧贴主体的高亮核心,第二层负责主要光晕,第三层负责带出“余晖”。三层透明度依次衰减,发光就有层次感。调的时候优先改第二层,因为它决定了你能看到的光晕大小;第一层保持不透明显得亮,第三层保持低透明度避免光污染。每次改完记得用浏览器缩放一倍看看,小屏上过度发光更容易刺眼。
4.4 动画时长与缓动:1 秒是个分水岭
加载动画的节奏直接决定等待观感。旋转圆环的周期建议在 0.8 到 1.2 秒之间。超过 1.5 秒,用户会以为动画卡住;低于 0.6 秒,视觉上容易产生眩晕感。背景渐变的流动建议放到 8 到 15 秒,因为它不是交互重点,只需要让人察觉到“背景在呼吸”即可。缓动方面:圆环旋转用linear,因为圆周运动的速度本身应该是匀速的;呼吸光点和背景渐变用ease-in-out或ease,因为它们的运动有折返点,匀速会显得生硬。
4.5 用 CSS 变量统一管理,把“改源码”变成“改配置”
我自己做这类动画,一定会把颜色、尺寸、动画时长抽出来,写进:root:
:root { --loader-size: 70px; --loader-border: 3px; --loader-color: #00e5ff; --loader-bg-speed: 12s; --loader-spin-speed: 1s; --loader-core-size: 12px; } .loader { width: var(--loader-size); height: var(--loader-size); border: var(--loader-border) solid rgba(0, 229, 255, 0.2); border-top-color: var(--loader-color); animation: spin var(--loader-spin-speed) linear infinite; } .loader-core { width: var(--loader-core-size); height: var(--loader-core-size); box-shadow: 0 0 12px var(--loader-color), 0 0 24px var(--loader-color); }这样接手你源码的人不再需要四处找选择器,直接在顶部改五个变量就能换主题。变量名一定要写清楚语义,否则还不如不用。我在开源项目里见到过的反面教材是直接用--color1、--color2这种命名,改半天不知道哪个是边框哪个是光晕。
4.6 给覆盖层加一层“毛玻璃”遮罩,把加载器融进背景
很多源码预览里加载器是浮在纯透明背景上的,这时候渐变背景是页面主体,加载器像贴上去的补丁。想要科技感更强,我一般会在.loader-wrap上加一个低透明度的背景滤镜:
.loader-wrap { background: rgba(10, 10, 30, 0.3); backdrop-filter: blur(6px); }注意backdrop-filter会把后面所有元素一起模糊,如果你的加载器需要保持锐利,就把模糊加在覆盖层的背景层上,把加载器放在独立元素里。另外这个属性在部分 Linux 浏览器上性能不稳定,如果发现整个页面拖动时发黏,就直接去掉backdrop-filter,用rgba(0, 0, 0, 0.35)模拟半透明遮罩效果。
5. 避坑与排查:按下 F5 后最容易遇到的五个翻车现场
5.1 背景一动不动?先查三样东西
现象:页面打开后渐变颜色是漂亮的,但完全没有流动感,整个背景像一张静态壁纸。
原因:最常见的是background-size被覆盖或写错。很多 UI 框架会给body设置background: #fff,这会把background-image整个清掉;其次是把@keyframes写在body选择器之前,但没有同名关键帧;第三是background-position百分比范围写窄了,比如只在0% 50%和20% 50%之间移动,视觉上看不出变化。
解决:用浏览器 DevTools 选中body,先看计算样式里background-image是否还存在。如果还在,就在 Keyframes 面板里确认gradientShift是否被触发。最后把动画幅度临时改成大跨度,比如0% 0%到100% 100%,立刻就能看出是否工作。
5.2 圆环转起来中心漂移,像个走得东倒西歪的钟表
现象:旋转的时候圆环不是围绕自身中心转,而是一直摆动,边缘忽大忽小。
原因:动画元素内部有子元素,比如.loader-core,它通过position: absolute; top: 50%; left: 50%居中,但负的margin-left或margin-top没写。当父元素旋转时,子元素中心不在父元素几何中心,于是整个圆环绕着错误的点旋转。另一种情况是这个元素不小心被设置成了display: inline,inline 元素无法正确参与绝对定位。
解决:给.loader加position: relative,给.loader-core的居中改用top: 50%; left: 50%; transform: translate(-50%, -50%),并且把transform和旋转动画放在不同层级。最常见做法是父级只负责旋转,子级只负责居中,不要把居中用的translate跟动画的rotate写在同一个元素上,否则一旦动画覆盖transform,居中就被冲掉了。
5.3 发光的圆环边缘闪得厉害,整个页面看起来都是噪点
现象:动画在白色背景上能看到一圈明显的闪烁残影,尤其深色背景上更刺眼。
原因:box-shadow或filter: drop-shadow每帧都在重新计算阴影区域。如果同时给多个元素加发光,合成器的压力增大,浏览器会降低渲染精度,边缘就开始“呲”。尤其是动画元素本身在旋转,阴影边缘本来就在变化。
解决:把发光属性集中到静态元素上,不要让发光元素自己旋转。比如给.loader-wrap加一个静态的伪元素光晕,圆环只管转。如果必须让发光跟随旋转,就保留一个filter: drop-shadow,不要既用box-shadow又用filter,两个都在搞模糊计算,等于开销翻倍。
5.4 Firefox 和移动端的显示差异,真的不是玄学
现象:Chrome 上效果完美,Firefox 里圆环不发绿光,或者移动端小屏里覆盖层底部地切掉一截。
原因:Firefox 对filter: drop-shadow的某些色值范围处理与 Chromium 不同,发光颜色偏灰。移动端则是因为100vh在浏览器导航栏收缩时高度计算不一致,覆盖层优先按视口初始高度定位,导航栏自动缩起后底部就被裁掉。
解决:发光颜色尽量用高饱和度的纯色,避免用rgba(0, 229, 255, 0.2)这种低透明度颜色作为发光源,因为低透明度颜色在 Firefox 里会被叠加成浑浊灰蓝。覆盖层改用min-height: 100dvh而不是100vh,同时保留100vh做兼容:
.loader-wrap { position: fixed; inset: 0; min-height: 100vh; min-height: 100dvh; }5.5 源码包放进自己项目里就被全局样式污染
现象:加载器的圆环变成了椭圆,颜色被全局按钮样式覆盖,或者边框消失。
原因:很多框架的 CSS reset 会把border-radius: 50%清掉,或者给所有div设置了box-sizing: border-box,导致原本算好的 70px 宽高变成 70px 含边框,内部空间变小,圆环比例看着不对。
解决:把加载器 CSS 的选择器前缀写重一点,用 class 嵌套锁定作用域:
.loader-wrap .loader { box-sizing: content-box; border-radius: 50%; width: 70px; height: 70px; }不要用div作为选择器,谁加载了你的源码都会被全局div { border: 0 }影响。必要时给覆盖层加一个固定的包裹类名,比如.loader-wrap--fixed,再同权重覆盖框架的全局样式。我踩过的坑多数不是动画逻辑写错,而是被别人的 reset 悄悄改掉了盒子模型。
6. 进阶用法:把动画嵌入真实项目,并验证它真的不卡顿
6.1 从纯 HTML 迁移到 Vite、Vue、React:结构怎么挪
源码包里的 HTML 结构可以直接拆进组件。如果是 React:
function Loader() { return ( <div className="loader-wrap"> <div className="loader"> <span className="loader-core" /> </div> </div> ); }把index.html里的<main>当作页面组件的内容,.loader-wrap保留成根级节点。CSS 直接复制到全局样式文件中,不要写在组件作用域里,因为@keyframes在多处使用时会遇到命名冲突,加上组件前缀更安全。如果是 Vue,同样把<div class="loader-wrap">放在App.vue顶层,再配合v-show控制显示。注意一点:CSS 变量定义在:root上,在框架里依然有效,不用额外处理。
6.2 用 Performance 面板确认动画是否掉帧
动画写得好不好,肉眼之外也要量化。打开浏览器 DevTools,切到 Performance 面板,开启录制,点刷新,等加载动画转完几圈后再停止。重点关注 FPS 曲线,如果长时间低于 50 甚至有红条区域,说明有主线程长任务。纯 CSS3 动画一般不会产生长任务,但如果出现,多半是background-position动画在窗口尺寸较大时绘制压力过高,或者覆盖层加了backdrop-filter导致大量像素被反复模糊。
另一种快速验证方式是在 Rendering 面板勾选 “FPS meter”,把设备模拟成 Moto G4 等低端手机,看动画是否明显掉帧。我一般会用这个方式重置自己对“性能正常”的判断,因为开发者电脑上的渲染能力不代表用户设备。
6.3 给“减少动态效果”用户一个交代
系统开启“减少动态效果”后,CSS3 动画会变得急促或者直接停止,但如果你强行动画,可能会让部分用户感到眩晕。这个时应该提供一个降级方案:
@media (prefers-reduced-motion: reduce) { .loader-wrap { animation: none; background: rgba(0, 0, 0, 0.6); } .loader, .loader-core { animation-duration: 0.001s; animation-iteration-count: 1; } }动画关掉之后,至少保留静态的圆环和光点,用静态视觉表明“正在加载中”。这是很多源码包不会替你考虑的点,但你会因此在团队评审里获得额外好感。
6.4 在覆盖层加上一行“加载中”文字,并让它有节奏感
加载动画不只是圆环,还有信息补充。给覆盖层加一行文案不会破坏科技感,反而能让用户明确知道系统在干什么。我常用的做法是不写额外 HTML,直接用.loader-wrap::after产出文字,并让它做一个淡入淡出的小动画:
.loader-wrap::after { content: "页面加载中 ···"; position: absolute; bottom: 28%; left: 50%; transform: translateX(-50%); color: rgba(255, 255, 255, 0.8); font-size: 14px; letter-spacing: 2px; animation: textBreath 1.6s ease-in-out infinite; } @keyframes textBreath { 0%, 100% { opacity: 0.4; } 50% { opacity: 1; } }如果加载时间不确定,我会把“···”做成三个点循环出现,又不想引入 JS,就用三段式@keyframes控制content并不保险——伪元素内容不能跨关键帧改变。所以实际发布时我一般保留“页面加载中”五个字,省略号直接用静态的“…”放在紧邻位置,避免为了一个省略号去写一堆 hack。做完之后记得回 DevTools 确认文案没被覆盖层背景吞掉。其实到了这一步,你已经比很多“下载源码改个颜色就发朋友圈”的人做得更彻底了:你理解了渐变流动的原理,知道哪些参数会引发性能问题,也踩过了盒子模型和浏览器差异的坑。我自己的习惯是一直把 CSS 变量和降级动画留着,等哪天上线前临时改色号,才后悔当初没有顺手多写那三行变量。希望帮到你。
本文还有配套的精品资源,点击获取