资讯动态

Primitive Tokens 深度解析:设计系统的原始地基

发布时间:2026/9/18 2:31:26 来源:尧图企业网站定制
Primitive Tokens 深度解析设计系统的原始地基【免费下载链接】ui-ux-pro-max-skillAn AI skill that provides design intelligence for building professional UI/UX across multiple platforms.项目地址: https://gitcode.com/gh_mirrors/ui/ui-ux-pro-max-skillPrimitive Tokens原始设计令牌是任何设计系统最底层的地基——它们定义了一组不带语义含义的原始设计值颜色、间距、字号、圆角、阴影、动效时长、层级等上层所有语义令牌Semantic Tokens和组件令牌Component Tokens都通过var()引用它们。本文基于 ui-ux-pro-max-skill 仓库中 primitive-tokens.md 的完整定义逐一拆解每个原始令牌族的作用、命名约定、使用场景与底层实现支撑。读完本文你将掌握如何搭建一套可扩展的 primitive token 体系、如何理解它与语义层/组件层的关系、如何用仓库配套脚本生成与校验令牌以及如何避免最常见的硬编码污染陷阱。1. 什么是 Primitive Tokens在 token-architecture.md 定义的三层令牌体系中Primitive Tokens 位于最底层┌─────────────────────────────────────────┐ │ Component Tokens │ Per-component overrides │ --button-bg, --card-padding │ ├─────────────────────────────────────────┤ │ Semantic Tokens │ Purpose-based aliases │ --color-primary, --spacing-section │ ├─────────────────────────────────────────┤ │ Primitive Tokens │ Raw design values │ --color-blue-600, --space-4 │ └─────────────────────────────────────────┘核心特征Primitive Tokens 是不带语义的原始值。--color-blue-600: #2563EB只表达这是蓝色系第 600 号色值而不表达这个颜色应该用在按钮上。语义层--color-primary: var(--color-blue-600)和组件层--button-bg: var(--color-primary)才负责含义赋值。层级用途何时变更Primitive基础值颜色、尺寸极少变更——它们是地基Semantic语义赋值主题切换亮/暗Component组件定制按组件需求定制这带来的核心收益是可替换性当品牌从蓝色换为绿色时只需改动 primitive 层的--color-blue-*系列值语义层与组件层无需任何修改同理暗色主题只需在.dark作用域重定义语义令牌primitive 层原封不动。2. 颜色令牌Color Scales2.1 灰色阶Gray Scale灰色阶是全套令牌中使用频率最高的色系承担背景、边框、次级文字等大量中性角色。primitive 文档给出从 50 到 950 的完整梯度:root { --color-gray-50: #F9FAFB; --color-gray-100: #F3F4F6; --color-gray-200: #E5E7EB; --color-gray-300: #D1D5DB; --color-gray-400: #9CA3AF; --color-gray-500: #6B7280; --color-gray-600: #4B5563; --color-gray-700: #374151; --color-gray-800: #1F2937; --color-gray-900: #111827; --color-gray-950: #030712; }数字越小越浅、越大越深。在语义层中这组值被大量引用--color-background: var(--color-gray-50)亮色背景、--color-foreground: var(--color-gray-900)正文前景、--color-border: var(--color-gray-200)边框、--color-muted-foreground: var(--color-gray-500)弱化文字等详见 semantic-tokens.md。提示primitive 层的灰阶在亮/暗双主题中扮演镜像角色——暗色模式下--color-background变为--color-gray-950、--color-foreground变为--color-gray-50而 primitive 值本身不变这正是原始值不动、语义值变换的典型体现。2.2 主色系Primary Colors - Blue主色选用蓝色系提供 50–900 九个色阶:root { --color-blue-50: #EFF6FF; --color-blue-100: #DBEAFE; --color-blue-200: #BFDBFE; --color-blue-300: #93C5FD; --color-blue-400: #60A5FA; --color-blue-500: #3B82F6; --color-blue-600: #2563EB; --color-blue-700: #1D4ED8; --color-blue-800: #1E40AF; --color-blue-900: #1E3A8A; }其中 500/600/700/800 在交互状态中承担关键角色--color-primary: var(--color-blue-600)—— 主要操作色--color-primary-hover: var(--color-blue-700)—— hover 加深--color-primary-active: var(--color-blue-800)—— 按下再加深--color-ring: var(--color-blue-500)—— 焦点环为什么每个色系要保持完整梯度因为语义层与组件层需要同色系不同明度来表达交互状态。若只用单一色值hover/active/focus 状态将无差异化组件将失去可感知的反馈层次。2.3 状态色Status Colors状态色直接映射到产品级反馈场景primitive 层只定义 500/600 两档语义层再补充 foreground:root { /* Success - Green */ --color-green-500: #22C55E; --color-green-600: #16A34A; /* Warning - Yellow */ --color-yellow-500: #EAB308; --color-yellow-600: #CA8A04; /* Error - Red */ --color-red-500: #EF4444; --color-red-600: #DC2626; /* Info - Blue */ --color-info: var(--color-blue-500); }注意--color-info这里直接引用了主色系的 blue-500——这说明 primitive 层允许跨色系引用它只是原始值仓库不承担语义命名职责。语义层在此基础上完成最终映射--color-success: var(--color-green-600); --color-warning: var(--color-yellow-500); --color-error: var(--color-red-600); --color-destructive: var(--color-red-600);3. 间距令牌Spacing Scale3.1 4px 基准单位系统primitive 文档明确说明间距采用4px 基准单位系统所有间距值都是 4px 的整数倍含 0.5 倍档位:root { --space-0: 0; --space-px: 1px; --space-0-5: 0.125rem; /* 2px */ --space-1: 0.25rem; /* 4px */ --space-1-5: 0.375rem; /* 6px */ --space-2: 0.5rem; /* 8px */ --space-2-5: 0.625rem; /* 10px */ --space-3: 0.75rem; /* 12px */ --space-3-5: 0.875rem; /* 14px */ --space-4: 1rem; /* 16px */ --space-5: 1.25rem; /* 20px */ --space-6: 1.5rem; /* 24px */ --space-7: 1.75rem; /* 28px */ --space-8: 2rem; /* 32px */ --space-9: 2.25rem; /* 36px */ --space-10: 2.5rem; /* 40px */ --space-12: 3rem; /* 48px */ --space-14: 3.5rem; /* 56px */ --space-16: 4rem; /* 64px */ --space-20: 5rem; /* 80px */ --space-24: 6rem; /* 96px */ }为什么用 rem 而非 pxrem 以根元素字号为基准用户调整浏览器默认字号无障碍场景常见时间距、字号会等比缩放保证整体比例不变。注释中的 px 值仅供设计还原参考。使用规律4px 整数倍使不同组件、不同页面之间的留白保持视觉节奏统一。语义层在此基础上定义--spacing-component组件内距、--spacing-section区块间距、--spacing-page-x/y页面边距等更高层别名。真实工程中用--space-*替换散落的margin: 12px、padding: 24px是消除硬编码污染的第一步。4. 字体令牌Typography Scale4.1 字号Font Sizes:root { --font-size-xs: 0.75rem; /* 12px */ --font-size-sm: 0.875rem; /* 14px */ --font-size-base: 1rem; /* 16px */ --font-size-lg: 1.125rem; /* 18px */ --font-size-xl: 1.25rem; /* 20px */ --font-size-2xl: 1.5rem; /* 24px */ --font-size-3xl: 1.875rem; /* 30px */ --font-size-4xl: 2.25rem; /* 36px */ --font-size-5xl: 3rem; /* 48px */ }该梯度与 Tailwind 默认字号刻度完全一致便于后续映射到 Tailwind 主题见 tailwind-integration.md。语义层基于它构建标题/正文/标签体系--font-heading: var(--font-size-2xl); --font-heading-lg: var(--font-size-3xl); --font-body: var(--font-size-base); --font-caption: var(--font-size-xs);4.2 行高Line Heights:root { --leading-none: 1; --leading-tight: 1.25; --leading-snug: 1.375; --leading-normal: 1.5; --leading-relaxed: 1.625; --leading-loose: 2; }行高使用无单位的倍数而非固定像素这是最佳实践行高与字号成比例字号变化时行距自动适配。标题通常用 tight/snug紧凑正文用 normal/relaxed舒展引用块或说明文字可用 loose。4.3 字重Font Weights:root { --font-weight-normal: 400; --font-weight-medium: 500; --font-weight-semibold: 600; --font-weight-bold: 700; }字重同样以数值令牌抽象避免在组件中直接写font-weight: 600。组件层典型用法是--button-font-weight: var(--font-weight-medium)。4.4 字间距Letter Spacing:root { --tracking-tighter: -0.05em; --tracking-tight: -0.025em; --tracking-normal: 0; --tracking-wide: 0.025em; --tracking-wider: 0.05em; }字间距使用em单位相对字号常用场景大标题压缩字距tight/tighter提升紧凑感小号标签或全大写按钮放宽字距wide/wider提升可读性。5. 圆角令牌Border Radius:root { --radius-none: 0; --radius-sm: 0.125rem; /* 2px */ --radius-default: 0.25rem; /* 4px */ --radius-md: 0.375rem; /* 6px */ --radius-lg: 0.5rem; /* 8px */ --radius-xl: 0.75rem; /* 12px */ --radius-2xl: 1rem; /* 16px */ --radius-3xl: 1.5rem; /* 24px */ --radius-full: 9999px; }圆角刻度从 0 到胶囊形9999px。组件层映射示例按钮--button-radius: var(--radius-md)、卡片--card-radius: var(--radius-lg)、徽章--badge-radius: var(--radius-full)。--radius-full用于胶囊按钮、Tag、头像等完全圆角元素。注意primitive 文档中--radius-default: 0.25rem4px与 token-architecture 中示例的 0.5rem 略有差异应以 primitive-tokens.md 为准——它是本仓库该体系的最终定义来源。6. 阴影令牌Shadows:root { --shadow-none: none; --shadow-sm: 0 1px 2px 0 rgb(0 0 0 / 0.05); --shadow-default: 0 1px 3px 0 rgb(0 0 0 / 0.1), 0 1px 2px -1px rgb(0 0 0 / 0.1); --shadow-md: 0 4px 6px -1px rgb(0 0 0 / 0.1), 0 2px 4px -2px rgb(0 0 0 / 0.1); --shadow-lg: 0 10px 15px -3px rgb(0 0 0 / 0.1), 0 4px 6px -4px rgb(0 0 0 / 0.1); --shadow-xl: 0 20px 25px -5px rgb(0 0 0 / 0.1), 0 8px 10px -6px rgb(0 0 0 / 0.1); --shadow-2xl: 0 25px 50px -12px rgb(0 0 0 / 0.25); --shadow-inner: inset 0 2px 4px 0 rgb(0 0 0 / 0.05); }阴影采用 Tailwind 同款的两层阴影组合主阴影 偏移方向阴影透明度使用rgb(0 0 0 / 0.05)现代空格语法。层级用途sm用于按钮等小元素轻微浮起default用于卡片默认态md用于卡片 hover 提升lg/xl用于弹窗如组件层--dialog-shadow: var(--shadow-lg)2xl用于强调浮层。7. 动效令牌Motion / Duration:root { --duration-75: 75ms; --duration-100: 100ms; --duration-150: 150ms; --duration-200: 200ms; --duration-300: 300ms; --duration-500: 500ms; --duration-700: 700ms; --duration-1000: 1000ms; /* Semantic durations */ --duration-fast: var(--duration-150); --duration-normal: var(--duration-200); --duration-slow: var(--duration-300); }这是 primitive 文档中唯一的半语义定义底层提供从 75ms 到 1000ms 的完整时间梯度同时预置三个语义别名fast/normal/slow。在组件中应优先使用语义别名例如按钮过渡transition: background var(--duration-fast)。较长的 500/700/1000ms 用于页面级动画或进度类动效。8. 层级令牌Z-Index Scale:root { --z-auto: auto; --z-0: 0; --z-10: 10; --z-20: 20; --z-30: 30; --z-40: 40; --z-50: 50; --z-dropdown: 1000; --z-sticky: 1100; --z-modal: 1200; --z-popover: 1300; --z-tooltip: 1400; }z-index 是最容易被滥用为魔数的令牌族。primitive 层同时提供数值刻度0–50步进 10与语义层级的安全区1000 起每层 100。这样设计的原因数值刻度用于页面内相对层级而 1000 语义档位用于浮层体系保证 dropdown/sticky/modal/popover/tooltip 之间有稳定的层级差避免出现z-index: 999999之类的魔数。9. 命名约定与完整令牌清单primitive 令牌统一遵循--{category}-{item}-{variant}结构详见 token-architecture.md 的命名约定章节类别命名模式示例color--color-{色系}-{梯度}--color-gray-100、--color-blue-600space--space-{数值}--space-4、--space-2-5font-size--font-size-{档位}--font-size-sm、--font-size-2xlleading--leading-{风格}--leading-tight、--leading-normalfont-weight--font-weight-{档位}--font-weight-semiboldtracking--tracking-{风格}--tracking-wideradius--radius-{档位}--radius-lg、--radius-fullshadow--shadow-{档位}--shadow-mdduration--duration-{毫秒}--duration-200z--z-{数值/语义}--z-40、--z-modal10. 在工程中落地从 JSON 到 CSS 再到校验10.1 用模板 JSON 定义原始令牌primitive 文档给出的是最终 CSS 形态而仓库提供的 design-tokens-starter.json 是其上游 JSON 数据源采用 W3C Design Tokens Community Group 的$value/$type格式。primitive 层在 JSON 中位于顶层primitive键下{ primitive: { color: { gray: { 50: { $value: #F9FAFB, $type: color } }, blue: { 600: { $value: #2563EB, $type: color } } }, spacing: { 4: { $value: 1rem, $type: dimension } }, fontSize: { sm: { $value: 0.875rem, $type: dimension } } } }语义层通过{primitive.color.blue.600}这样的引用语法指向原始值组件层再引用语义层。10.2 生成 CSS仓库配套脚本 generate-tokens.cjs 将上述 JSON 一键生成 CSS 变量文件node scripts/generate-tokens.cjs --config tokens.json -o tokens.css脚本工作流程源码可见parseArgs()解析-c/--config、-o/--output、-f/--formatcss | tailwind参数resolveReference()递归解析{primitive.color.blue.600}形式的引用链flattenTokens()将嵌套 JSON 扁平化为--category-item-variant形式的 CSS 变量generateCSS()按PRIMITIVES → SEMANTIC → COMPONENTS → DARK MODE四段输出generateTailwind()将语义层--color-*变量转换为 Tailwindtheme.extend.colors片段。--format tailwind可进一步生成 Tailwind 颜色配置node scripts/generate-tokens.cjs --config tokens.json --format tailwind10.3 校验杜绝硬编码validate-tokens.cjs 用于扫描代码库找出本应使用令牌却写成魔数的地方node scripts/validate-tokens.cjs --dir src/ node scripts/validate-tokens.cjs --dir src/ --fix # 仅提示建议不自动改写它检测四类违规硬编码 hex 颜色#RGB/#RRGGBB、硬编码 RGB 颜色、两位及以上像素值、CSS 中的硬编码 rem 值并跳过tailwind.config、globals.css、tokens.css/json等令牌定义文件。仓库测试 test_validate_tokens.py 验证了关键回归场景即使一行中同时存在var(--...)引用和硬编码值硬编码值仍会被正确标记为违规而纯令牌行不会产生误报。11. 常见误区与最佳实践综合 primitive 文档、语义层文档与校验脚本的规则落地时需注意组件中绝不直接使用 primitive 值。.card { background: var(--color-gray-50) }是错误用法应写为var(--color-card)语义层。primitive 只应被语义层/组件层引用组件消费语义层这是 semantic-tokens.md 明确强调的规则。颜色禁用裸 hex。SKILL.md 的最佳实践明确指出Never use raw hex in components - always reference tokens。间距/字号一律走 token从校验脚本的pixelValue/remValue规则可见除 0 与 1px 外的散落像素值和 rem 值都会被标记。语义别名优先动效使用--duration-fast/normal/slow而非直接写150ms层级使用--z-modal而非1200。primitive 是极少变更层品牌换色只改 primitive 色值主题切换只改 semantic 覆盖.dark { --color-background: var(--color-gray-950); ... }组件层保持零改动。12. 相关阅读primitive-tokens.md本文主题全部原始令牌定义token-architecture.md三层令牌架构与命名约定semantic-tokens.md语义层如何引用 primitive 并支撑暗色主题component-tokens.md组件层如何消费语义层tailwind-integration.md将令牌映射到 Tailwind 配置design-tokens-starter.json三层令牌 JSON 模板generate-tokens.cjs 与 validate-tokens.cjs生成与校验脚本SKILL.md设计系统技能总览与最佳实践【免费下载链接】ui-ux-pro-max-skillAn AI skill that provides design intelligence for building professional UI/UX across multiple platforms.项目地址: https://gitcode.com/gh_mirrors/ui/ui-ux-pro-max-skill创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价