用 Claude Code 实现深色模式的实务指南
用 CSS 变量、系统偏好、localStorage 和 hydration 对策实现可靠的深色模式。
先控制产品风险
用 Claude Code 实现深色模式时,关键不是把页面做得多炫,而是在不破坏转化、阅读体验、移动端和可访问性的前提下,让界面更可靠。初学者很容易让 Claude Code 一次生成大量代码,觉得”能跑起来”就算完成,但真正上线时,空数据、加载状态、键盘焦点、屏幕宽度、颜色对比和主要按钮的位置才更重要。本文要讲的是:如何把深色模式小步、安全地引入项目,并把它培养成日后不易出错的形态。
建议同时阅读 claude code design system, claude code accessibility, claude code code review。官方资料可以参考 Claude Code docs, MDN prefers-color-scheme, MDN color-scheme, WCAG contrast。给 Claude Code 的指令要写清楚目标、禁止改动的范围、需要检查的 use case 和 pitfall。
推荐提示词
请用最小安全改动实现这个功能。
保留现有组件结构、设计 token 和路由。
请覆盖 use case、pitfall、可访问性、移动端、失败状态和回滚方法。
返回可直接复制运行的代码,并附上 review checklist。
这段提示词的用意,是让 Claude Code 产出的不是”完成版 UI”,而是”不易出错的改动流程”。在已有站点上尤其如此:比起华丽的改版,更重要的是不增加跳出、不挡住咨询和购买入口。
适用场景清单
- 落地页和文章页:让读者更容易看到下一步,但不能遮挡正文、广告或咨询按钮。
- SaaS 仪表板:加载、空数据、错误和成功状态要清楚。
- 购买、注册、咨询流程:视觉优化不能抢走主要行动按钮。
- 团队协作:Claude Code 需要输出代码、理由和检查清单,方便他人复核。
实现代码
:root {
color-scheme: light;
--color-page: #ffffff;
--color-surface: #f8fafc;
--color-text: #0f172a;
--color-muted: #475569;
--color-border: #dbe3ef;
--color-link: #2563eb;
--color-focus: #f59e0b;
}
[data-theme="dark"] {
color-scheme: dark;
--color-page: #0b1120;
--color-surface: #111827;
--color-text: #f8fafc;
--color-muted: #cbd5e1;
--color-border: #334155;
--color-link: #93c5fd;
--color-focus: #fbbf24;
}
body {
background: var(--color-page);
color: var(--color-text);
}
:focus-visible {
outline: 3px solid var(--color-focus);
outline-offset: 3px;
}
const storageKey = "theme";
const root = document.documentElement;
const stored = localStorage.getItem(storageKey);
const prefersDark = window.matchMedia("(prefers-color-scheme: dark)").matches;
const theme = stored === "light" || stored === "dark" ? stored : prefersDark ? "dark" : "light";
root.dataset.theme = theme;
type Theme = "light" | "dark" | "system";
export function ThemeToggle({ value, onChange }: { value: Theme; onChange: (theme: Theme) => void }) {
return (
<fieldset aria-label="Theme">
{(["light", "dark", "system"] as const).map((theme) => (
<button
key={theme}
type="button"
aria-pressed={value === theme}
onClick={() => onChange(theme)}
>
{theme}
</button>
))}
</fieldset>
);
}
如何避免主题闪烁(FOUC)
做深色模式最先撞上的坑,就是打开页面的一瞬间先看到亮色,随后才变暗的”闪烁”。英文里叫 FOUC(Flash of Unstyled Content),也叫主题闪烁。原因在于:HTML 已经显示出来之后,才用 JavaScript 去切换主题。如果要等 CSS 或 React 加载完才给元素加上 data-theme,那段等待时间里读者看到的就是初始配色(多半是亮色)。
对策是把决定主题的那一小段脚本,放在正文之前(<head> 内)同步执行。像下面这样,只看已保存的设置和系统偏好,在画面绘制之前就把 data-theme 定下来。
<script>
(function () {
var stored = localStorage.getItem("theme");
var prefersDark = window.matchMedia("(prefers-color-scheme: dark)").matches;
var theme = stored === "light" || stored === "dark" ? stored : prefersDark ? "dark" : "light";
document.documentElement.dataset.theme = theme;
})();
</script>
要点是让这段脚本足够轻量,并且先于正文绘制运行。如果把重逻辑或 React 初始化塞进这里,闪烁就又回来了。在 Astro 或 Next.js 中也一样:要让主题在框架的 hydration(在服务端生成的 HTML 上,由浏览器侧补上交互行为)之前就确定下来,就得把这一小段脚本单独处理。由于服务端无法得知用户设备的设置,比较好操作的流程是:首屏先尊重系统设置,等用户手动切换后写入 localStorage,下次起以它为准。
让对比度、图片和阴影在暗色下也清晰
只是把颜色反过来,深色模式并不算做完。在亮色下足够的对比度,到了暗色背景上可能就不够了。正文与背景的对比度,建议以 WCAG 给出的 4.5:1 以上为基准来核对。尤其是浅灰的补充文字、占位符、禁用状态的按钮,最容易在暗色背景上看不清。
图片和阴影也需要调整。以白底为前提做的 Logo 和图标,放到暗色背景上边缘会消失;透明 PNG 要么垫一层背景色,要么准备一张暗色专用的替换图。阴影方面,在亮色背景上用深灰很有效,但在暗色背景上几乎看不见——原本靠阴影区分的边界,改用 --color-border 这样的描边来表达,两种主题下都能看清结构。
| 元素 | 亮色下的前提 | 暗色下的调整 |
|---|---|---|
| 补充文字 | 浅灰就够 | 提高明度以保证对比度 |
| Logo、图标 | 默认白底 | 垫背景色或换暗色专用图 |
| 阴影 | 用深灰表达边界 | 改用描边(border)表达 |
| 状态色 | 鲜艳的绿、红 | 降低饱和度,并配上图标 |
最后,图表、图示和状态色(成功为绿、警告为红等)也要复核一遍。高饱和的颜色在暗色背景上会发刺、不好读,所以要准备暗色专用、稍微沉稳一些的配色。不要只靠颜色传达状态,再配上图标或文字标签,这样在对比偏弱的环境或有色觉特性的读者那里也能看懂。让 Claude Code 来 review 时,具体地让它去找”暗色背景下对比度下降的地方""以白底为前提的图片""靠阴影表达的边界”,就能少漏一些问题。
陷阱清单
- 只看截图不看真实流程,容易让转化路径变差。
- 只依赖颜色或动效表达含义,会影响可访问性。
- 未检查 375px 宽度时,移动端可能出现横向滚动。
- 未处理空数据、长文本、慢网络和刷新,会在真实用户环境出错。
- 让 Claude Code 顺手重构无关文件,会让 review 成本变高。
验证方法
让 Claude Code 再做一次只读 review,要求列出改动文件、风险、手动检查项和浏览器检查项。然后在移动端宽度打开页面,确认没有横向溢出,代码块可以滚动,CTA 仍然可见,辅助文本和焦点样式没有消失。
商业化视角
深色模式不是装饰,而是减少读者走向咨询、资料索取、购买、报名培训路上犹豫的改进。想在自家站点搭好 Claude Code 的引入和 review 流程的团队,可以通过 Claude Code 培训与咨询,以现有界面为题材讨论改进步骤。
额外检查
- 把修改前后的截图并排对比,确认 CTA、广告、正文、表单和代码块依旧清晰易读。
- 不要直接照搬 Claude Code 的建议,反过来追问它哪些代码可以删、哪些命名别扭、哪些地方和既有 CSS 冲突。
- 上线前把移动端、桌面端、键盘操作、慢网络、空数据和刷新行为都过一遍。
实测记录
这套步骤是在不破坏既有博客 UI 的前提下,一边盯着 375px 手机宽度、常规显示、慢网络和键盘操作一边验证的。我没有把所有事情一次性丢给 Claude Code,而是拆成实现、review、修正三步——这样差分更好读,质量也更稳。比起一次性大改,更容易发现问题,也更适合每天持续打磨内容站和产品页。
免费 PDF: Claude Code 速查表
输入邮箱即可获取一页 PDF,整理常用命令、审查习惯和安全工作流。
我们会妥善保护你的信息,不发送垃圾邮件。
把 Claude Code 变成真正能带来结果的工作流
先领取中文说明的免费 PDF,再进入英文商品页选择合适的教材。如果你需要团队落地、流程设计或内容变现支持,也可以直接咨询。
关于作者
Masa
专注 Claude Code 实务流程、团队导入和内容转化的工程师。
相关文章
Claude Code权限安全阶梯:逐步放开访问而不失控
从只读到有限编辑、验证命令和部署检查的 Claude Code 权限升级流程。
Claude Code 小PR证据包:让小改动真正可审查
用差异、验证命令、公开URL、CTA路径和回滚说明,把Claude Code的小PR变得可审查。
Claude Code 提交前 Review Gate:同时检查差异、测试、公开 URL 和 CTA
提交前用 Claude Code 审查差异范围、build、公开 URL、Gumroad 链接、咨询 CTA、缺少测试和无关文件。