🎨 模板下载

用 CSS 变量实现无闪烁的深色模式

深色模式做不好通常有两个症状:刷新时闪一下白屏,以及某个组件在暗色下依然刺眼。前者是时序问题,后者是架构问题。

一、首帧之前就把主题定下来#

React 水合发生在首屏绘制之后,所以切换逻辑不能放在组件里。要在 <head> 里同步执行:

ts
const themeScript = `(function(){try{
  var t = localStorage.getItem('theme');
  if (t !== 'dark' && t !== 'light') {
    t = window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light';
  }
  document.documentElement.dataset.theme = t;
}catch(e){}document.documentElement.dataset.theme=document.documentElement.dataset.theme||'light';})();`;
tsx
<html lang="zh-CN" suppressHydrationWarning>
  <head><script dangerouslySetInnerHTML={{ __html: themeScript }} /></head>

suppressHydrationWarning 是必要的:服务端不知道用户选了哪个主题,这个差异是预期的。

二、颜色全部走变量,并且只维护一份#

css
:root {
  --bg: #f6f7fb;
  --card: #ffffff;
  --text: #1a1f2b;
  --muted: #5c6577;
  --border: #e3e7f0;
}

html[data-theme='dark'] {
  --bg: #0d1117;
  --card: #161b22;
  --text: #e6e9ef;
  --muted: #a7b0bf;
  --border: #242c37;
}

组件里只写 var(--card)、var(--text),永远不要写死 #fff 或 #000。做到这一点,切换主题就是改一个属性的事。

三、容易漏掉的几类颜色#

类型 建议做法
代码块 token 配色 也定义成变量,暗色下单独给一组
半透明遮罩(灯箱) 用 rgba(8,11,16,.9),两种主题共用即可
阴影 暗色下加深,否则层次消失
表单控件 显式设置 background 与 color,别依赖浏览器默认

四、跟随系统 + 手动覆盖#

优先级:用户手动选择 > 系统偏好。切换时写回 localStorage:

ts
document.documentElement.dataset.theme = next;
localStorage.setItem('theme', next);

这样用户的选择跨页面、跨会话都保留,而没选过的访客自动跟随系统。

自测清单:切到暗色后逐个检查 —— 表格斑马纹、引用块、标签胶囊、分页按钮、404 页、后台表单。这些是最容易出现"半白半黑"的地方。

付费下载 · ¥99.00

付款后立即开通下载链接(30 天有效、可下载 5 次)。在微信中打开本页可直接支付,在电脑上则显示扫码支付。

客服微信二维码微信扫码加客服

评论

正在加载评论…

评论保存在本站 data/comments.json,不经过第三方。