视觉令牌(颜色、字号、间距、圆角、阴影、层级、动效)怎么命名、分层、存放和生成;深色模式与主题、字体、图标集、品牌图标,以及设计稿和代码怎么保持一致。
令牌源文件放在 Git 仓库并走 PR 评审;设计工具里的改动导出成文件差异后再合并
怎么检查:评审时检查令牌改动是否来自仓库内的文件差异;设计工具的同步记录能对应到某个 PR
为什么、来源
为什么:只存在设计工具里的变量没有版本、没有评审、没法回滚,也绑死在一个工具上。
令牌文件采用 DTCG 格式:每个令牌都有 $value,类型由自身或所在组的 $type 确定,并通过 JSON Schema 校验
怎么检查:CI 用 JSON Schema 校验器(如 AJV)校验所有 *.tokens.json
为什么、来源
为什么:类型不明的令牌,转换工具会猜错单位或格式,各端输出就不一致。
令牌之间不得有循环别名或指向不存在令牌的引用
怎么检查:CI 解析全部引用并做图遍历,发现环或悬空引用时失败
为什么、来源
为什么:循环或悬空引用会让构建失败,或者在某些工具里被静默替换成错误的值。
每个支持的主题组合都必须完整解析:必需的语义键(文字、背景、边框、状态)一个不缺,构建时不得静默回退到默认主题
怎么检查:CI 枚举支持的主题组合逐个构建,对照必需键清单,缺键即失败
为什么、来源
为什么:缺键时静默回退,深色模式里就会冒出浅色的背景或看不清的文字。
只用转换工具实测支持的 DTCG 特性;项目用到的每类令牌(颜色对象、复合令牌、主题解析等)都有兼容用例
怎么检查:维护一组覆盖所用特性的样例令牌和期望输出,CI 比对
为什么、来源
为什么:「支持 DTCG」不等于支持最新版的全部特性,Style Dictionary 官方就说明对 2025.10 还没完整支持。
生成的产物(CSS 变量、Swift、Kotlin、XML 资源等)不手改;CI 重新生成后必须与仓库内容一致
怎么检查:CI 跑令牌构建后执行 git diff --exit-code 检查生成目录
为什么、来源
为什么:手改的生成文件下次构建就被覆盖,而且源文件和产物从此对不上。
升级令牌转换工具前,在样例令牌上比对新旧输出,差异逐条确认
怎么检查:升级 PR 附上样例令牌的新旧输出差异
为什么、来源
为什么:转换工具的大版本常改默认格式和单位处理,不比对就会把视觉变化悄悄带进发布。
令牌分三层:原始值、语义、组件;平台适配层只做映射,不新增含义
怎么检查:评审令牌目录结构,看语义层是否只引用原始值、组件层是否只引用语义或原始值
为什么、来源
为什么:分层后换主题、换品牌只改映射,不用逐个组件改。
| 层 |
例子 |
谁用 |
| 原始值 |
color.blue.600、space.4 |
只给设计系统内部引用 |
| 语义 |
color.text.primary、color.surface.raised |
业务界面首选 |
| 组件 |
button.primary.background |
组件内部,由组件负责人维护 |
在采用设计令牌的项目里,业务界面只用语义或组件令牌,不写新的裸颜色、间距、圆角、阴影、z-index、动效值;例外要登记
怎么检查:样式 lint 禁止这些属性使用字面量(Web 可用 Stylelint 规则,CSS-in-JS 用 ESLint 规则);例外清单之外的命中让 CI 失败
为什么、来源
为什么:散落的字面量让换主题、调品牌变成全局搜索替换,视觉也会一点点漂移。
工具配置见 07。图片叠色、第三方嵌入等确实要用字面量的地方,写进例外清单(见 DSN-033)。
令牌名表达用途而不是取值:用 color.text.danger,不用 color.red;统一小写点分
怎么检查:命名脚本检查语义层和组件层的名字里不含色名或数值
为什么、来源
为什么:名字里写值,一换主题名字就成了谎话;按用途命名,Agent 和新人也能看名字选对令牌。
推荐结构 类别.用途.变体.状态,如 color.background.button.hover。不要把品牌名、主题名写进组件 API。
语义令牌和组件令牌写 $description,说明什么时候用
怎么检查:脚本列出缺描述的令牌,CI 给出警告
为什么、来源
为什么:只看名字很难区分 surface.raised 和 surface.overlay,描述能减少用错。
深色主题单独映射一套语义值,不用 filter: invert() 反转整页
怎么检查:样式 lint 禁止在根元素或大容器上使用 filter: invert(...)
为什么、来源
为什么:反相会把图片、品牌色、状态色一起反掉,层级关系也会颠倒。
深色下用表面的明度区分层级(画布、表面、浮层、选中),阴影要配合边框或表面色,不能只靠模糊半径。
主题按维度分开定义(如明暗、密度),列出支持的组合,不做任意自由组合
怎么检查:评审主题配置,看是否有明确的组合清单,且清单里的每个组合都在 DSN-004 的构建测试里
为什么、来源
为什么:维度叠加会让组合数爆炸,没列出的组合没人测过。
色阶可以用 OKLCH 生成,但发布值要做色域映射;输出广色域颜色时同时给 sRGB 回退
怎么检查:构建脚本检查每个颜色在 sRGB 内或带回退值,审查亮端和暗端的色相偏移
为什么、来源
为什么:OKLCH 的明度变化更均匀,适合生成色阶;但超出屏幕色域的值在不同设备上显示不同。
用成熟的色彩库做换算和色域映射,不自己写色阶算法。
为每个主题维护前景/背景配对表,CI 按 09 的对比度阈值逐对计算;不能凭 OKLCH 的 L 值判断达标
怎么检查:脚本读取配对表和各主题的解析结果,按 WCAG 公式计算对比度,低于 09 的阈值即失败
为什么、来源
为什么:OKLCH 的 L 是感知明度,和 WCAG 对比度的相对亮度公式不是一回事,同样的 L 值可能不达标。
状态色按语义家族定义(中性、信息、成功、警告、危险),不按色名定义
怎么检查:命名脚本检查状态类令牌使用语义家族名
为什么、来源
为什么:按语义定义才能在不同主题里换实际颜色;「颜色之外还要有文字或图标」的要求见 09。
图表配色用分类、顺序、发散三类色板令牌,不为新数据系列临时生成随机颜色
怎么检查:检查图表配置里的颜色是否引用色板令牌
为什么、来源
为什么:随机颜色每次渲染都可能变,相邻系列也可能撞色;固定色板可复现、可校对比度。
字号和行高成对定义为排版令牌,组件只用排版令牌,不私造新的字号
怎么检查:样式 lint 禁止 font-size、line-height 使用字面量
参考值:参考值(信息密度较高的中文后台,字号/行高,px):12/18、13/20、14/22、16/24、18/26、22/30、28/36。门户、教学、移动端应整体加大;没有标准出处,按真实中英文本截图调整。
为什么、来源
为什么:一套固定的字阶让层级清楚;每个组件自己定字号,页面很快就有十几种大小。
默认用系统字体栈;栈里要有中文字体,并以通用字体族结尾
怎么检查:检查字体令牌的回退链;在目标系统上截图确认中文实际显示的字体
为什么、来源
为什么:系统字体不占包体积,也更符合各平台的阅读习惯;缺中文字体时浏览器会挑一个不可控的字体。
Web 示例(按目标系统确认字体真实存在):
system-ui, -apple-system, "Segoe UI", "PingFang SC", "Microsoft YaHei", "Noto Sans CJK SC", sans-serif
随产品打包的字体必须允许再分发,并随包附带许可证文件;不得从操作系统或网上抽取商用字体打包
怎么检查:资产清单列出每个字体文件的来源、许可证和哈希;发布前人工核对
为什么、来源
为什么:系统自带的商用字体(如微软雅黑、苹方)只授权给系统本身使用,随产品分发有侵权风险。
思源黑体与 Noto Sans CJK 是同一字体家族的两个发行名,均为 SIL OFL 1.1:可以随软件分发,要保留版权声明和许可证;修改后再发布不能沿用保留字体名(Source / Noto)。
对中文字体做子集化后,在断网环境里截图检查不缺字
怎么检查:用覆盖常用字和业务专有字的样例页,在断网环境下截图人工检查
为什么、来源
为什么:中文字体体积大,子集化能省很多,但切掉的字会显示成方框或回退字体。
数字列、金额、计时器使用等宽数字(font-variant-numeric: tabular-nums)
怎么检查:检查表格和数字组件的样式;截图看列是否对齐
为什么、来源
为什么:比例数字宽度不一,数字一变列就跳动、对不齐。
间距用一套有名字的阶梯,页面和组件只从阶梯里取值
怎么检查:样式 lint 禁止 margin、padding、gap 使用字面量
参考值:参考阶梯(px):0、2、4、6、8、12、16、20、24、32、40、48、64、80,布局优先取 4 和 8 的倍数,2px 只用于小元素微调。没有标准出处,是常见做法。
为什么、来源
为什么:统一的阶梯让视觉节奏一致;成熟设计系统都用有名字的空间体系,但没有「必须 8px」的标准。
圆角和阴影各定少数几档令牌;阴影按层级含义命名,不按模糊半径命名
怎么检查:样式 lint 禁止 border-radius、box-shadow 使用字面量
参考值:参考值:圆角 0、4、8、12、16、full(px);阴影 none、sm、md、lg。没有标准出处。
为什么、来源
为什么:档位少才统一;按层级命名,深色主题里才能换成边框或表面色来表达。
z-index 只用项目的层级清单;第三方弹层组件的层级也纳入同一清单
怎么检查:扫描样式里的 z-index,不在清单内的值报错
参考值:参考清单:base 0、sticky 100、dropdown 200、popover 300、modal 400、toast 500。只是项目约定;浏览器 top layer(如原生 dialog)不受 z-index 影响,要单独验证。
为什么、来源
为什么:各写各的 99999 最后谁也盖不住谁;弹窗、下拉、提示的上下关系要在一处定。
紧凑模式用密度令牌调整尺寸和间距,不用 transform: scale 或 zoom 整页缩放
怎么检查:样式 lint 检查根元素和页面容器上的 scale、zoom
参考值:参考值:数据表行高舒适 44px、紧凑 36px;字号一般不随紧凑模式变小。没有标准出处。
为什么、来源
为什么:整页缩放会让文字发虚、像素对不齐、点击区域变小。
动效时长和缓动曲线用动效令牌,不在组件里写字面量
怎么检查:样式 lint 禁止 transition、animation 的时长和缓动使用字面量
参考值:参考值:instant 0ms、fast 120ms(悬停、颜色过渡)、normal 180ms(控件展开收起)、slow 280ms(面板、布局变化);standard 缓动 cubic-bezier(0.2, 0, 0, 1),exit 缓动 cubic-bezier(0.4, 0, 1, 1)。时长没有标准出处;原生端优先用系统动画参数。
为什么、来源
为什么:统一的时长和曲线让动效节奏一致,也方便在「减少动效」时集中关闭(行为要求见 09)。
过渡动画优先只改 transform 和 opacity,大面积模糊和无限循环的闪烁骨架要有理由
怎么检查:评审动效代码;对可疑页面录性能面板看布局和重绘
为什么、来源
为什么:改宽高、位置会触发重排,模糊和循环动画持续占用渲染,低端设备上会卡顿。
每个项目选定一个主图标集;平台原生图标作为有映射的例外
怎么检查:检查依赖清单和资源目录里的图标来源
参考值:参考尺寸 16、20、24px,同一图标集内统一线宽。
为什么、来源
为什么:不同图标集的线宽、端点、光学尺寸不同,混用后同样 20px 也看着不齐。
随产品分发的图标、插画、字体登记到资产清单:来源、许可证、版本或哈希
怎么检查:CI 检查资源目录里的每个文件都在清单中;新增条目由人核对许可证
为什么、来源
为什么:设计资产也是要分发的第三方组件,来源不明的素材有侵权风险,出了问题也无从追查。
许可口径和扫描工具见 27。SVG 打包前要检查外链、脚本和远程字体引用。
断网或内网部署的产品,运行时不得从外部地址加载字体、图标和插画
怎么检查:在断网环境里跑页面测试;Web 端用 CSP 限制字体和图片来源,并检查网络请求记录
为什么、来源
为什么:外链资源在内网里加载不出来,界面就缺字缺图;对外请求还会暴露使用信息。
常见漏网的是 Google Fonts、图标 CDN、在线徽章。自托管设计工具也要检查其默认的外部服务和更新检查。
品牌标志和应用图标保留矢量母稿,各平台按官方规范分别导出,不用一张位图通用
怎么检查:脚本检查各平台图标的尺寸和格式;评审看母稿是否在仓库或资产库中
为什么、来源
为什么:各平台对图标的尺寸、安全区、分层要求不同,一张图到处缩放会糊或被裁切。
- Web:SVG 母稿 + 多尺寸
favicon.ico + manifest 图标(含 maskable)。
- Apple:1024×1024 分层母稿,交给 Xcode 生成下游尺寸。
- Android:自适应图标 108×108dp 分层,主体在 66×66dp 安全区内,提供单色层。
- Windows:多尺寸 ICO 和 MSIX 资产。
具体打包和上架见 28–31。
视觉例外登记在一份清单里,写明范围、原因、负责人和复核日期;过期由 CI 提示
怎么检查:例外清单用 schema 校验必填项,CI 检查复核日期是否已过
为什么、来源
为什么:允许受控的例外,规则才能落地;没有到期日的例外会悄悄变成常态。
跨端统一令牌的名字和语义,不要求 px、pt、dp 数值逐一相同;原生端遵循平台的字体、图标和材质惯例
怎么检查:设计评审时按语义核对各端,不做像素比对
为什么、来源
为什么:各平台单位、系统字体和交互惯例不同,强求像素一致反而让原生端显得别扭。
项目用了组件库时,由令牌生成组件库的主题配置,不并行维护两套令牌
怎么检查:评审主题配置的来源,确认组件库主题值来自令牌构建产物
为什么、来源
为什么:组件库自带一套令牌(如 Ant Design 的基础、派生、别名令牌),两套各改各的就会对不上。
视觉改动的 PR 写明令牌差异(或说明没有令牌改动)、受影响的组件和主题,并附改动前后的截图
怎么检查:PR 模板固定这些栏目;改到令牌或样式目录时 CI 检查栏目非空
为什么、来源
为什么:评审者要能看到改了哪些令牌、影响到哪里;截图基线的生成和审批规则见 04。
没有符合条件的规则。
令牌格式
DTCG 设计令牌格式(Format、Color、Resolver 模块) · 社区组规范文本,按 W3C 社区组协议发布,可免费实现
备选:项目自定的简化 JSON(令牌很少且只有一端,但要写清到 DTCG 的映射)
不推荐:只用设计工具里的私有变量
令牌转换与多端生成
Style Dictionary · Style Dictionary 为 Apache-2.0
备选:Terrazzo(Style Dictionary 不支持项目要用的 DTCG 特性时,先做小范围验证);简单生成脚本(只有一端、令牌很少)
不推荐:自建完整的令牌语言或解析器
令牌校验
JSON Schema + AJV,加循环引用和必需键的检查脚本 · AJV 为 MIT
备选:其他 JSON Schema 校验器(项目不用 Node 时)
不推荐:只靠 TypeScript 类型检查令牌
设计工具
Figma Variables(联网团队) · Figma 为商业服务;Penpot 为 MPL-2.0
备选:Penpot 自托管(设计稿不能出网、需要内网部署或开源工具时;断网安装要单独验证);Tokens Studio 插件(需要在 Figma 里管理 DTCG 令牌并与 Git 同步时)
不推荐:把插件或设计工具当唯一事实来源
色阶生成与对比度计算
OKLCH 设计 + 成熟色彩库做换算、色域映射和对比度计算
备选:Material 3 的 HCT 动态配色(Android 风格或需要动态取色的项目)
不推荐:固定 HSL 亮度就认为对比度达标;自写「万能色阶算法」
中文字体
系统字体栈;需要打包时用思源黑体 / Noto Sans CJK · 思源黑体 / Noto Sans CJK 为 SIL OFL 1.1
备选:已购买再分发授权的商业字体(品牌有指定字体)
不推荐:从操作系统抽取商用字体随产品分发;从字体 CDN 在线加载
图标集(Web 与桌面)
Lucide · Lucide 为 ISC(部分图标源自 Feather,需同时保留 MIT 声明);Material Symbols 为 Apache-2.0
备选:Material Symbols(产品采用 Material 风格或主要面向 Android);Phosphor(需要多种字重风格时)
不推荐:不经评审混用多个图标集
原生图标
iOS / macOS 用 SF Symbols;Android 用 Material Symbols
备选:项目自有矢量图标集(品牌要求跨端统一图标造型)
不推荐:把 SF Symbols 带到 Web 或 Android 使用
✕ 错误做法:把 DTCG 稳定版说成「W3C 正式标准」
✓ 应该:写「W3C 社区组稳定报告」
✕ 错误做法:认为转换工具「支持 DTCG」就能无损处理全部新特性
✓ 应该:只用实测支持的特性,写兼容用例
✕ 错误做法:在各页面直接写 #1677ff、12px
✓ 应该:用语义令牌或组件令牌
✕ 错误做法:深色模式直接对整页反相
✓ 应该:单独映射一套语义值,逐对校验对比度
✕ 错误做法:OKLCH 的 L 相同就宣称对比度合规
✓ 应该:按 WCAG 公式实算前景和背景
✕ 错误做法:各处写 z-index: 99999
✓ 应该:用层级清单
✕ 错误做法:用整页 scale(0.85) 做紧凑模式
✓ 应该:用密度令牌
✕ 错误做法:混用 Lucide、Material、Heroicons 而不审风格
✓ 应该:每个项目一个主图标集
✕ 错误做法:内网系统仍从 CDN 加载字体和图标
✓ 应该:自托管资源,断网测试 + CSP
✕ 错误做法:把含真实客户信息的截图或设计稿传到外部 SaaS
✓ 应该:先脱敏,涉及个人信息出境按 27 处理
✕ 错误做法:为几个页面搭建实时双向令牌同步平台
✓ 应该:令牌文件 + 转换工具 + PR 评审