最轻量兼容的异步css加载方式是,利用浏览器对不匹配媒体类型的低优先级处理实现异步下载,onload中必须立即切换media并清空onload防止重复触发。

直接用 media="print" 切换是最轻量、兼容性最好的异步加载方式,但必须配 onload 回调,否则样式永远不会生效。
为什么 media="print" 能绕过阻塞
浏览器只对 media="all" 或匹配当前设备的媒体类型(如 screen)强制同步解析 CSS;print 是一个真实但当前不匹配的媒体类型,所以下载不阻塞 HTML 解析和渲染。等文件加载完成,再把 media 改回 "all",样式就立刻参与 CSSOM 构建。
注意:media="none" 理论上也行,但部分旧版 Firefox 和 IE 不会触发 onload,实测稳定性不如 print。
-
media="print"是规范支持的合法值,所有现代浏览器都可靠触发onload - 不能省略
this.onload = null,否则重复插入或缓存复用时可能多次执行 - 如果页面本身有
@media print规则,这个 trick 不会影响它们——两者互不干扰
onload 回调里必须做哪些事
关键不是“改 media”,而是确保 DOM 状态干净、样式能被正确拾取。只写 this.media = 'all' 不够稳妥。
- 先清空
onload处理器:this.onload = null,防止二次触发 - 再设置
this.media = 'all',让浏览器重新评估媒体查询 - 推荐加一层防护:
if (this.media !== 'all') this.media = 'all',避免因脚本重入导致异常 - 不要用
setTimeout模拟延迟切换——网络波动下不可靠,且没必要
实际插入时容易漏掉的边界情况
你写的那行 <link rel="stylesheet" href="main.css" media="print" onload="..."> 很可能在某些场景下失效。
- 如果该
link标签是通过 JS 动态插入的(比如在DOMContentLoaded后),需手动调用link.addEventListener('load', ...),因为内联onload在动态创建时不生效 - 多个同名 CSS 并发加载时,插入顺序影响层叠优先级——务必按依赖顺序 append,别用
document.write - 服务端渲染(SSR)页面中,若首屏依赖该 CSS,仍会出现 FOUC;这类样式应保留在同步
<link rel="stylesheet">中 - 使用
import语法或 CSS-in-JS 的项目,此方法仅适用于纯静态 CSS 文件,不适用于构建产物带 hash 的路径(需配合构建插件处理)
真正要注意的是:media 切换只是“卸下阻塞”,不是“消除依赖”。关键视觉区域的样式一旦异步,用户第一眼看到的就是无样式的 HTML 结构——这个权衡没法靠技巧绕过,只能靠拆分策略来判断哪些能动、哪些必须锁死同步加载。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











