design-tokens-theming
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseDesign Tokens & Theming
Design Token 与主题化
Overview
概述
A SaaS UI looks "designed" when every color, space, and font size comes from a small, named scale — not arbitrary values sprinkled per component. Define tokens once as CSS variables, expose them through Tailwind, and let dark mode be a swap of variable values, not a rewrite of class names.
当每种颜色、间距和字号都来自一套精简且命名明确的 scale,而不是在各组件中随意散落具体数值时,SaaS UI 才显得“经过精心设计”。将这些 token 一次性定义为 CSS 变量,通过 Tailwind 对外暴露,并让深色模式只需交换变量值,而不必重写 class 名称。
When to use
使用场景
- Starting a new app and deciding colors/spacing/typography.
- Components use raw hex codes or one-off pixel values.
- You need dark mode or multi-brand theming.
- 启动新应用并确定颜色、间距和排版。
- 组件使用原始十六进制色值或零散的 px 值。
- 需要深色模式或多品牌主题化。
Semantic tokens (the key idea)
语义化 token(核心思路)
Name tokens by role, not by hue. , , — not . Roles let you re-theme without touching components. shadcn/ui uses exactly this convention:
--primary--muted--destructive--blue-500css
/* globals.css */
:root {
--background: 0 0% 100%;
--foreground: 240 10% 3.9%;
--primary: 240 5.9% 10%;
--primary-foreground: 0 0% 98%;
--muted: 240 4.8% 95.9%;
--muted-foreground: 240 3.8% 46.1%;
--destructive: 0 84.2% 60.2%;
--border: 240 5.9% 90%;
--radius: 0.5rem;
}
.dark {
--background: 240 10% 3.9%;
--foreground: 0 0% 98%;
--primary: 0 0% 98%;
--primary-foreground: 240 5.9% 10%;
--muted: 240 3.7% 15.9%;
--muted-foreground: 240 5% 64.9%;
--border: 240 3.7% 15.9%;
}Store HSL channels (no wrapper) so Tailwind can add opacity: .
hsl(...)hsl(var(--primary) / 0.5)按角色而非色相命名 token。、、——而不是 。借助角色,你无需修改组件即可重新设置主题。shadcn/ui 正是采用这一约定:
--primary--muted--destructive--blue-500css
/* globals.css */
:root {
--background: 0 0% 100%;
--foreground: 240 10% 3.9%;
--primary: 240 5.9% 10%;
--primary-foreground: 0 0% 98%;
--muted: 240 4.8% 95.9%;
--muted-foreground: 240 3.8% 46.1%;
--destructive: 0 84.2% 60.2%;
--border: 240 5.9% 90%;
--radius: 0.5rem;
}
.dark {
--background: 240 10% 3.9%;
--foreground: 0 0% 98%;
--primary: 0 0% 98%;
--primary-foreground: 240 5.9% 10%;
--muted: 240 3.7% 15.9%;
--muted-foreground: 240 5% 64.9%;
--border: 240 3.7% 15.9%;
}存储 HSL 通道值(不要使用 包装),以便 Tailwind 可以添加透明度:。
hsl(...)hsl(var(--primary) / 0.5)Wire tokens into Tailwind
将 token 接入 Tailwind
ts
// tailwind.config.ts
export default {
darkMode: "class",
theme: {
extend: {
colors: {
background: "hsl(var(--background))",
foreground: "hsl(var(--foreground))",
primary: { DEFAULT: "hsl(var(--primary))", foreground: "hsl(var(--primary-foreground))" },
muted: { DEFAULT: "hsl(var(--muted))", foreground: "hsl(var(--muted-foreground))" },
border: "hsl(var(--border))",
},
borderRadius: { lg: "var(--radius)", md: "calc(var(--radius) - 2px)" },
},
},
};Now works in both themes automatically.
bg-primary text-primary-foregroundts
// tailwind.config.ts
export default {
darkMode: "class",
theme: {
extend: {
colors: {
background: "hsl(var(--background))",
foreground: "hsl(var(--foreground))",
primary: { DEFAULT: "hsl(var(--primary))", foreground: "hsl(var(--primary-foreground))" },
muted: { DEFAULT: "hsl(var(--muted))", foreground: "hsl(var(--muted-foreground))" },
border: "hsl(var(--border))",
},
borderRadius: { lg: "var(--radius)", md: "calc(var(--radius) - 2px)" },
},
},
};现在, 会在两种主题中自动生效。
bg-primary text-primary-foregroundDark mode toggle
深色模式切换
Use (or a tiny class toggler) and . Never hard-code colors when a semantic token already flips — beats .
next-themesdarkMode: "class"dark:bg-backgroundbg-white dark:bg-zinc-950使用 (或一个简单的 class 切换器),并设置 。当语义化 token 已经能够完成切换时,绝不要硬编码 颜色—— 优于 。
next-themesdarkMode: "class"dark:bg-backgroundbg-white dark:bg-zinc-950Scales to standardize
需要标准化的 scale
- Spacing: stick to Tailwind's 4px scale (,
p-2,gap-4). Avoidspace-y-6.p-[13px] - Typography: a 5–6 step type scale (→
text-sm); settext-3xlfor secondary text.text-muted-foreground - Radius/shadow: one token; 2–3 shadow steps.
--radius
- **间距:**坚持使用 Tailwind 的 4px scale(、
p-2、gap-4)。避免使用space-y-6。p-[13px] - **排版:**采用 5–6 级字号 scale(→
text-sm);次要文本设置为text-3xl。text-muted-foreground - **圆角/阴影:**使用一个 token;设置 2–3 级阴影。
--radius
Pitfalls
常见问题
- Raw hex/px values per component → inconsistent UI that can't be re-themed.
- overrides everywhere instead of flipping tokens once.
dark: - Naming tokens by color () instead of role (
--blue).--primary - Wrapping in the variable — breaks Tailwind opacity modifiers.
hsl() - Too many shades — a bloated palette is harder to keep consistent than a tight one.
- 在每个组件中使用原始十六进制/px 值 → 导致 UI 不一致,且无法重新设置主题。
- 到处使用 覆盖值,而不是一次性切换 token。
dark: - 按颜色命名 token(),而不是按角色命名(
--blue)。--primary - 在变量中包装 → 会破坏 Tailwind 的透明度修饰符。
hsl() - 色阶过多 → 过于庞大的调色板比精简的调色板更难保持一致。
Hand-off
交付
A token layer that , , and every component skill build on — change a value once, the whole app re-themes.
responsive-layoutaccessible-components交付一个 token 层,供 、 以及所有组件 skill 在其上构建——修改一次数值,整个应用都会重新应用主题。
responsive-layoutaccessible-components