design-tokens by dylanfeltus/skills
npx skills add https://github.com/dylanfeltus/skills --skill design-tokens通过数学计算生成字体比例、色彩调色板、间距系统以及深色模式衍生方案——而非猜测。包含 WCAG 对比度检查、系统化间距网格以及可用于生产的 CSS/Tailwind 输出。
fontSize = baseFontSize × ratio^step
| 比率 | 名称 | 值 | 最适合 |
|---|---|---|---|
| Minor Second | 1.067 | 紧凑,差异极小 | 密集 UI,仪表板 |
广告位招租
在这里展示您的产品或服务
触达数万 AI 开发者,精准高效
| Major Second | 1.125 | 微妙的递进 | 应用程序,数据密集型界面 |
| Minor Third | 1.200 | 平衡,通用性强 | 大多数网站,SaaS |
| Major Third | 1.250 | 清晰的层级结构 | 营销网站,博客 |
| Perfect Fourth | 1.333 | 强烈对比 | 社论,落地页 |
| Augmented Fourth | 1.414 | 戏剧性 | 大胆的设计,作品集 |
| Perfect Fifth | 1.500 | 极具戏剧性 | 以英雄区域为主的设计 |
给定一个基础尺寸(通常为 16px)和一个比率:
Step -2: 16 / ratio² = xs
Step -1: 16 / ratio = sm
Step 0: 16 = base
Step 1: 16 × ratio = lg
Step 2: 16 × ratio² = xl
Step 3: 16 × ratio³ = 2xl
Step 4: 16 × ratio⁴ = 3xl
Step 5: 16 × ratio⁵ = 4xl
Step 6: 16 × ratio⁶ = 5xl
四舍五入到最近的 0.5px 或转换为 rem(÷ 16)。
| 字体大小 | 行高 | 用途 |
|---|---|---|
| ≤ 14px | 1.6–1.7 | 小文本,说明文字 |
| 16–20px | 1.5–1.6 | 正文文本 |
| 20–32px | 1.3–1.4 | 副标题 |
| 32–48px | 1.1–1.2 | 标题 |
| 48px+ | 1.0–1.1 | 展示/英雄文本 |
经验法则: 随着字体大小增加,行高应减小。
| 大小 | 字间距 | 原因 |
|---|---|---|
| 小文本 (≤14px) | 0.01–0.02em | 略微拉开以提高可读性 |
| 正文文本 | 0em (正常) | 保持原样 |
| 副标题 | -0.01em | 略微收紧 |
| 标题 | -0.02em 到 -0.03em | 随着尺寸增大而收紧 |
| 展示文本 | -0.03em 到 -0.05em | 大尺寸时紧密的字间距 |
| 角色 | 字重 | Tailwind |
|---|---|---|
| 正文 | 400 (常规) | font-normal |
| 正文强调 | 500 (中等) | font-medium |
| 副标题 | 600 (半粗体) | font-semibold |
| 标题 | 700 (粗体) | font-bold |
| 展示 | 800 (特粗体) | font-extrabold |
:root {
--font-size-xs: 0.694rem; /* 11.1px */
--font-size-sm: 0.833rem; /* 13.3px */
--font-size-base: 1rem; /* 16px */
--font-size-lg: 1.2rem; /* 19.2px */
--font-size-xl: 1.44rem; /* 23px */
--font-size-2xl: 1.728rem; /* 27.6px */
--font-size-3xl: 2.074rem; /* 33.2px */
--font-size-4xl: 2.488rem; /* 39.8px */
--font-size-5xl: 2.986rem; /* 47.8px */
}
每个调色板都需要:
| 令牌 | 用途 | 示例 |
|---|---|---|
primary | 主要品牌色,行动号召 | 您的品牌色 |
neutral | 文本,边框,背景 | 灰色 (暖/冷/纯) |
success | 积极状态 | 绿色 |
warning | 警告状态 | 琥珀色/黄色 |
error | 破坏性状态 | 红色 |
info | 信息提示 | 蓝色 (可与主色重叠) |
为每个基础色彩生成一个 10 步色阶。基础色彩通常是第 500 步。
方法:HSL 调整
从基础 HSL 开始:
| 步数 | 明度调整 | 饱和度调整 |
|---|---|---|
| 50 | +45% | -30% |
| 100 | +38% | -25% |
| 200 | +28% | -15% |
| 300 | +18% | -5% |
| 400 | +8% | 0% |
| 500 | 0% (基础) | 0% (基础) |
| 600 | -8% | +5% |
| 700 | -18% | +5% |
| 800 | -28% | 0% |
| 900 | -38% | -10% |
| 950 | -45% | -20% |
限制所有值:明度 0–100%,饱和度 0–100%。
将色阶步数映射到语义角色:
/* 浅色模式 */
--color-bg: var(--neutral-50);
--color-bg-subtle: var(--neutral-100);
--color-bg-muted: var(--neutral-200);
--color-border: var(--neutral-200);
--color-border-strong: var(--neutral-300);
--color-text-muted: var(--neutral-500);
--color-text-subtle: var(--neutral-600);
--color-text: var(--neutral-900);
--color-text-heading: var(--neutral-950);
--color-primary: var(--primary-600);
--color-primary-hover: var(--primary-700);
--color-primary-bg: var(--primary-50);
--color-primary-text: white;
对比度比率 = (L1 + 0.05) / (L2 + 0.05)
其中 L1 = 较亮的相对亮度,L2 = 较暗的。
对于每个通道 (R, G, B):
sRGB = channel / 255
linear = sRGB <= 0.04045 ? sRGB / 12.92 : ((sRGB + 0.055) / 1.055) ^ 2.4
L = 0.2126 × R_linear + 0.7152 × G_linear + 0.0722 × B_linear
| 级别 | 比率 | 适用于 |
|---|---|---|
| AA 正常文本 | ≥ 4.5:1 | 正文文本 (< 18px 或 < 14px 粗体) |
| AA 大文本 | ≥ 3:1 | ≥ 18px 常规 或 ≥ 14px 粗体 |
| AAA 正常文本 | ≥ 7:1 | 增强可访问性 |
| AA UI 组件 | ≥ 3:1 | 边框,图标,焦点环 |
| 色阶 | 近似对比度 | 通过情况 |
|---|---|---|
| 300 | ~2.5:1 | ❌ 仅用于装饰 |
| 400 | ~3.5:1 | ✅ 大文本,UI |
| 500 | ~4.5:1 | ✅ AA 正文文本 |
| 600 | ~6:1 | ✅ AA 舒适 |
| 700 | ~8:1 | ✅ AAA 正文文本 |
生成调色板时,始终验证:
text (900) 在 bg (50) 上 → 必须 ≥ 4.5:1text-muted (500) 在 bg (50) 上 → 必须 ≥ 4.5:1primary (600) 在 white 上 → 必须 ≥ 4.5:1primary-text 在 primary (600) 上 → 必须 ≥ 4.5:1border (200) 在 bg (50) 上 → 必须 ≥ 3:1如果某个组合失败,将较暗的颜色调暗一个步长,直到通过。
所有值都是 4px 的倍数。可预测、一致,适用于大多数字体大小。
:root {
--space-0: 0px;
--space-0.5: 2px;
--space-1: 4px;
--space-1.5: 6px;
--space-2: 8px;
--space-3: 12px;
--space-4: 16px;
--space-5: 20px;
--space-6: 24px;
--space-8: 32px;
--space-10: 40px;
--space-12: 48px;
--space-16: 64px;
--space-20: 80px;
--space-24: 96px;
--space-32: 128px;
}
这与 Tailwind 的默认比例完全匹配。
| 上下文 | 间距 | 值 |
|---|---|---|
| 行内图标间隙 | space-1 到 space-2 | 4–8px |
| 按钮内边距 | space-2 × space-4 | 8px 16px |
| 卡片内边距 | space-4 到 space-6 | 16–24px |
| 区块间隙 (元素之间) | space-6 到 space-8 | 24–32px |
| 区块内边距 (容器) | space-12 到 space-16 | 48–64px |
| 页面区块垂直节奏 | space-16 到 space-24 | 64–96px |
| 令牌 | 宽度 | 用途 |
|---|---|---|
sm | 640px | 窄内容 (认证表单) |
md | 768px | 博客文章,文档 |
lg | 1024px | 应用程序布局 |
xl | 1280px | 宽布局 |
2xl | 1536px | 全宽仪表板 |
不要手动选择深色模式色彩。系统化地衍生它们:
浅色模式 → 深色模式
neutral-50 (bg) → neutral-950 (bg)
neutral-100 (bg-subtle) → neutral-900 (bg-subtle)
neutral-200 (border) → neutral-800 (border)
neutral-300 (border-strong) → neutral-700 (border-strong)
neutral-500 (text-muted) → neutral-400 (text-muted)
neutral-600 (text-subtle) → neutral-300 (text-subtle)
neutral-900 (text) → neutral-50 (text)
neutral-950 (heading) → neutral-50 (heading)
规则: 背景色阶反转 (50↔950, 100↔900, 200↔800)。文本色阶类似反转。中间色阶 (400–600) 偏移约 1–2 步。
primary-400 或 primary-500 代替 primary-600neutral-900 或 neutral-950 背景的对比度/* 浅色 */
:root {
--color-bg: var(--neutral-50);
--color-text: var(--neutral-900);
--color-primary: var(--primary-600);
}
/* 深色 */
.dark {
--color-bg: var(--neutral-950);
--color-text: var(--neutral-50);
--color-primary: var(--primary-400);
}
其美妙之处在于:组件引用语义令牌,而非原始色阶。切换主题只是交换令牌映射。
:root {
/* 字体 */
--font-size-base: 1rem;
--font-size-lg: 1.2rem;
/* 色彩 */
--color-primary-500: hsl(220, 80%, 50%);
/* 间距 */
--space-4: 1rem;
}
module.exports = {
theme: {
extend: {
fontSize: {
'xs': '0.694rem',
'sm': '0.833rem',
'base': '1rem',
'lg': '1.2rem',
'xl': '1.44rem',
},
colors: {
primary: {
50: 'hsl(220, 50%, 95%)',
500: 'hsl(220, 80%, 50%)',
900: 'hsl(220, 60%, 15%)',
},
},
},
},
}
{
"color": {
"primary": {
"500": { "$value": "hsl(220, 80%, 50%)", "$type": "color" }
}
},
"fontSize": {
"base": { "$value": "1rem", "$type": "dimension" }
}
}
每周安装数
103
代码仓库
GitHub 星标数
173
首次出现
2026年2月19日
安全审计
安装于
gemini-cli93
codex93
opencode93
github-copilot88
kimi-cli85
amp85
Generate type scales, color palettes, spacing systems, and dark mode derivations with math — not guessing. Includes WCAG contrast checking, systematic spacing grids, and production-ready CSS/Tailwind output.
fontSize = baseFontSize × ratio^step
| Ratio | Name | Value | Best for |
|---|---|---|---|
| Minor Second | 1.067 | Tight, minimal difference | Dense UI, dashboards |
| Major Second | 1.125 | Subtle progression | Apps, data-heavy interfaces |
| Minor Third | 1.200 | Balanced, versatile | Most websites, SaaS |
| Major Third | 1.250 | Clear hierarchy | Marketing sites, blogs |
| Perfect Fourth | 1.333 | Strong contrast | Editorial, landing pages |
| Augmented Fourth | 1.414 | Dramatic | Bold designs, portfolios |
| Perfect Fifth | 1.500 | Very dramatic | Hero-heavy designs |
Given a base size (typically 16px) and a ratio:
Step -2: 16 / ratio² = xs
Step -1: 16 / ratio = sm
Step 0: 16 = base
Step 1: 16 × ratio = lg
Step 2: 16 × ratio² = xl
Step 3: 16 × ratio³ = 2xl
Step 4: 16 × ratio⁴ = 3xl
Step 5: 16 × ratio⁵ = 4xl
Step 6: 16 × ratio⁶ = 5xl
Round to nearest 0.5px or convert to rem (÷ 16).
| Font Size | Line Height | Use |
|---|---|---|
| ≤ 14px | 1.6–1.7 | Small text, captions |
| 16–20px | 1.5–1.6 | Body text |
| 20–32px | 1.3–1.4 | Subheadings |
| 32–48px | 1.1–1.2 | Headings |
| 48px+ | 1.0–1.1 | Display/hero text |
Rule of thumb: As font size increases, line height decreases.
| Size | Letter Spacing | Why |
|---|---|---|
| Small text (≤14px) | 0.01–0.02em | Slightly open for readability |
| Body text | 0em (normal) | Don't touch it |
| Subheadings | -0.01em | Slightly tighten |
| Headings | -0.02em to -0.03em | Tighten as size grows |
| Display text | -0.03em to |
| Role | Weight | Tailwind |
|---|---|---|
| Body | 400 (Regular) | font-normal |
| Body emphasis | 500 (Medium) | font-medium |
| Subheading | 600 (Semibold) | font-semibold |
| Heading | 700 (Bold) | font-bold |
| Display | 800 (Extrabold) | font-extrabold |
:root {
--font-size-xs: 0.694rem; /* 11.1px */
--font-size-sm: 0.833rem; /* 13.3px */
--font-size-base: 1rem; /* 16px */
--font-size-lg: 1.2rem; /* 19.2px */
--font-size-xl: 1.44rem; /* 23px */
--font-size-2xl: 1.728rem; /* 27.6px */
--font-size-3xl: 2.074rem; /* 33.2px */
--font-size-4xl: 2.488rem; /* 39.8px */
--font-size-5xl: 2.986rem; /* 47.8px */
}
Every palette needs:
| Token | Purpose | Example |
|---|---|---|
primary | Main brand color, CTAs | Your brand color |
neutral | Text, borders, backgrounds | Gray (warm/cool/pure) |
success | Positive states | Green |
warning | Caution states | Amber/yellow |
error | Destructive states | Red |
For each base color, generate a 10-step shade scale. The base color is typically the 500 step.
Method: HSL manipulation
Starting from the base HSL:
| Step | Lightness Adjustment | Saturation Adjustment |
|---|---|---|
| 50 | +45% | -30% |
| 100 | +38% | -25% |
| 200 | +28% | -15% |
| 300 | +18% | -5% |
| 400 | +8% | 0% |
| 500 | 0% (base) | 0% (base) |
| 600 | -8% | +5% |
| 700 | -18% | +5% |
| 800 | -28% | 0% |
| 900 | -38% | -10% |
| 950 |
Clamp all values: lightness 0–100%, saturation 0–100%.
Map shade steps to semantic roles:
/* Light mode */
--color-bg: var(--neutral-50);
--color-bg-subtle: var(--neutral-100);
--color-bg-muted: var(--neutral-200);
--color-border: var(--neutral-200);
--color-border-strong: var(--neutral-300);
--color-text-muted: var(--neutral-500);
--color-text-subtle: var(--neutral-600);
--color-text: var(--neutral-900);
--color-text-heading: var(--neutral-950);
--color-primary: var(--primary-600);
--color-primary-hover: var(--primary-700);
--color-primary-bg: var(--primary-50);
--color-primary-text: white;
Contrast ratio = (L1 + 0.05) / (L2 + 0.05)
Where L1 = lighter relative luminance, L2 = darker.
For each channel (R, G, B):
sRGB = channel / 255
linear = sRGB <= 0.04045 ? sRGB / 12.92 : ((sRGB + 0.055) / 1.055) ^ 2.4
L = 0.2126 × R_linear + 0.7152 × G_linear + 0.0722 × B_linear
| Level | Ratio | Applies to |
|---|---|---|
| AA Normal Text | ≥ 4.5:1 | Body text (< 18px or < 14px bold) |
| AA Large Text | ≥ 3:1 | ≥ 18px regular or ≥ 14px bold |
| AAA Normal Text | ≥ 7:1 | Enhanced accessibility |
| AA UI Components | ≥ 3:1 | Borders, icons, focus rings |
| Shade | Approx Contrast | Passes |
|---|---|---|
| 300 | ~2.5:1 | ❌ Decorative only |
| 400 | ~3.5:1 | ✅ Large text, UI |
| 500 | ~4.5:1 | ✅ AA body text |
| 600 | ~6:1 | ✅ AA comfortable |
| 700 | ~8:1 | ✅ AAA body text |
When generating palettes, always verify:
text (900) on bg (50) → must be ≥ 4.5:1text-muted (500) on bg (50) → must be ≥ 4.5:1primary (600) on white → must be ≥ 4.5:1primary-text on primary (600) → must be ≥ 4.5:1border (200) on bg (50) → must be ≥ 3:1If a combo fails, adjust the darker color one step darker until it passes.
Everything is a multiple of 4px. Predictable, consistent, works with most font sizes.
:root {
--space-0: 0px;
--space-0.5: 2px;
--space-1: 4px;
--space-1.5: 6px;
--space-2: 8px;
--space-3: 12px;
--space-4: 16px;
--space-5: 20px;
--space-6: 24px;
--space-8: 32px;
--space-10: 40px;
--space-12: 48px;
--space-16: 64px;
--space-20: 80px;
--space-24: 96px;
--space-32: 128px;
}
This matches Tailwind's default scale exactly.
| Context | Spacing | Values |
|---|---|---|
| Inline icon gap | space-1 to space-2 | 4–8px |
| Button padding | space-2 × space-4 | 8px 16px |
| Card padding | space-4 to space-6 | 16–24px |
| Section gap (between elements) | space-6 to space-8 | 24–32px |
| Section padding (container) | space-12 to space-16 | 48–64px |
| Page section vertical rhythm | space-16 to space-24 | 64–96px |
| Token | Width | Use |
|---|---|---|
sm | 640px | Narrow content (auth forms) |
md | 768px | Blog posts, documentation |
lg | 1024px | App layouts |
xl | 1280px | Wide layouts |
2xl | 1536px | Full-width dashboards |
Don't manually pick dark mode colors. Derive them systematically:
Light mode → Dark mode
neutral-50 (bg) → neutral-950 (bg)
neutral-100 (bg-subtle) → neutral-900 (bg-subtle)
neutral-200 (border) → neutral-800 (border)
neutral-300 (border-strong) → neutral-700 (border-strong)
neutral-500 (text-muted) → neutral-400 (text-muted)
neutral-600 (text-subtle) → neutral-300 (text-subtle)
neutral-900 (text) → neutral-50 (text)
neutral-950 (heading) → neutral-50 (heading)
The rule: Background shades flip (50↔950, 100↔900, 200↔800). Text shades flip similarly. Middle shades (400–600) shift by ~1–2 steps.
primary-400 or primary-500 instead of primary-600neutral-900 or neutral-950 background/* Light */
:root {
--color-bg: var(--neutral-50);
--color-text: var(--neutral-900);
--color-primary: var(--primary-600);
}
/* Dark */
.dark {
--color-bg: var(--neutral-950);
--color-text: var(--neutral-50);
--color-primary: var(--primary-400);
}
The beauty: components reference semantic tokens, never raw shades. Switching themes is just swapping the token mapping.
:root {
/* Type */
--font-size-base: 1rem;
--font-size-lg: 1.2rem;
/* Colors */
--color-primary-500: hsl(220, 80%, 50%);
/* Spacing */
--space-4: 1rem;
}
module.exports = {
theme: {
extend: {
fontSize: {
'xs': '0.694rem',
'sm': '0.833rem',
'base': '1rem',
'lg': '1.2rem',
'xl': '1.44rem',
},
colors: {
primary: {
50: 'hsl(220, 50%, 95%)',
500: 'hsl(220, 80%, 50%)',
900: 'hsl(220, 60%, 15%)',
},
},
},
},
}
{
"color": {
"primary": {
"500": { "$value": "hsl(220, 80%, 50%)", "$type": "color" }
}
},
"fontSize": {
"base": { "$value": "1rem", "$type": "dimension" }
}
}
Weekly Installs
103
Repository
GitHub Stars
173
First Seen
Feb 19, 2026
Security Audits
Gen Agent Trust HubPassSocketPassSnykPass
Installed on
gemini-cli93
codex93
opencode93
github-copilot88
kimi-cli85
amp85
前端设计技能指南:避免AI垃圾美学,打造独特生产级界面
45,300 周安装
-0.05em| Tight tracking at large sizes |
info | Informational | Blue (can overlap primary) |
| -45% |
| -20% |