应直接用 localStorage.setItem('theme', 'dark') 存字符串,页面加载时立即读取并设 document.documentElement.className,切换时实时写入;注意 iOS 隐私模式等场景需 try/catch 捕获 SecurityError,并 fallback 到 prefers-color-scheme。

怎么用 localStorage 保存用户选的主题(比如 dark / light)
直接存字符串就行,但得注意时机和触发逻辑。页面刚加载时就读取,切换主题时立刻写入,别等 onbeforeunload 或用户关页——那会丢数据。
- 用
localStorage.setItem('theme', 'dark')写入,值必须是字符串,true、1、对象都得先JSON.stringify() - 读取用
localStorage.getItem('theme'),返回null表示没存过,别直接当布尔值用 - 别在 CSS 文件里读 localStorage —— 它是 JS API,只能在 JS 中读,然后动态切
class或改document.documentElement.setAttribute()
切换主题时如何避免闪屏(FOUC)
闪屏本质是:HTML 渲染完、CSS 生效了,JS 才运行并改主题。解决方案不是“等 JS”,而是“让初始渲染就带对的主题”。
- 服务端不参与的话,就在
里加一段内联 JS,用localStorage.getItem('theme')立即设document.documentElement.className - 不要把主题 class 加在
上——更早生效,CSS 里用:root或html.dark更稳 - 如果用了 CSS 自定义属性(
--bg-color),确保初始值写在 :root 里,再用html.dark :root覆盖,而不是靠 JS 逐个 setStyle
localStorage 存失败的常见原因
不是所有环境都能写,尤其 iOS Safari 隐私模式、某些 WebView、或设置了 Strict-Origin-Isolation 的站点会静默拒绝。
- 调用
localStorage.setItem()前先 try/catch,捕获QuotaExceededError和SecurityError - iOS Safari 隐私模式下
localStorage是只读空对象,getItem返回null,setItem抛SecurityError—— 别假设它一定可用 - 存太多键或单个值超 5–10MB(实际阈值因浏览器而异)会失败;主题偏好这种小数据没问题,但别顺手把整个 CSS 字符串塞进去
CSS class 名要不要和 localStorage key 对齐
没必要强绑定,但保持一致能降低维护成本。关键是别让 class 名含歧义,比如 dark-mode 和 dark 混用。
立即学习“前端免费学习笔记(深入)”;
- 推荐统一用
dark/light这类短名,存到 localStorage 也用同样字符串,JS 里直接拼document.documentElement.className = theme - 避免用
is-dark或theme--dark这类带前缀的 class——除非你整套 CSS 都按 BEM 写,否则容易漏匹配 - 如果支持系统级偏好(
prefers-color-scheme),记得 fallback 逻辑:localStorage 有值就用它,没有才读matchMedia('(prefers-color-scheme: dark)')



















