内联纯色 background-color 到 <head> 的 <style> 中可彻底消除白屏;需预加载背景图并确保路径与 CSS 一致;使用渐进式 JPEG 提升加载连续性。

直接给 body 或背景容器设一个 solid 背景色,比任何 JS 预加载都管用——白屏本质是首帧渲染时背景透明/未定义,浏览器只能画白。
必须内联 background-color 到 <head> 的 <style> 里
外部 CSS 文件(哪怕只有一行)会触发网络请求和解析延迟,首帧已渲染完毕。只有内联样式能抢在 HTML 解析阶段就被识别:
-
background-color值必须是纯色,如#1a1a1a、rgb(26, 26, 26),禁用url()、渐变、变量 - 写在
<head>内的<style>中,不能靠 JS 插入或框架动态注入 - 如果页面主色调是深灰,别硬套
#000;选最接近的 solid 色,避免视觉跳变 - 验证方式:Network 面板切 Offline,刷新看顶部是否还闪白
用 background-image 替代 <img> 并预设宽高比
背景图不占文档流,但容器若没高度,图片加载完成前就是“空盒子”,后续撑开必然跳。仅靠 background-size: cover 不解决占位问题:
- 优先用
aspect-ratio: 16 / 9,配合width: 100%和height: auto - iOS 15.4 之前需 fallback:
padding-top: 56.25%+position: relative+ 子元素position: absolute; inset: 0 - 父容器禁用
height、max-height或flex: 1,它们会覆盖aspect-ratio - 浮动布局要加
display: flow-root或overflow: hidden防塌陷
切换背景图前必须预加载,且路径完全一致
JS 动态改 element.style.backgroundImage 或 React/Vue 绑定 :style="{ backgroundImage }" 时,浏览器会先清旧图、再发新请求——中间空白期就是闪的来源:
立即学习“前端免费学习笔记(深入)”;
- 用
new Image().src = 'url.jpg'触发缓存,等onload后再切换样式 - 多个图批量预加载:
['a.jpg', 'b.jpg'].forEach(src => { const i = new Image(); i.src = src; }) - 路径必须和 CSS 中
url()完全一致:含 CDN 域名、hash 版本、大小写,否则缓存不命中 - 滚动中频繁切换?改用 class 切换 + 预加载完成状态控制,别在
scroll回调里直接设backgroundImage
渐进式 JPEG 比预加载更底层有效
即使做了所有预加载和宽高比,基准式 JPEG(Baseline JPEG)仍可能造成“上半截先显、下半截后出”的撕裂感。渐进式 JPEG 会先画模糊全图,再逐层清晰,视觉连续性更好:
- 用
PIL.Image.save(..., progressive=True)转换 PNG/JPEG 为渐进式 - PS 导出时勾选 “Progressive” 选项
- 注意:WebP 和 AVIF 原生支持渐进加载,但兼容性不如渐进式 JPEG(IE11+ 支持)
- 别用 base64:体积膨胀约 33%,首屏 HTML 加载反而更慢
最容易被忽略的是三件事:内联 background-color 的时机(必须在 <head> 里)、预加载路径和 CSS 中 url() 的字符串一致性、以及父容器偷偷加的 height: auto 或 flex: 1 覆盖了 aspect-ratio。这些点卡住,其他优化全白搭。


















