内联关键CSS必须紧贴<meta charset>之后首个位置,以确保在HTML解析早期即参与CSSOM构建,抢在外部CSS前完成首屏渲染;若被任何<link>或<title>阻塞,则触发白屏延迟。
浏览器按顺序解析HTML,<style>的位置决定它能否抢在外部CSS前参与渲染树构建。如果<style>被任何<link rel="stylesheet">或<title>标签挡住,解析就会先暂停去加载那个外部CSS——哪怕它只有一行body { margin: 0 },也会导致白屏。
常见错误现象:First Contentful Paint没改善甚至变差,DevTools里Parse HTML阶段卡在main.css请求上。
<meta charset="utf-8">之后第一个非<meta>标签必须是<style>
<style>里写@import,它会触发同步网络请求,等价于新增一个阻塞点{ width: 375, height: 667 }),不是截取main.css开头10KB<template>还是display: none
display: none只是隐藏绘制,DOM节点照常构建、CSSOM照常匹配、布局计算照常触发——它不解决阻塞,只掩盖问题。真正要的是“不创建”。
使用场景:轮播图下方的推荐列表、Tab页未激活面板、评论区、侧边栏。
立即学习“前端免费学习笔记(深入)”;
<template>包裹非首屏结构,它完全不参与DOM构建和样式计算data-html属性暂存字符串,切换时再innerHTML挂载document.createElement在循环中动态插入高样式开销元素(如display: table),它们会强制同步LayoutRendering > FPS Meter和Layers面板可验证首屏区域是否混入大量隐藏节点defer和async选错会导致DOM操作失败两者都不阻塞HTML解析,但执行时机完全不同:defer按书写顺序在DOMContentLoaded前执行;async下载完立刻执行,不保证顺序,且可能早于DOM构建完成。
常见错误现象:脚本报document.getElementById is null,或事件监听器没绑上。
<script defer src="a.js"></script>和<script defer src="b.js"></script>严格按顺序执行async只适合完全独立逻辑(如统计、广告SDK),不能依赖DOM或其它脚本输出async脚本放在<head>里又没加defer——它可能在<body>还没解析完就执行<script>console.log(1)</script>)默认阻塞,除非显式加defer或async
CSS解析本身很快,但某些写法会显著增加CSSOM树节点数量或匹配开销,间接拉长渲染树合成时间。
影响实际首屏渲染的不是“看起来多复杂”,而是浏览器在样式计算阶段要遍历多少节点、比对多少规则。
* {}会匹配所有节点,强制重算全部样式,应彻底禁用article section div p em不拖慢解析,但极大增加匹配成本,优先用BEM类名扁平化@media (min-width: 768px)未命中时规则仍进CSSOM,只是不参与当前渲染树——暗色模式、打印样式等非首屏媒体查询建议拆到单独<link>并设media属性@import在CSS文件中会串行加载,打断并行下载;必须用<link>替代关键点不在“要不要优化”,而在于:内联位置错一位、<template>漏掉一个节点、defer写成async、选择器多嵌套一层——这些毫秒级偏差,在高并发场景下会直接放大为跳出率拐点。