关键是在HTML标签预设loading类并用CSS控制显隐,再通过JS移除该类,辅以超时兜底;避免依赖link.onload,注意SSR冲突及字体/CSS变量延迟。

如何用 loading 类避免 CSS 加载完成前的页面闪烁
关键不是“等 CSS 加载完再显示”,而是让浏览器在 CSS 尚未就绪时,主动隐藏内容或降级样式——靠的是在 或 上预设一个加载状态类,再用 CSS 规则控制显隐。
常见错误是只在 里放 ,然后指望它“静默加载”。实际上,CSS 加载期间浏览器会先渲染无样式的 HTML(FOUC),尤其在慢网或高延迟下非常明显。
- 必须在
标签上初始添加class="loading",例如: - 在所有外部 CSS 加载并解析完成后,用 JS 移除该类:
document.documentElement.classList.remove('loading') - 对应的 CSS 规则要覆盖关键区域,比如:
.loading body { visibility: hidden; }或.loading * { opacity: 0; }(后者需注意可访问性) - 不要用
display: none,否则会触发重排,且可能干扰 SSR 渲染或 SEO
link.onload 和 link.onerror 的兼容性陷阱
想监听 CSS 加载完成?别只信 link.onload。它在 Firefox 旧版、Safari 15.4 之前都不支持,而且即使支持,也只在 CSS 成功解析后触发——若 CSS 里有语法错误或 @import 失败,onload 不会触发,onerror 也不一定可靠。
- 稳妥做法是:用
link.addEventListener('load', ...)+link.addEventListener('error', ...),但必须在link插入 DOM 前绑定事件 - 多个 CSS 文件时,不能简单计数等待——应使用
Promises.all包装每个 link 的加载 Promise,但需手动封装(因为原生 link 没有 Promise 接口) - 更简单的兜底:加个超时(如 3s),防止因网络中断或资源 404 导致永远不移除
loading类
为什么不用 rel="preload" 替代 rel="stylesheet"
rel="preload" 只是提前下载,不触发解析和应用;它不会阻止渲染,也不会自动转为样式表。直接替换会彻底失效——页面始终无样式。
- 正确组合是:
- 但
onload在preloadlink 上同样存在兼容问题,且 Safari 对该写法支持不稳定 - 如果用了 HTTP/2 Server Push 或 HTTP/3,
preload价值进一步降低,反而增加头部复杂度 - 真正省事的方案仍是:保留
rel="stylesheet",配合loading类 + 超时兜底
服务端渲染(SSR)场景下 loading 类的冲突点
Node.js 渲染的 HTML 已含完整样式,首屏本不该闪。但若客户端 JS 还是执行了 remove('loading'),可能造成样式抖动——尤其当 SSR 输出的 HTML 已经没有 loading 类时。
- 服务端渲染时,应判断是否已注入全部 CSS(如通过
renderToString后插入内联 style),若已完备,就不该输出class="loading" - 客户端 JS 移除类前,先检查是否存在:
if (document.documentElement.classList.contains('loading')) { ... } - Next.js / Nuxt 等框架通常内置 FOUC 防御,但自定义
_document.tsx或app.html时容易绕过机制,得手动对齐
最易被忽略的是字体加载和 CSS 变量初始化——哪怕样式表加载完成,@font-face 或 :root 中的 var(--color) 仍可能滞后,这时仅靠 link.onload 并不足够。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











