最轻量稳妥的异步css加载方式是,利用media="print"触发浏览器低优先级异步下载且不阻塞渲染,onload后切回"all"使样式生效,需置于中并确保onload内清除事件防止重复执行。

直接用 <link rel="stylesheet" href="xxx.css" media="print" onload="this.media='all'; this.onload=null;"> 就行,不用 JS、不阻塞渲染、兼容所有现代浏览器——这是目前最轻量也最稳妥的第三方 CSS 异步加载方式。
为什么 media="print" 能绕过渲染阻塞
浏览器只对 media="all" 或匹配当前设备的媒体类型(如 screen)强制同步解析 CSS;print 是一个真实但当前不匹配的媒体类型,所以下载完全不参与关键渲染路径。等文件加载完成触发 onload,再把 media 改回 "all",样式就立刻进入 CSSOM 构建流程。
常见错误现象:
-
media="bogus"或media="only x"在旧版 Safari 中不触发onload - 漏写
this.onload = null,缓存复用或重复插入时会多次执行切换逻辑 - 把这行
<link>写在里——必须放在中,否则预加载器无法识别
onload 回调里必须做哪些事
关键不是“改 media”,而是确保 DOM 状态干净、样式能被正确拾取。只写 this.media = 'all' 不够稳妥。
- 必须加
this.onload = null,防止二次触发 - 推荐加防护判断:
if (this.media !== 'all') this.media = 'all',避免脚本重入导致异常 - 不要用
setTimeout模拟延迟切换——网络波动下不可靠,且没必要
动态插入时容易漏掉的边界情况
你写的那行 <link rel="stylesheet" href="main.css" media="print" onload="..."> 很可能在某些场景下失效。
- 如果是通过 JS 动态创建的
<link>(比如在DOMContentLoaded后),内联onload属性不会生效,得手动绑定:link.addEventListener('load', () => { ... }) - 多个同名 CSS 并发加载时,插入顺序影响层叠优先级——务必按依赖顺序
append,别用document.write - 服务端渲染(SSR)页面中,若首屏依赖该 CSS,仍会出现 FOUC;这类样式应保留在同步
<link rel="stylesheet">中 - 使用构建工具(如 Webpack/Vite)的项目,若 CSS 路径带 hash,需配合插件处理路径,否则缓存或 CDN 场景下可能 404
media="print" 和 rel="preload" 的本质区别
media="print" 是利用浏览器对不匹配媒体类型的低优先级处理实现异步下载;rel="preload" 是显式声明高优先级预加载资源,但必须三要素齐全:rel="preload" + as="style" + onload 切换 rel,漏掉任一环节就等于没写。
真正要注意的是:media 切换只是“卸下阻塞”,不是“消除依赖”。第三方 CSS 一旦异步,用户第一眼看到的就是无样式的 HTML 结构——这个权衡没法靠技巧绕过,只能靠拆分策略来判断哪些能动、哪些必须锁死同步加载。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











