如何为你的网站或应用添加深色模式(且没有白屏闪烁)
要添加深色模式,请把你的颜色定义为具名的令牌(背景、文字、表面、边框、强调色),而不是硬编码的数值,并为每个令牌设置浅色和深色两个值,然后使用CSS的 prefers-color-scheme 媒体特性在两者之间切换,让网站跟随访客的系统设置。如果你还想要手动切换,请把选择存储在浏览器中,并通过页面头部的一小段内联脚本应用它,以避免加载时的白屏闪烁。之后再检查两种主题下的对比度、图片和图表。在AI应用构建器中,一条清晰的提示词就能完成大部分工作;真正决定质量的是检查环节。
两种方法
| 方法 | 工作方式 | 适合 | 权衡 |
|---|---|---|---|
| 跟随系统 | CSS媒体特性 prefers-color-scheme 选择浅色或深色 | 简单网站,无需界面 | 访客无法与设备设置不同 |
| 切换按钮 + 系统默认 | 以系统设置为起点;“浅色 / 深色 / 跟随系统”切换会覆盖它,并被记住 | 人们经常使用的应用 | 需要一点JavaScript,还要解决加载时闪烁的问题 |
大多数应用采用第二种方式效果最好:默认尊重系统设置,同时允许用户覆盖。
从颜色令牌开始
如果颜色以 white、#333 和 gray-100 的形式散落在代码各处,深色模式就很难做。如果每种颜色都来自一小组具名令牌,就容易得多:
| 令牌 | 浅色 | 深色 |
|---|---|---|
background | 近白色 | 非常深的灰色 |
surface(卡片、菜单) | 白色 | 比背景略浅的深灰色 |
text | 近黑色 | 灰白色 |
text-muted | 中灰色 | 较浅的中灰色 |
border | 浅灰色 | 带一点对比的深灰色 |
accent | 你的品牌色 | 通常是更浅或饱和度更低的版本 |
每个组件都使用令牌名称。切换主题时,只需替换一组值,而不必逐个修改组件。
深色配色的几点建议:
- 大面积区域避免使用纯黑和纯白;非常深的灰色和灰白色更易阅读。
- 用更浅的表面颜色来体现层次,而不是用阴影——阴影在深色背景上几乎看不见。
- 适当降低明亮品牌色的饱和度,它们在深色背景上可能会显得刺眼。
- 保持文字对比度可读。 WCAG的AA级标准要求普通文字的对比度至少为4.5:1。在深色主题中,灰色的辅助文字经常达不到这个要求。
与Tailwind CSS配合使用
Tailwind是许多AI构建应用默认的样式工具。根据Tailwind的深色模式文档,dark: 变体默认使用 prefers-color-scheme,因此 bg-white dark:bg-gray-900 这样的类无需额外设置就能跟随系统设置。
要在Tailwind v4中实现手动切换,文档展示了将变体切换为父元素上的类:
@import "tailwindcss";
@custom-variant dark (&:where(.dark, .dark *));
然后应用会在根元素上添加或移除 dark 类。文档还建议在头部放置一段内联脚本,在页面绘制之前应用已保存的选择(或系统设置)——这正是避免闪烁的方法。
避免白屏闪烁
闪烁的原因是:页面先以浅色模式绘制,然后JavaScript加载,读取已保存的选择,再切换到深色。解决方法如下:
- 在页面头部放置一段很小的内联脚本,在任何内容渲染之前读取已保存的主题,并在根元素上设置类。
- 为每种主题设置
color-schemeCSS属性,使浏览器绘制的部分(滚动条、表单控件)与之匹配。 - 为两种主题都设置明确的背景色。
- 如果应用是服务端渲染的,要确保服务器和浏览器对初始主题的判断一致,否则页面可能会重新渲染并出现闪烁。
示例提示词
完整设置:
添加深色模式。首先把硬编码的颜色替换为主题令牌(背景、表面、文字、辅助文字、边框、强调色),每个令牌都有浅色和深色两个值。默认跟随访客的系统设置。在页眉添加主题切换,提供“浅色”“深色”和“跟随系统”选项,将选择记在 localStorage 中,并通过头部的内联脚本应用,避免加载时白屏闪烁。为两种主题分别设置 color-scheme。保持当前的浅色设计完全不变。
修复剩余问题:
在深色模式下检查每个页面,并修复:对比度过低的文字(力求至少4.5:1)、硬编码的白色背景、消失的边框、深色背景上的深色文字图表,以及看不见的logo。不要改动浅色主题。
图片和图表:
深色模式下使用浅色版本的logo。让图表的坐标轴、网格线和标签使用主题令牌。深色模式下为截图添加一层淡淡的边框,使其不会与背景融为一体。
分步操作
- 审计颜色。 找出硬编码的颜色并替换为令牌。这是大部分工作所在。
- 为每个令牌定义深色值。
- 用
prefers-color-scheme(或Tailwind默认的dark:)跟随系统。 - 如果需要,添加切换按钮:浅色、深色、跟随系统。把选择存储在浏览器中;对于需要登录的应用,也可以保存到用户资料中。
- 用头部内联脚本和
color-scheme防止闪烁。 - 检查较难处理的部分:logo、图标、带白色背景的图片、图表、代码块、地图、嵌入内容、邮件。
- 测试两种主题,分别在桌面和手机上测试,系统分别设为浅色和深色,并在强制刷新后再次测试。
常见错误
- 把所有颜色都反转。 用于反转颜色的滤镜会破坏照片和品牌色。
- 遗留硬编码颜色。 深色页面中一张白色卡片会立刻显得突兀。
- 低对比度的灰色文字。 看起来很精致,却难以阅读。
- 加载时白屏闪烁。 在夜间用手机打开时尤其明显。
- 忘记第三方嵌入内容。 地图、视频和组件可能保持浅色;请检查它们是否提供深色选项。
- 只有两种状态的切换按钮。 用户一旦点击,就无法再回到跟随系统的状态。
- 破坏浅色主题。 请在提示词中明确说明浅色设计应保持不变。
检查清单
- 所有颜色都来自主题令牌
- 默认跟随系统设置
- 可选的切换按钮,提供浅色、深色和跟随系统,并被记住
- 加载或刷新时没有白屏闪烁
- 设置了
color-scheme,使表单控件和滚动条匹配 - 两种主题下的文字对比度至少为4.5:1
- 已在深色模式下检查logo、图片、图表和嵌入内容
- 浅色主题未被改动
- 已在桌面和手机上测试
在Mythex中使用深色模式
基于Mythex构建的应用默认使用Vite、React、TypeScript和Tailwind,因此上面的Tailwind方法可以直接适用:把完整设置的提示词粘贴到聊天中,然后在预览中分别检查两种主题,并在手机尺寸下查看。Mythex的设计提示建议是说明要改动什么、要保留什么,这在这里尤其重要——请明确说明浅色主题必须保持不变。参见设计与UI提示词;如果某次修改出错,可以用检查点回滚。
关于如何打造好看的界面,请参见如何用AI设计好看的应用和如何为AI应用构建器编写提示词。
常见问题
如何让网站跟随设备的深色模式设置?
使用CSS的 prefers-color-scheme 媒体特性,它可以判断访客的系统设置是浅色还是深色。Tailwind的 dark: 变体默认就使用它。
为什么我的网站在切换到深色模式之前会闪一下白色?
已保存的主题是由JavaScript在页面已经绘制之后才应用的。解决办法是在页面头部放置一小段内联脚本,在任何内容渲染之前设置主题类,并为两种主题都设置明确的背景色。
深色模式应该是纯黑色吗?
通常不需要。非常深的灰色更适合长时间阅读,并且可以通过略浅的表面颜色来体现层次感。纯黑色可能适合以OLED为主或以媒体内容为主的设计。
如果我跟随系统设置,还需要深色模式切换按钮吗?
并非必须。跟随系统是很好的默认方式,但提供“浅色”“深色”和“跟随系统”选项的切换按钮,能帮助那些希望网站与设备设置不同的人。