Chrome/Firefox支持link.onload/onerror,Safari仅支持onerror;可靠方案是结合事件监听与getComputedStyle轮询检测样式是否生效,并设5秒超时。

link标签的onload和onerror在Chrome/Firefox中确实可用,但Safari不支持onload
现代浏览器中,<link rel="stylesheet"> 元素的 onload 和 onerror 事件在 Chrome、Firefox、Edge(Chromium)中能可靠触发,但 Safari(截至 Safari 17.6)**完全不触发 onload**,仅支持 onerror。这意味着仅靠 onload 判断“加载成功”在 Safari 下会永远挂起。
根本原因:Safari 将 CSS 加载视为异步但不可观测过程,不派发 load 事件——这不是 bug,而是规范未强制要求,而 Safari 选择不实现。
判断CSS是否真正生效,得看样式是否被应用到DOM上
比监听事件更可靠的方案,是检测目标样式是否实际影响了某个元素的计算样式。例如,你动态插入一个带 test-class 的 <div>,并在 CSS 中定义 <code>.test-class { opacity: 0.001; },然后轮询 getComputedStyle(el).opacity 是否变为 "0.001"。
- 必须确保测试元素已挂载到 DOM(
document.body.appendChild(testEl)) - 避免使用可能被重置的通用属性(如
color),优先选低干扰、高唯一性的声明,比如font-family: "css-loaded-123";或margin-top: 9999px; - 轮询间隔建议 ≥ 16ms(1帧),用
requestAnimationFrame比setTimeout更稳妥 - 设置超时(如 5s),防止因网络中断或CSS语法错误导致无限等待
兼容性兜底:onerror + onload + 计算样式检测三者组合
单一机制都不保险,生产环境应分层判断:
立即学习“Java免费学习笔记(深入)”;
- 立即绑定
link.onerror:只要触发,说明加载失败(404、CORS、解析错误等) - 对 Chrome/Firefox/Edge,同时监听
link.onload并 resolve Promise - 无论事件是否触发,在
link插入后启动样式检测逻辑(带超时) - 任一路径成功(onload 触发 或 样式检测命中),即标记为“引入成功”;超时 + onerror 触发 → 失败
示例关键逻辑:
const link = document.createElement('link');
link.rel = 'stylesheet';
link.href = '/path/to/style.css';
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')); };
document.head.appendChild(link);
// 同时启动样式检测(略去具体轮询实现)
注意:@import、CSSOM注入、preload link不适用此监听方式
这个方案只适用于 <link rel="stylesheet"> 标签动态插入场景。以下情况不适用:
-
@import在 CSS 文件内部 —— 完全无事件可监听,也无法提前感知 - 通过
document.styleSheets[...].insertRule()注入规则 —— 属于运行时操作,不涉及网络加载 -
<link rel="preload" as="style">—— preload 只预取,不自动应用,且无onload事件
如果你控制不了 link 标签插入时机(比如由第三方 SDK 注入),或 CSS 是通过构建工具内联的,那“监听是否引入成功”本身就不成立——它压根没走网络加载流程。


















