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

如何为PC端网站实现深色/浅色模式的localStorage持久化?

深色模式刷新恢复问题的适配解决方案

你的代码存在几个关键问题导致刷新后模式重置:

  • 监听的元素ID拼写错误(darkModeToggle vs 实际的dark-mode-toggle)
  • 切换逻辑与localStorage保存逻辑脱节,用了无意义的bodyCssProps类
  • 重复绑定点击事件,导致逻辑冲突

以下是适配你现有代码的修正版,直接替换即可:

修正后的HTML

<header>
  <div class="controls">
    <p>Light/Dark Mode</p>
    <label class="toggle-switch" for="dark-mode-toggle">
      <input type="checkbox" id="dark-mode-toggle" name="theme">
      <div class="toggle-switch-border">
        <div class="toggle-switch-dot"></div>
      </div>
    </label>
  </div>
</header>

修正后的CSS(无需改动,保留原代码)

.toggle-switch {
  display     : inline-flex;
  align-items : center;
  font-family : 'Sora', sans-serif;
  font-weight : 700;
  font-size   : .875rem;
  cursor      : pointer;
  }
.toggle-switch-border {
  display             : inline-flex;
  align-items         : center;
  width               : 60px;
  height              : 36px;
  border              : 1px solid var(--primary); 
  border-radius       : 20px;
  box-sizing          : border-box;
  margin-inline-start : 8px;
  }
.toggle-switch input {
  display: none;
  }
.toggle-switch-dot {
  width         : 28px;
  height        : 28px;
  border-radius : 50%;
  background    : var(--primary);
  transform     : translate3d(3px, 0, 0);
  transition    : transform .1s ease-in-out;
  }
.toggle-switch input:checked + * .toggle-switch-dot {
  transform : translate3d(26px, 0, 0);
  }
body {
  color              : var(--primary);
  font-family        : "Work Sans", sans-serif;
  background         : var(--background);
  transition         : color 0.5s, background 0.5s;
 
  --dark-background  : #253a52;
  --dark-primary     : white; /*#FFFFE3*/
  --dark-link        : #A9FE75;
 
  --light-background : white; /*#ffffe3*/
  --light-primary    : #253a52;
  --light-link       : #1348da;
 
  --background       : var(--light-background);
  --primary          : var(--light-primary);
  --link             : var(--light-link);
  }
a {
  color : var(--link);
  }
/* separator bars */
nav,
section {
  border-block-end : 1px solid var(--primary);
  }
/* container for dark-mode toggle */
header .controls {
  display         : flex;
  justify-content : end;
  padding         : 1rem 0;
  margin-right    : 3rem;
  }
 a.btn {
  display         : inline-flex;
  align-items     : center;
  background      : var(--link);
  color           : var(--background);
  text-decoration : none;
  padding         : 0 1rem;
  height          : 2.5rem;
  border-radius   : 1.25rem;
  font-family     : "Montserrat", sans-serif;
  font-weight     : 700;
  font-size       : 0.875rem;
  }

修正后的JavaScript

class CssPropControl {
  constructor(element) {
    this.element = element
  }
  get(varName) {
    return getComputedStyle(this.element).getPropertyValue(varName)
  }
  set(varName, val) {
    return this.element.style.setProperty(varName, val)
  }
}

const bodyCssProps = new CssPropControl(document.body)
const toggle = document.querySelector('#dark-mode-toggle')

// 切换主题并保存到localStorage
function toggleTheme(isDark) {
  const mode = isDark ? 'dark' : 'light'
  bodyCssProps.set('--background', bodyCssProps.get(`--${mode}-background`))
  bodyCssProps.set('--primary', bodyCssProps.get(`--${mode}-primary`))
  bodyCssProps.set('--link', bodyCssProps.get(`--${mode}-link`))
  localStorage.setItem('darkModeStatus', isDark)
  toggle.checked = isDark
}

// 页面加载时恢复保存的主题
window.addEventListener('load', () => {
  const isDark = localStorage.getItem('darkModeStatus') === 'true'
  toggleTheme(isDark)
})

// 监听切换按钮点击
toggle.addEventListener('click', () => {
  toggleTheme(toggle.checked)
})

关键改动说明

  1. 修复ID错误:统一使用dark-mode-toggle作为元素ID,避免找不到元素的问题
  2. 整合逻辑:把主题切换、localStorage保存、页面初始化逻辑合并,避免重复事件绑定
  3. 移除无效代码:删掉无意义的bodyCssProps类操作,直接通过CSS变量切换主题
  4. 优化过渡效果:把body的两个transition合并成一行,确保颜色和背景过渡同步

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.08 16:25:26