首屏文本不能等CSS加载完才显示,因为浏览器需先构建关键CSSOM才能生成渲染树,而外部CSS在弱网下可能pending超2秒,导致白屏;关键CSS须内联且精简,非关键CSS异步加载。

为什么首屏文本不能等CSS加载完才显示
因为浏览器必须等关键CSSOM构建完成才能生成渲染树,而外部CSS在弱网下可能卡在pending状态超2秒——此时<body>里已有标题、段落等文本节点,但用户看到的仍是白屏或骨架屏。这不是“样式没出来”,是整个渲染流程被阻塞在CSSOM环节。
- 关键CSS必须内联进
<head>,且只包含首屏文本所需的font-size、line-height、color、margin等基础声明,体积控制在10KB以内 - 非关键CSS改用
<link rel="preload" as="style" onload="this.rel='stylesheet'">异步加载,避免阻塞 - 禁用
@import引入CSS,它会隐式创建串行依赖,弱网下放大延迟
骨架屏DOM结构怎么写才不塌、不抖、不闪
90%的骨架屏塌陷是因为没设尺寸,只靠background-color撑不开流式布局。浏览器把空<div>当0×0渲染,真实内容插入必然重排。
- 图片占位必须用
aspect-ratio: 16 / 9(现代)或padding-top: 56.25%+position: relative+ 子元素position: absolute - 文字行占位用
line-height × 行数设高度,比如三行正文就写height: calc(1.5em * 3),禁用height: 100% - 所有骨架块加
overflow: hidden,否则background-position动画会溢出圆角边界 - 绝对禁用
<img>、<svg>、::before/::after插文字——它们触发加载、解析或被读屏器误读
骨架和真实内容切换时最容易踩的坑
不是“替换不干净”,而是DOM结构错位导致hydration失败、focus丢失、第三方插件未重初始化。Vue/React里一个class名拼错,就会让骨架残留或内容闪跳。
- 骨架项与真实列表项必须严格对齐:同级元素数量、
class名、data-id属性、甚至注释位置都一致 - 替换用
<template>+replaceWith(),别用innerHTML = ''再拼字符串——后者丢事件监听、表单值、滚动位置 - 加载完成必须调用
element.remove()销毁骨架节点,而非display: none或visibility: hidden,否则动画持续消耗CPU - SSR场景下,服务端已吐真实HTML,客户端需判断
document.readyState === 'complete'跳过初始骨架,否则必闪一下
无限滚动中骨架如何接续才不漏、不卡、不丢状态
触发时机不准、DOM结构不一致、替换方式粗暴,三者叠加会让骨架在页尾突然消失、新内容错位、滚动焦点丢失。
立即学习“前端免费学习笔记(深入)”;
- 用
IntersectionObserver监听<div id="infinite-trigger">,rootMargin: '200px'提前触发,留出网络与渲染缓冲 - 页尾占位符必须独立于骨架列表之外,且不参与任何动画,否则
IntersectionObserver会误判可见性 - 服务端返回数据必须带
hasMore: true/false,前端据此决定是否继续挂载observer,避免白发请求 - 低配设备加
will-change: transform优化动画,同时用@media (prefers-reduced-motion: reduce) { animation: none; }兜底
骨架屏不是“加个灰色div就完事”,它是和真实DOM共用同一套尺寸计算逻辑的视觉契约。一旦结构、尺寸、切换时机有一处没对齐,用户感知到的就是闪、抖、卡,而不是“正在加载”。



















