浏览器允许 写在 ,但会导致FOUC、布局重排和解析中断;DOMContentLoaded 等 CSSOM 完成因 CSS 是渲染阻塞资源,而 JS 默认仅解析阻塞;推荐用 media 属性或 onload 动态激活样式,而非挪动位置。

为什么浏览器要求 必须写在 里
不是“必须写在 ”,而是写在 中间会导致不可控的 FOUC(Flash of Unstyled Content)和布局重排,浏览器会主动阻塞渲染直到 CSSOM 构建完成。HTML 规范允许 出现在 ,但实际效果极差——现代浏览器遇到 body 内的样式表时,会暂停解析 HTML、回退并同步加载该 CSS,造成严重性能抖动。
DOMContentLoaded 为何等 CSS 而不等 JS
因为 CSS 是渲染阻塞资源(render-blocking),而 JS 默认是解析阻塞资源(parser-blocking)。关键区别在于:JS 执行可能修改 DOM 或 CSSOM,所以浏览器必须等 CSSOM 就绪后,才能安全执行后续 JS(尤其当 JS 读取 getComputedStyle 或 offsetHeight 时)。这意味着:
-
在中,会触发 CSS 加载 → 阻塞 HTML 解析 → 阻塞DOMContentLoaded -
放在且无async/defer,也会阻塞解析,但它不参与 CSSOM 构建 - 如果 JS 放在
底部,它不会阻塞 CSS 加载,但一旦执行时访问样式相关属性,仍需等待 CSSOM 完成
把 放在 会发生什么
实测 Chrome/Firefox 会立即中断 HTML 解析,发起 CSS 请求,并将该 CSS 视为“关键样式表”强制同步加载——即使它本应是非关键资源。典型问题包括:
- 页面白屏时间延长:浏览器已解析部分 DOM,却因新样式表重新构建 CSSOM,清空已生成的渲染树
- 触发额外 layout:DOM 已部分渲染,CSS 加载后引发全量重排(reflow)
- 无法被 preload 干预:
只对中声明的资源有效 - SSR/SEO 风险:服务端渲染时若动态注入 body 内样式,客户端 hydration 可能因 CSSOM 不一致导致样式闪烁
HelloWorld
真正可控的加载策略:media 和 onload 回调
想避免阻塞又保持样式可用性?别挪位置,改用特性控制加载时机:
立即学习“前端免费学习笔记(深入)”;
- 用
media="print"声明非关键样式,浏览器初始不加载,打印时才 fetch(可配合onload切换为all) - 用
实现异步加载 + 后续激活 - 注意:IE 不支持
onload,需 fallback 用onreadystatechange - 慎用
rel="preload"+as="style":它只提前请求,不自动应用,仍需手动插入或切换link的media
CSS 加载机制的核心不是“放哪”,而是“何时构建 CSSOM”。 是约定俗成的安全区,不是语法限制;真正容易被忽略的是:哪怕你把 放对了位置,只要没配好 media、preload 或 HTTP 缓存头,它照样会成为首屏瓶颈。










