内联关键CSS能真正压住FOUC,因为它绕过网络请求,在HTML解析阶段同步提供首屏必需样式,使浏览器在首次绘制前就构建好CSSOM,实现有样式的首帧渲染;其体积需≤10KB、不可加media属性、须置于head最顶部,并通过Coverage工具验证有效性。

为什么内联关键CSS能真正压住FOUC
FOUC不是加载慢导致的“偶然问题”,而是浏览器在首次绘制(first paint)前没拿到首屏必需样式规则的必然结果。内联
注意:这不是把整个main.css复制进
- 内联体积必须≤10KB(移动端保守值),否则会阻塞HTML解析本身
- 不能加media属性(如media="(min-width:768px)"),否则浏览器跳过阻塞
- 必须放在最顶部,早于任何<script>或<link></script>
- 手动维护极易过期,应使用
critters(Vite插件)或critical(CLI)自动生成
如何验证你内联的CSS是否真“关键”
靠猜不行。打开Chrome DevTools → Coverage tab → 刷新页面 → 查看哪些CSS规则被实际执行(绿色高亮)。Coverage报告会明确告诉你:当前页面加载中,哪些选择器被用到了,哪些是“dead code”。
重点关注以下几类容易误判的情况:
立即学习“前端免费学习笔记(深入)”;
-
article p:nth-child(2n+1)这类复杂伪类:可能只在滚动后才触发,不应内联 - 带
@import的CSS文件:Coverage不会追踪导入链,需单独分析被导入文件 - CSS变量定义(
:root { --color-primary: #333; }):如果变量只在非首屏组件中使用,就不该进内联块 - 字体声明(
@font-face):若字体仅用于折叠区域或懒加载模块,移出内联
内联之后,非关键CSS怎么安全加载
内联只是解决“首帧有样式”,后续样式仍要加载。但直接放在
里,可能因体积大或CDN延迟导致回流重绘。更稳妥的做法是让它“预加载但不阻塞”:- 用
<link rel="preload" as="style" href="non-critical.css" onload="this.rel='stylesheet'">,注意onload必须在插入DOM前绑定,否则Safari可能漏掉 - 或更兼容的写法:
<link rel="stylesheet" href="non-critical.css" media="print" onload="this.media='all'">,利用media="print"让浏览器预加载但不应用,加载完成再切换 - 务必配
<noscript><link rel="stylesheet" href="non-critical.css"></noscript>兜底,防JS失效 - 避免在JS里用
document.write()或appendChild()动态插入——这会让浏览器完全错过预加载时机
最容易被忽略的两个细节
一是Content-Type响应头。哪怕你把CSS内联了,如果外链CSS返回的是text/plain而非text/css,浏览器会拒绝解析,降级为异步加载,FOUC照常发生。检查Network面板里每个CSS请求的Response Headers。
二是loading类的控制粒度。只写.loading body { visibility: hidden; }不够——某些第三方脚本或Web Component可能绕过body直接操作document.documentElement。更保险的是:.loading * { opacity: 0.01; } + transition: opacity 0.1s,配合3秒超时强制移除loading类,防止因资源404或网络中断卡死。


















