You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

HTML页面深色模式切换优化:解决加载闪白与状态持久化问题

深色模式切换闪白问题优化方案

我正在用HTML/CSS/JavaScript制作作品集网站,实现深色模式切换功能时遇到了难题。最初采用独立CSS文件切换主题,通过localStorage存储名为dark的布尔值保持状态,但页面刷新或跳转时会先显示浅色主题,再切换为深色,出现恼人的闪白现象。随后改用按钮替代复选框,通过为body添加darkmode类修改CSS变量实现切换,但仍存在加载闪白问题,希望得到优化方案。

最初的JavaScript代码

window.onbeforeprint = darkMode();

function darkMode() {
    /*===== Dark Mode =====*/
    let theme = localStorage.getItem('dark');
    let element = document.getElementById("theme-style");

    // Check if state is initialized
    if (theme != null) {
        setTheme(theme);
    }

    // Set the css for the theme-style sheet
    function setTheme(theme) {
        if (theme === "true") {
            element.href = 'assets/css/dark.css';
            document.getElementById("darkmode-toggle").checked = true;
        } else {
            element.href = 'assets/css/styles.css';
            document.getElementById("darkmode-toggle").checked = false;
        }
    }

    // If dark mode is selected
    document.getElementById("darkmode-toggle").onclick = function checkClickFunc() {
        localStorage.setItem('dark', document.getElementById("darkmode-toggle").checked);
        if (document.getElementById("darkmode-toggle").checked) {
            element.href = 'assets/css/dark.css';
        } else {
            element.href = 'assets/css/styles.css';
        }
    }
}

已尝试的无效方案

  • 使用window.onbeforeprint函数
  • 将JavaScript代码移至HTML头部
  • 设置脚本type="module"

修改后的JavaScript代码

// check for saved "darkMode" in localStorage
let darkMode = localStorage.getItem("darkMode"); 

const darkModeToggle = document.querySelector("#dark-mode-toggle");

const enableDarkMode = () => {
  // Add the class to the body
  document.body.classList.add("darkmode");
  // Update darkMode in localStorage
  localStorage.setItem("darkMode", "enabled");
}

const disableDarkMode = () => {
  // Remove the class from the body
  document.body.classList.remove("darkmode");
  // Update darkMode in localStorage 
  localStorage.setItem("darkMode", null);
}
 
// If the user already visited and enabled darkMode
// start things off with it on
if (darkMode === "enabled") {
  enableDarkMode();
}

// When someone clicks the button
darkModeToggle.addEventListener("click", () => {
  // get their darkMode setting
  darkMode = localStorage.getItem("darkMode"); 
  
  // if it not current enabled, enable it
  if (darkMode !== "enabled") {
    enableDarkMode();
  // if it has been enabled, turn it off  
  } else {  
    disableDarkMode(); 
  }
});

有效优化方案

1. 提前执行主题判断逻辑(核心解决闪白)

闪白的根本原因是浏览器先渲染默认浅色样式,之后JavaScript才完成主题切换。要避免这个问题,必须让主题判断在页面开始渲染前执行。

将以下代码放在HTML的<head>标签最顶部,确保在所有CSS引入之前运行:

<script>
(function() {
  const savedDarkMode = localStorage.getItem("darkMode");
  // 若本地存储开启深色模式,直接给根元素添加类
  if (savedDarkMode === "enabled") {
    document.documentElement.classList.add("darkmode");
  }
})();
</script>

这样浏览器解析CSS时,会直接应用darkmode类对应的样式,不会出现先渲染浅色再切换的延迟。

2. 用CSS变量统一管理主题样式

确保所有主题相关样式通过CSS变量定义,避免切换文件带来的加载延迟:

/* 默认浅色主题变量 */
:root {
  --bg-color: #ffffff;
  --text-color: #333333;
  --link-color: #2563eb;
}

/* 深色主题变量 */
.darkmode {
  --bg-color: #1a1a1a;
  --text-color: #f5f5f5;
  --link-color: #60a5fa;
}

/* 全局元素使用变量 */
body {
  background-color: var(--bg-color);
  color: var(--text-color);
  transition: background-color 0.3s ease, color 0.3s ease; /* 可选:添加平滑过渡 */
}

a {
  color: var(--link-color);
}

3. 移除动态加载CSS文件的逻辑

之前切换独立CSS文件的方式会引入网络请求延迟,必然导致闪白。改用CSS变量+类切换的方式更高效,无额外加载成本。

4. 可选:兼容系统主题偏好

若想优先遵循用户的系统深色模式设置,可以扩展主题判断逻辑:

<script>
(function() {
  let savedDarkMode = localStorage.getItem("darkMode");
  // 若本地存储无设置,判断系统主题偏好
  if (savedDarkMode === null) {
    savedDarkMode = window.matchMedia("(prefers-color-scheme: dark)").matches ? "enabled" : null;
  }
  if (savedDarkMode === "enabled") {
    document.documentElement.classList.add("darkmode");
  }
})();
</script>

内容的提问来源于stack exchange,提问作者Darien

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.10 05:54:51