弱网下文本不显示的根源是cssom构建阻塞,需从html结构、资源加载策略、降级逻辑三方面协同优化:首屏文本须直写于body最前;关键css内联且最小化;字体图片提权;弱网探测基于fetch响应时间而非online。

弱网下文本不显示,不是 CSS 没加载完,而是浏览器卡在 CSSOM 构建环节,DOM 里明明有 <h1></h1> 和 <p></p>,用户却看到白屏或骨架屏——这问题必须从 HTML 结构、资源加载策略、降级逻辑三处同时切。
首屏文本节点必须写死在 HTML 最前面,不包裹、不延迟、不隐藏
浏览器解析 HTML 是流式的,<main></main> 越靠前,文本越早进入渲染流程。任何“优化”式封装都会断掉这条通路。
-
<h1></h1>、<p></p>、<button></button>必须直接出现在内,不能包在<div class="container"> 或 <code><section data-lazy="true"></section>里 - 禁用
display: contents替代文本容器——Safari 15.4 以下版本会丢文本上下文,导致空白 - 不要用
visibility: hidden或opacity: 0控制首屏文本显隐,这些样式仍需等待 CSSOM 就绪才能生效 - 所有文本级元素必须带
lang属性(如<p lang="zh-CN"></p>),否则弱网下字体 fallback 时易触发重排(CLS) - 用
critters或类似工具提取 LCP 元素(如<h1></h1>父容器、正文段落)的 layout / color / font-size / line-height 等基础规则,内联为<style></style> - 动画、栅格、悬停效果、
@keyframes、复杂媒体查询全部剥离,改用<link rel="stylesheet" href="non-critical.css" media="print" onload="this.media='all'">延迟注入 - 绝对禁用
@import:它强制串行加载,等价于把多个 CSS 请求压进一个长队列,弱网下雪上加霜 - 外链 CSS 加
fetchpriority="low",避免和文本资源争带宽 - 所有字体文件(
.woff2)必须加fetchpriority="high",并配合rel="preload"提前声明 - 首屏
<h1></h1>所在<section></section>的背景图,加fetchpriority="high"+loading="eager" - 非可视资源(埋点脚本、广告 SDK)统一设
fetchpriority="low",不抢文本通道 - 图片必须带
decoding="async",防止解码阻塞主线程;小图标优先用 inline SVG,绕过 HTTP 请求 - 探测地址选轻量静态资源(如
/ping?_t=123456789),超时设为1500ms(比常规 5s 更激进) - 连续两次响应耗时 >
800ms→ 标记为弱网,立刻启用简化模式(跳过推荐模块、关闭动画、注入内联 fallback 样式) - 降级样式必须由 JS 动态注入,不能写死在 HTML 里,否则 SSR 会污染 SEO 和爬虫
- 提示文案插入到
<div id="network-status" aria-live="polite"></div>中,用textContent赋值,防 XSS
关键 CSS 必须内联,非关键样式用 media 隔离或延迟加载
把整个 style.css 内联进 是典型误区:体积大、无法卸载、仍阻塞渲染。真正要内联的,只是 LCP 元素所需的最小样式集。
字体与图片资源必须提权,否则 fallback 会撑开布局
.woff2 字体加载慢,系统字体 fallback 时字宽不同,会引发布局位移(CLS)。背景图若没及时加载,也会让 <h1></h1> 所在容器高度塌缩,拖慢文本可见时间。
弱网探测与降级必须由 fetch 主动触发,不能依赖 navigator.onLine
navigator.onLine 只反映系统接口状态,WiFi 已连但服务器 RTT 达 2s 时它仍返回 true,完全不可信。真实降级必须基于响应时间感知。
最常被忽略的一点:结构优化和资源策略必须同步生效。只调 fetchpriority 不改 DOM 顺序,或只写对了 <main></main> 位置却不剥离关键 CSS,效果都会打折扣——弱网下的文本可见性,是 HTML、CSS、JS 三层结构共同决定的执行结果,不是单点优化能解决的。











