如何为PC端网站实现深色/浅色模式的localStorage持久化?
深色模式刷新恢复问题的适配解决方案
你的代码存在几个关键问题导致刷新后模式重置:
- 监听的元素ID拼写错误(
darkModeTogglevs 实际的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) })
关键改动说明
- 修复ID错误:统一使用
dark-mode-toggle作为元素ID,避免找不到元素的问题 - 整合逻辑:把主题切换、localStorage保存、页面初始化逻辑合并,避免重复事件绑定
- 移除无效代码:删掉无意义的
bodyCssProps类操作,直接通过CSS变量切换主题 - 优化过渡效果:把body的两个transition合并成一行,确保颜色和背景过渡同步
内容的提问来源于stack exchange,提问作者Zero Hour
相关产品推荐
相关产品推荐

