因为默认阻塞渲染,浏览器会暂停html解析和dom构建直至css下载解析完成;关键css须内联于且≤14kb,非关键css可用media属性或preload+onload异步加载。

为什么放在里反而卡住首屏
浏览器解析 HTML 时,遇到 <link rel="stylesheet"> 就会暂停 DOM 构建和渲染,直到该 CSS 下载、解析完成。哪怕它只用在页脚,只要在 里,整个 HTML 解析就停在 开始前——这不是“加载慢”,是“被强制暂停”。实测一个 200KB 的 main.css 在弱网下耗时 800ms,期间页面完全白屏。
关键点:rel="stylesheet" 默认就是 render-blocking;media 属性才是解耦开关:
-
media="print"或media="(min-width: 1024px)"(当前不匹配)→ 异步加载,不阻塞 -
media="all"(默认)、media="screen"→ 始终阻塞 - 多个
<link>按 DOM 顺序串行加载,前一个没就绪,后一个不会发起请求
关键CSS必须内联,且不能超 14KB
首屏必需样式(如 header、hero banner、按钮、@font-face)要提取出来,直接写进 的 <style></style> 标签里。不是整站 CSS,通常只占原始体积的 10%–30%。
内联位置和写法有硬性要求:
- 必须放在所有
<link rel="stylesheet">之前,否则仍可能被后续资源拖慢 - 禁止在
<style></style>中使用@import——它会触发额外 HTTP 请求并阻塞解析 - 若启用 CSP,需加
nonce(如<style nonce="abc123"></style>)并在响应头中同步配置,比'unsafe-inline'更安全 - 内联内容建议控制在 ~14KB(gzip 后约 4–8KB),避免跨 TCP 包影响 TTFB
非关键CSS怎么异步加载才真正不阻塞
折叠区域、模态框、图表库、后台模块等非首屏样式,应延迟加载。原生方案比 JS 动态插入更可靠:
- 用
<link rel="stylesheet" media="print" onload="this.media='all'">:媒体不匹配时异步加载,匹配后立即生效;IE 不支持onload,需降级 fallback - 拆分文件 + 条件
media:比如dark-theme.css设为media="(prefers-color-scheme: dark)",desktop.css设为media="(min-width: 1024px)" - 慎用
<link rel="preload" as="style">:它只提前下载,不改变应用时机;必须配对真实rel="stylesheet",且两个href字符串必须完全一致(大小写、路径都不能差)
preload 和 @import 是最容易踩坑的两个点
<link rel="preload" as="style"> 常被误当成“加速加载”,但只写它不写对应 rel="stylesheet",样式根本不会应用;而 @import 在 CSS 文件里引入其他样式,会串行阻塞,比 <link> 多一次网络往返,实测拖慢 FCP 300ms+。
还有几个隐蔽但高频的问题:
- 把第三方 UI 库的 CSS 放在自定义样式之后 → 后加载的规则直接覆盖前面的,不是优先级问题,是层叠顺序问题
- 在
里写<link>→ 部分浏览器仍会阻塞渲染,且顺序不可靠 - 多个
preload写满关键 CSS → 带宽竞争反而挤掉 HTML 或首屏图片,只预加载 1–2 个最核心的即可
真正起效的优化,不在堆技巧,而在识别哪些 CSS 真正参与了首屏渲染——Chrome DevTools 的 Network 面板禁用缓存后刷新,盯着首屏元素对应的样式规则看,比任何工具都准。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











