最稳方案是将loading元素置于<body>开头并用内联CSS固定定位,因HTML自上而下解析,末尾插入会导致DOM建完才渲染、引发闪屏;须用position:fixed+z-index防遮挡,flex居中更可靠,动画需预置在<head>style中避免Safari闪烁,且load事件需配8秒超时兜底以防资源失败卡死。

直接在 <body> 开头插入一个固定定位的 loading 元素,用内联 CSS 控制初始显示,再通过 window.addEventListener('load', ...) 隐藏它——这是最稳、兼容性最好、且不依赖构建工具的方案。
为什么不能把 loading 写在 <body> 末尾?
页面是从上到下解析 HTML 的。如果 <div id="loading"> 写在 </body> 前面,浏览器得先把整个 DOM 树建完才渲染它,用户会先看到空白或错位内容,再“闪”出动画——这比没动画还伤体验。
正确做法是把它放在 <body> 最开头:
<body>
<div id="loading" style="position: fixed; top: 0; left: 0; width: 100%; height: 100%; background: #fff; z-index: 9999; display: flex; justify-content: center; align-items: center;">
<div class="spinner"></div>
</div>
<!-- 其他内容 -->- 必须加
position: fixed和z-index,否则可能被后续元素遮住 -
display: flex居中比text-align: center+line-height更可靠,尤其在移动端 - 背景色建议用纯白
#fff或与品牌一致的底色,避免暗色背景下看不见 spinner
@keyframes spin 动画写在哪?怎么避免 Safari 闪烁?
动画定义必须出现在 loading 元素被创建之前,所以推荐直接写在 <head> 里的 <style> 中,而不是外链 CSS——外链加载有延迟,可能导致首帧空白。
立即学习“前端免费学习笔记(深入)”;
关键修复 Safari(iOS 15–16)偶发白屏/掉帧:
.spinner {
width: 40px;
height: 40px;
border: 4px solid #eee;
border-top-color: #333;
border-radius: 50%;
animation: spin 1s linear infinite;
transform: rotate(0deg);
transform-style: preserve-3d;
backface-visibility: hidden;
}- 只靠
transform: rotate()在 Safari 上不稳定;transform-style: preserve-3d+backface-visibility: hidden是目前最兼容的硬件加速提示 - 别用
will-change: transform,低内存设备(如旧 iPad)上反而拖慢首帧 -
border-radius: 50%缺一不可,否则转的是方框
用 window.addEventListener('load', ...) 隐藏的坑在哪?
这个事件等的是所有资源(图片、CSS、JS、iframe)全部下载并解析完成,对多数静态页够用;但它有个硬限制:如果页面里有失败的资源(比如 404 图片),load 就永远不会触发,loading 会一直卡着。
更健壮的做法是加超时兜底:
<script>
const loading = document.getElementById('loading');
const hideLoading = () => { loading.style.display = 'none'; };
<p>window.addEventListener('load', hideLoading);
setTimeout(hideLoading, 8000); // 8秒强制隐藏
</script>- 不要把 script 放在
<head>里且不加defer,否则会阻塞 HTML 解析,导致 loading 元素根本没机会渲染出来 - 如果用了第三方脚本(如统计代码),它们加载慢也可能拖长
load时间,超时兜底很必要 - 别用
DOMContentLoaded替代load,它不等图片和样式表,隐藏太早会导致图片加载时页面“跳动”
真正难的不是让圆圈转起来,而是让它在所有设备、所有网络条件下都“准时出现、安静退场”——时机控制比动画本身重要得多。



















