CSS首次加载时页面“闪一下”或样式错乱的根本原因是FOUC:浏览器阻塞渲染等待CSS加载,若CSS延迟则DOM先裸奔渲染,后重绘;解决关键是提取并内联首屏必需的关键CSS(Critical CSS),配合字体预加载与缓存策略。

为什么 CSS 首次加载时页面会“闪一下”或样式错乱
根本原因是浏览器渲染流程中,link 引入的 CSS 默认是阻塞渲染的,但若样式表体积大、路径深、或经过 CDN 缓存未命中,style.css 下载和解析就会延迟,导致 DOM 已渲染但无样式(白屏/文字裸奔),等 CSS 加载完才突然重绘——这就是常说的 FOUC(Flash of Unstyled Content)。
关键点在于:不是所有 CSS 都需要首屏就加载;只有影响首屏布局与可读性的那部分,才必须“抢在 渲染前就位”。
如何提取并内联“关键 CSS”(Critical CSS)
手动提取容易漏、难维护,推荐用工具自动化。常见做法是:基于真实 URL + 设备宽度(如 1366x768 或移动端 375x667),用 puppeteer 或 critical 库爬取首屏所需样式规则,输出为内联 。
-
critical https://yoursite.com/ --inline --base ./dist --width 375 --height 667(生成并自动内联) - 构建时集成:Webpack 可配
critters-webpack-plugin,Vite 可用vite-plugin-critical - 注意:提取后仍需保留原始
,否则后续路由或交互样式会缺失
内联 Critical CSS 后,怎么避免重复加载和缓存失效
内联样式无法被浏览器单独缓存,每次 HTML 更新都会重新传输;而外部 CSS 文件能长期缓存。所以不能把全部 CSS 都内联。
立即学习“前端免费学习笔记(深入)”;
- 只内联影响首屏渲染的规则:比如
header、.hero、button基础尺寸/颜色、字体加载声明(@font-face)等 - 避免内联含
@media (min-width: 768px)的整块规则——除非你确认该断点内容在首屏可见 - 不要内联通过 JS 动态插入的 class 对应样式(如
.is-open),它们不参与初始渲染 - 检查 DevTools → Network → 找到 HTML 请求,看响应体里
标签是否明显膨胀(超过 ~15KB 就该警惕)
遇到 font-display: swap 和关键字体没生效怎么办
即使内联了 @font-face,若字体文件本身加载慢,文字仍可能先用系统字体渲染再替换(造成跳动)。这时仅靠 Critical CSS 不够,需配合字体加载策略。
- 确保内联的
@font-face中包含font-display: optional或swap,且src指向已优化的 woff2 路径 - 对核心品牌字体(如 logo 文字),可考虑转成 SVG 或静态图片——比等字体加载更稳
- 使用
rel="preload"提前拉字体: - 注意:
crossorigin属性不可省,否则字体 preload 会静默失败
critical,结果内联的还是旧规则,首屏反而更乱。










