必须设rel="stylesheet",否则浏览器不加载CSS;需配href有效路径并插入document.head防FOUC;推荐用onload/onerror监听,IE需轮询cssRules。

必须设 rel="stylesheet",否则浏览器根本不会加载 CSS —— 这是 90% 动态引入失败的根源。
为什么 link.rel 必须是 "stylesheet"
浏览器只认 rel="stylesheet" 这个值来触发 CSS 加载;设成 "style"、"css"、甚至漏写,link 元素会留在 DOM 里但完全静默,不发请求、不报错、也不生效。
- 不是所有属性都可选:
rel和href是硬性组合,缺一不可 -
type="text/css"在现代浏览器中已非必需,但若需兼容 IE8 或某些 CMS 环境,建议保留 - 不要用
innerHTML插入 link 字符串(如document.head.innerHTML += '<link rel="stylesheet" href="...">'),它绕过元素生命周期,onload事件无法绑定
插入位置必须是 document.head
插到 document.body 后或末尾,部分浏览器(尤其是 Safari 和旧版 Chrome)会延迟应用样式,导致 FOUC(页面闪白)或样式错乱。
- 即使
head尚未解析完成,document.head在 DOM ready 前就已存在,可安全使用 - 极端情况(如 head 尚未生成)可用回退逻辑:
document.head || document.documentElement,但极少需要 - 避免在
document.write结束后往body插入 —— 不仅 FOUC 风险高,还可能被浏览器忽略 media 查询
如何避免重复插入同一份 CSS
多次调用 loadCSS('/theme-dark.css') 会导致多个相同 link 节点,引发冗余请求、样式覆盖冲突,甚至内存泄漏。
立即学习“Java免费学习笔记(深入)”;
- 用
document.querySelector(<code>link[href="${url}"]) 判断最简单,但注意相对路径问题 - 更健壮的做法是转为绝对 URL 比较:
new URL(url, location.href).href - 若 CSS 带版本参数(如
style.css?v=2.1.0),需确保每次传入的url字符串完全一致,否则去重失效 - 服务端返回 304 时,浏览器仍会复用缓存,但 DOM 中的
link节点仍是新节点 —— 所以去重逻辑不能依赖网络响应,只能靠 DOM 查询
onload 和 onerror 的真实行为
link.onload 在现代浏览器中可靠,但 onerror 在跨域场景下会被静默丢弃(CORS 错误不触发该事件),仅控制台报错。
- 不要写
link.addEventListener('load', ...)——link元素不支持事件委托式监听,必须用link.onload = fn - 想封装 Promise,得手动包装:
new Promise((resolve, reject) => { link.onload = resolve; link.onerror = () => reject(new Error('Load failed')); }) - 对跨域 CSS,
onerror失效时,可配合fetch(href, { method: 'HEAD' })预检(注意跨域限制),或改用服务端代理 - IE ≤ 11 不支持
onload,需轮询link.sheet?.cssRules,但该方式开销大、不推荐用于新项目
真正容易被忽略的是:动态插入的 CSS 不会阻塞 JS 执行,但会阻塞后续渲染 —— 如果你在 setTimeout 或点击回调里插入大量 CSS,用户操作反馈可能明显卡顿。别只盯着“能不能加载”,更要盯住“什么时候开始影响渲染”。


















