资讯文章 资讯 · NEWS
首屏那几秒不是图慢,是 CSS 堵住了:目录站的关键 CSS 该怎么拎出来
2026-10-23 约 1,717 字 预计阅读 4 分钟 yiyunkj
首
先说明白一件事:CSS 是渲染阻塞资源。浏览器拿到 HTML 之后,必须把外部样式表下载完、解析成 CSSOM,才会开始画第一个像素。你的分类页做得再轻量,只要头部挂着一个几百 KB 的样式表,移动端首屏还是白等着。

图片来源:网络,版权归原作者所有,侵权请联系删除
先别急着提取,先看看有没有用不上的 CSS
关键 CSS 这套技术有个前提:你的样式表确实大到值得拆解。但很多站的问题是另一回事——整个 Bootstrap 或者 Element UI 全量引进来,实际用到的不到三成。这种情况下,先把没用的删掉收益更大,而且没有后续维护成本。
判断方法很简单,Chrome DevTools 的 Coverage 面板,打开页面看红色部分占比。超过一半没用上,优先做清理;清理完还是大,才考虑提取。
| 做法 | 收益 | 维护成本 | 建议优先级 |
|---|---|---|---|
| 删掉用不上的 CSS | 中到高 | 低 | 第一优先 |
| 按页面类型拆 CSS | 中 | 低 | 第二优先 |
| 内联关键 CSS | 中 | 高 | 前两项做完再看 |
第二项对目录站特别合适。首页、分类页、条目详情页、搜索结果页这四类模板的样式重合度其实不高,各自打一个 CSS 文件,比全站共用一个文件有效得多,而且 Bundler 一般能自动做。
真要提取:14KB 是个参考线
web.dev 给的经验值是:为了让首次渲染的往返次数尽量少,内联的首屏 CSS 压缩后控制在 14KB 以内。这个数字背后的道理是 TCP 慢启动初期一个拥塞窗口的大小,超了就得多一个来回,抵消掉省下的那次 CSS 请求。
目录站的页面结构整齐,其实很好达到。头部导航、分类栏、首屏三到四张卡片的样式,通常有六七 KB 就够了。难点在于「首屏」这三个字在判断时要同时考虑移动端和桌面端视口——只按桌面宽度算,手机上打开照样闪一下。
常用的几个工具:
- Critical——能自动检测样式表,支持多分辨率,可以直接内联输出
- Critters——webpack / Vite 插件形态,能顺带做 preload 切换
- Penthouse——样式量大或者有动态插入 DOM 的情况用它,基于 Puppeteer
工具帮你做提取,但它不知道哪些内容是你的真正首屏。提取完还是要人看一遍,重点确认两个地方:一是 LCP 元素的样式有没有被提成「非关键」排到后面去了,二是下拉展开、悬停这类交互的首帧样式有没有漏。
剩下的 CSS 怎么加载
主流做法是 preload + onload 切换:
<link rel="preload" href="/css/main.css" as="style" onload="this.rel='stylesheet'">
<noscript><link rel="stylesheet" href="/css/main.css"></noscript>
noscript 那份兜底别省。前面几批文章里提过,搜索引擎的渲染有延迟,加上禁用 JS 的老客户端,只靠 JS 切换的方案会有一小撮访问者是白板。
还有个更老的模式:media="print" onload="this.media='all'"。现在不推荐优先用它——语义绕,而且部分环境下 print 媒体查询的资源优先级会被压得比 preload 低。能上新写法就别留着旧的。
FOUC 比慢 300 毫秒更伤
提取得太狠,就会出 FOUC:首屏先出来一堆没样式的裸内容,几百毫秒后再「啪」地套上样式。用户对这种闪动的反感程度高于多等一会儿。
宁可内联的样式多包一点,也不要为了压数字让首屏闪。真算不准就偏保守,把首屏往下再延伸一屏的样式也包含进去。
另外 FOUC 和 CLS 是联动的。异步加载的完整样式里如果有改变布局的规则(比如卡片高度、导航固定位),加载完成后会把已经渲染好的内容推走,指标直接扣分。解决办法是在关键 CSS 里就把尺寸和位置相关的规则写死,后加载的部分只补颜色、字号这类不影响布局的属性。
部署之后怎么保持不失效
关键 CSS 最大的问题不是做出来,是三个月后有人改了页脚样式但忘了重新提取,于是线上出现半截不一致的状态。
- 把提取写进构建步骤,不要做成手动脚本
- 提一项 CI 检查:产出 HTML 里内联样式块的大小超过阈值就报警
- 模板大改之后重新跑一遍 Coverage,确认关键集合没偏
如果这套流程短期没人维护,那就别做提取,先把用不上的 CSS 删干净。半成品的关键 CSS 方案比它解决的问题还多。