CSS样式表必须放在HTML的<head>中,否则会导致无样式渲染、闪屏和布局跳动;因CSS是渲染阻塞资源,浏览器需构建CSSOM并与DOM合并成渲染树才能绘制。

不行,css 样式表不能放在 HTML 底部(比如 </body> 之前),否则会导致页面先无样式渲染、闪屏、布局跳动,甚至部分浏览器阻塞交互。
为什么浏览器会等 CSS 加载完才渲染?
因为 CSS 是“渲染阻塞资源”——浏览器需要构建 CSSOM(CSS 对象模型),再和 DOM 合并成渲染树(Render Tree),才能开始绘制。如果 <link rel="stylesheet"> 放在底部,DOM 已解析完毕,但 CSSOM 还没就绪,浏览器只能暂停绘制,直到 CSS 下载并解析完成。
- Chrome / Safari / Firefox 都会延迟首次绘制(
First Paint)直到关键 CSS 就绪 - 即使 JS 已执行,
document.body.style.color这类读取也可能返回旧值——因样式未生效 -
DOMContentLoaded事件不等待 CSS,但load事件会等(取决于是否含img等)
哪些“放底部”的写法看似可行实则危险?
以下写法都不可取:
<body> <h1>内容</h1> <p>正文</p> <link rel="stylesheet" href="main.css"> <!-- ❌ 在 body 内,非 head --> </body>
<body>
<h1>内容</h1>
<script>
const link = document.createElement('link');
link.rel = 'stylesheet';
link.href = 'main.css';
document.head.appendChild(link); <!-- ✅ 动态插入到 head,但仍是异步加载,不阻塞 DOM 解析 -->
</script>
</body>- 直接
<link>在<body>中:HTML 规范允许,但浏览器仍会同步加载并阻塞渲染,且可能触发重排 - 用 JS 动态插入:不阻塞初始 HTML 解析,但样式应用滞后,用户可见白屏或 FOUC(Flash of Unstyled Content)
- 用
@import在 CSS 文件里引用其他 CSS:比<link>更慢,是串行加载,且同样阻塞渲染
正确加载位置和优化方式
必须把关键 CSS 的 <link> 放在 <head> 内,并按需优化:
立即学习“前端免费学习笔记(深入)”;
- 关键样式(Above-the-Fold)可内联到
<style>标签中,避免 HTTP 请求 - 非关键 CSS 用
media属性隔离,例如:<link rel="stylesheet" href="print.css" media="print">,这类不会阻塞屏幕渲染 - 需要异步加载的非关键 CSS,用
rel="preload"+onload注入:<link rel="preload" href="non-critical.css" as="style" onload="this.onload=null;this.rel='stylesheet'">
- 避免在
<head>中混用<script>(尤其是同步脚本),它会阻塞后续<link>的下载
最易被忽略的一点:哪怕你把 css 放在 <head>,如果服务器响应慢、CDN 未命中、或用了未压缩的 sourceMap 文件,照样卡渲染——位置只是前提,加载性能才是关键。










