
通过在 HTML 中同步执行主题初始化逻辑,提前为 元素设置对应 class,可彻底避免页面加载时默认样式短暂显示导致的“闪屏”(FOUC)。
通过在 html `
` 中同步执行主题初始化逻辑,提前为 `` 元素设置对应 class,可彻底避免页面加载时默认样式短暂显示导致的“闪屏”(FOUC)。
现代 CSS 主题系统常依赖 :root 自定义属性与 HTML 元素上的类名(如 lightMode/darkMode)联动。但若主题切换逻辑延迟至 DOMContentLoaded 或 document.onreadystatechange === 'complete' 阶段执行,浏览器已开始渲染未应用主题样式的初始 DOM —— 此时 尚无 lightMode 或 darkMode 类,:root 回退到无 class 的默认样式(如浅色背景),造成肉眼可见的“白屏闪动”或“颜色跳变”,即 Flash of Unstyled Content(FOUC)。
根本解法:将主题初始化逻辑前置到 内联执行
不要等待 DOM 加载完成,而应在 中立即运行主题判断与 class 设置逻辑。这样可在浏览器解析并渲染 前,就为 元素打上正确 class,确保所有后续样式(包括 body { background: var(--background); })从首帧起即生效。
✅ 正确做法(推荐):
<meta charset="UTF-8"><title>Felps Todo Dia Atlas</title><!-- 内联初始化主题,早于 body 渲染 --><script type="module">
// 直接在 head 中执行,不依赖任何 DOM 事件
const getStoredColorMode = () => {
try {
return localStorage.getItem('colorMode') || 'auto';
} catch {
return 'auto';
}
};
const applyColorMode = (mode) => {
document.documentElement.classList.remove('lightMode', 'darkMode');
if (mode === 'dark') document.documentElement.classList.add('darkMode');
else if (mode === 'light') document.documentElement.classList.add('lightMode');
else {
const isDark = window.matchMedia?.('(prefers-color-scheme: dark)').matches;
document.documentElement.classList.add(isDark ? 'darkMode' : 'lightMode');
}
};
const colorMode = getStoredColorMode();
applyColorMode(colorMode);
// 可选:监听系统偏好变更(仅对 auto 模式生效)
if (colorMode === 'auto' && window.matchMedia) {
const mediaQuery = window.matchMedia('(prefers-color-scheme: dark)');
mediaQuery.addEventListener('change', () => {
applyColorMode('auto');
});
}
</script><style>
:root {
--text: #030202;
--background: #f0efef;
}
:root.lightMode {
--text: #030202;
--background: #f0efef;
}
:root.darkMode {
--text: #f9f4f4;
--background: #100f0f;
}
body {
color: var(--text);
background-color: var(--background);
margin: 0;
font-family: system-ui, sans-serif;
}
</style><!-- 页面内容 -->
⚠️ 注意事项:
-
禁止异步延迟执行:
document.onreadystatechange、DOMContentLoaded、window.onload均晚于首屏渲染,无法规避 FOUC; -
避免模块导入阻塞:若必须使用外部模块(如
import { updateColorMode } from './colorModeModule.js'),请确保该模块为type="module"且置于中——但更推荐内联脚本,因其零网络请求、最高优先级执行; -
localStorage 安全兜底:
try/catch包裹读写操作,防止无痕模式或禁用 localStorage 时抛错; -
是唯一目标元素:务必操作document.documentElement(而非document.body),因:root对应的就是; - 移除冗余 class:每次只保留一个主题 class,避免样式冲突或继承异常。
总结:FOUC 不是 CSS 或 JS 的缺陷,而是执行时机不当所致。将主题判定与 class 注入逻辑“前移至 内联脚本”,是最轻量、最可靠、兼容性最佳的解决方案。它不增加额外请求、不依赖第三方库,且对 SSR 和静态站点同样有效。










