应优先选用 intersectionobserver,因其天然防抖、不阻塞渲染、支持阈值控制;scroll 需手动节流且易卡顿漏加载;ie11 降级为 domcontentloaded 后延时加载。

滚动监听触发 css 加载的时机选 scroll 还是 intersectionObserver
用 scroll 事件监听滚动再加载 CSS,容易卡顿、重复触发、漏加载;intersectionObserver 是更稳的选择,它天然防抖、不阻塞渲染、支持懒加载边界控制。
实际场景中,比如页面底部有个「评论区」模块,它的样式文件 comments.css 不需要首屏就加载,但用户滑到该区域时得立刻生效——这时用 intersectionObserver 观察对应容器的 boundingClientRect 进入视口即可。
-
scroll事件需手动节流(如requestIdleCallback或setTimeout),否则频繁触发会拖慢主线程 -
intersectionObserver的threshold设为0表示元素哪怕只露出 1px 就触发,设为0.1则需 10% 进入才加载,更保守 - 若目标元素可能被
display: none或visibility: hidden控制,intersectionObserver无法检测,得配合状态标记兜底
动态注入 CSS 的安全写法:避免 innerHTML 和重复插入
别用 document.body.innerHTML += '<style>...'</style>,会重排整个 body;也别无脑 appendChild 同一个 link 多次,导致样式重复或竞态。
正确做法是先查 DOM 是否已有对应 link 标签(靠 id 或 data-css-key 属性识别),没有再创建并插入到 head。
立即学习“前端免费学习笔记(深入)”;
- 用
document.createElement('link'),设rel="stylesheet"、href和唯一id(如css-comments-lazy) - 插入前检查:
document.getElementById('css-comments-lazy')存在就跳过 - 不要设
media="print"后再切回"all"来“激活”,部分浏览器不触发重绘;直接设media="all"即可
加载失败时的 fallback 处理:CSS 请求超时 ≠ 样式未生效
link 元素的 onerror 能捕获 404、跨域等加载失败,但无法感知 CSS 解析错误(如语法错)或规则被更高优先级覆盖——后者才是线上最常被误判为“没加载成功”的原因。
- 给
link加onload和onerror回调,失败时记录日志,但别自动重试(可能无限循环) - 验证是否真生效:用
getComputedStyle(el).color检查关键属性,比单纯看link.sheet.cssRules.Length更可靠 - 若依赖该 CSS 的 js 逻辑(如初始化评论组件)必须等样式就绪,建议加个短延时
setTimeout+ 属性检测双保险,而不是纯靠onload
IE11 兼容性下怎么绕过 intersectionObserver 缺失
IE11 没 intersectionObserver,也不能用 scroll 频繁监听——滚动卡顿会特别明显。稳妥做法是降级为“首屏后延时加载”,用 setTimeout + document.readyState 组合。
- 先判断:
typeof IntersectionObserver === 'undefined',为true则走降级逻辑 - 降级方案:等
DOMContentLoaded触发后setTimeout(() => { loadCSS(...) }, 800),800ms 是经验值,避开首屏渲染高峰 - 别用
document.body.scrollTop做滚动位置判断——IE 下要兼容document.documentElement.scrollTop
真正麻烦的不是加载动作本身,而是样式注入后 DOM 重绘时机和 JS 执行顺序的耦合。很多问题表面是“CSS 没生效”,实际是 JS 在样式还没解析完就去读 offsetHeight 了。