能监听,但只对link外链CSS有效;@import嵌套、内联样式、跨域样式表无法被onload/onerror捕获,事件须在插入head前绑定,并建议加5秒超时兜底。

能监听,但只对 link 标签外链的 CSS 有效;@import 嵌套加载、内联样式、跨域样式表都无法被原生事件捕获。
用 onload 和 onerror 监听外链 CSS 加载结果
这是最直接、兼容性最好的方式,适用于通过 document.createElement('link') 动态插入的样式表。
-
onload在 HTTP 状态码为 200 且 CSS 内容解析完成时触发(注意:不保证样式已应用到 DOM) -
onerror在请求失败(404/403/网络中断等)或 MIME 类型错误(如返回 HTML 而非text/css)时触发 - 必须在插入
document.head之前绑定事件,否则部分浏览器(如旧版 Safari)会漏掉事件 - 建议加超时兜底,因为某些场景(如服务器返回 200 但空内容)不会触发
onload或onerror
示例:
function loadCSS(url) {
return new Promise((resolve, reject) => {
const link = document.createElement('link');
link.rel = 'stylesheet';
link.href = url;
const timeoutId = setTimeout(() => reject(new Error('CSS load timeout')), 5000);
link.onload = () => {
clearTimeout(timeoutId);
resolve();
};
link.onerror = () => {
clearTimeout(timeoutId);
reject(new Error(`CSS load failed: ${url}`));
};
document.head.appendChild(link);
});
}
为什么不能靠 document.styleSheets 判断是否加载完成
这个 API 返回的是当前页面所有样式表列表,但它存在几个关键缺陷:
你接手一个需求时,是不是经常这样:"改一个小字段 → 结果把不相关的代码也改了"、"需求说得很模糊 → 做着做着发现跑偏了"、"数据库加个字段 → 上线才发现漏了数据兼容"、"做了个新功能 → 一个月后自己都忘了当时怎么设计的"、"写到一半被中断 → 再回来不知道从哪继续";这个 Skill 就是专门解决这些问题的。 它会自动探测你的项目环境(JDK、Spring Boot、ORM、数据库、前端框架),记在
立即学习“Java免费学习笔记(深入)”;
- 跨域样式表会出现在
document.styleSheets中,但读取其cssRules会抛出SecurityError,无法判断是否真正加载成功 - 即使样式表已加载,
cssRules可能为空(例如 CSS 语法错误、空文件),此时轮询会误判为“未加载” - 样式表插入后立即检查
document.styleSheets.length增加,并不能说明内容已就绪——它只是 DOM 节点存在了 - IE 低版本中
sheet属性可能延迟挂载,需配合attachEvent('onload'),但该行为已被现代标准废弃
遇到 @import 该怎么办
原生 onload 对 @import 完全无感知:主 CSS 加载成功,里面 @import 的资源失败也不会触发任何事件。
- 服务端尽量避免深度
@import,构建时用工具(如 PostCSS、Webpack)提前合并 - 若必须动态处理,得用
fetch()先拉取主 CSS 内容,正则或 AST 解析出所有@importURL,再逐个发起请求并监听 - 开发期可借助
performance.getEntriesByType('resource')查看实际发出的 CSS 请求,但无法区分哪些是@import触发的
真正难的不是监听事件,而是意识到:你监听到的只是“HTTP 层面的加载完成”,不是“样式已渲染生效”。如果后续逻辑依赖样式计算(比如 getBoundingClientRect() 或伪元素内容),仍需额外等待一次 requestAnimationFrame 或使用 MutationObserver 观察目标元素 computed style 变化。

















