关键CSS指首屏视口内参与绘制的必需样式,如.header、.hero-banner、h1等,而非整页所有类;需结合响应式断点、媒体查询及真实场景验证,避免依赖Coverage面板或整包提取。

关键CSS没提对,内联就白干;preload写错as属性,浏览器直接当普通资源下载——闪屏问题从来不是“加不加”的问题,而是“加什么、怎么加、加给谁”的问题。
怎么判断哪些CSS算“关键”
首屏渲染必需的样式,不是整张设计稿里所有用到的类,而是HTML解析到
<body>后、用户视口内(above-the-fold)真正参与绘制的那部分。比如
.header、
立即学习“前端免费学习笔记(深入)”;
.hero-banner、
立即学习“前端免费学习笔记(深入)”;
h1可能关键,但
.footer、
立即学习“前端免费学习笔记(深入)”;
.modal一定不关键。
- 别信Coverage面板导出的“绿色代码”——它只反映当前交互路径,不等于首屏真实依赖(比如暗色模式、登录态组件可能被漏掉)
- 工具提取要显式声明响应式断点和媒体查询,例如用
penthouse时必须传
--width 375 --height 667和
--include-media="(prefers-color-scheme: dark)" - 构建时若主CSS含
@import,critters默认不处理,得提前用
postcss-import合并,否则关键CSS提取不全
内联关键CSS的三个硬约束
内联不是把CSS塞进
<style>标签就完事。它必须满足三件事:不阻塞渲染、不破坏HTML结构、能随HTML缓存独立更新。
- 必须加
media="print"并配合
onload切换:<style media="print" onload="this.media='all'">...</style>,否则会阻塞首次绘制
- 内联内容里不能出现未转义的
</style>字符串(比如CSS注释里写了
/* */),会导致HTML解析中断
- 体积控制在≤15KB,HTTP/2下过度内联反而抵消多路复用优势;超过就该走
preload+异步加载
preload + onload回填为什么总失效
常见错误是只写
<link rel="preload" href="main.css">,缺了
as="style"——浏览器根本不识别这是样式资源,优先级拉不起来,也不会复用于后续的
<link rel="stylesheet">。
- 正确写法必须带
as="style"和
onload:<link rel="preload" href="critical.css" as="style" onload="this.onload=null;this.rel='stylesheet'">
- IE完全不支持
preload,必须降级:同一文件写两遍,第二遍去掉
preload,仅保留
rel="stylesheet" - 不要对整个打包后的
bundle.css做preload——它体积大、到达晚,起不到“关键”作用;只预加载提取出的那部分
critical.css
loading类兜底比opacity更可靠
靠
document.documentElement.style.opacity = '1'移除透明度,看似简单,实则隐患多:Safari对
link.onload支持不稳定,CSS语法错误时事件根本不会触发,页面可能永远黑着。
- 推荐用
class="loading"初始挂载在
<html>上,再配CSS规则如
.loading body { visibility: hidden; } - JS移除类时必须加超时兜底(比如3秒),防止网络异常或404导致loading状态卡死
- 多个CSS文件时,别数link个数来判断完成;用
Promise.all包装每个link的加载逻辑,但得自己封装Promise(原生link没.then接口)
最难的从来不是技术实现,而是每次发版前重新评估“关键”边界——设备尺寸变、AB实验分组变、用户登录态变,都可能让昨天有效的关键CSS今天变成噪音。这个判断没法自动化,得靠真实设备+真实网络条件下的反复验证。


















