关于 interface-kit
interface-kit 是用于设计和实现界面的指南,为没有 DESIGN.md 的项目提供默认规范。内容涵盖无障碍、性能、排版、布局、配色与动效,并规定已有设计规范优先。
主要功能
- 01优先考虑无障碍与性能
- 02提供排版和空间布局指导
- 03使用语义化颜色令牌与深色模式
- 04按交互频率制定动效建议
- 05DESIGN.md 优先于默认规范
适用场景
- 01为没有设计系统的项目构建界面
- 02检查无障碍和交互细节
- 03统一排版、配色与间距
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ juliusbrussee/ skills --skill interface-kit安装后在 Claude Code 中输入/interface-kit确认已加载。
包含的文件
除 SKILL.md 外,安装时一起下载的参考资料和脚本。
references/accessibility-checklist.mdanimation-playbook.mdcomponent-patterns.mdreview-checklist.md详细介绍
Interface Kit:打造卓越界面的实现指南
如果项目根目录中存在 DESIGN.md,其设计令牌和规范将覆盖本技能中的所有默认设置。当项目没有设计系统时,本技能会提供合理的默认设置,以及无论是否存在设计系统都适用的实现指导。
如需深入了解任何章节,请参阅本技能
references/目录中的参考文件。
1. 核心理念
品味可以培养,并非与生俱来。研究优秀的界面为何让人感觉恰到好处。拆解你欣赏的应用——间距、节奏、阴影的分量。从“还不错”到“卓越”的差距,源自数百个细微决策;用户能感受到这些决策,却从不会有意识地察觉。
看不见的细节会层层累积。 一个圆角、一段缓动过渡、一道恰到好处的阴影——单独来看都无关紧要。但它们组合起来,便会成为“千百个几乎听不见的声音,和谐地一同歌唱”。这种累积效应,正是匠心与产出的区别。
美感就是优势。 精致并非虚荣。恰当的默认设置、经过考量的排版和有意设计的动效,都是实实在在的差异化优势。用户会信任那些让人感到用心的界面。投资者也会注意到。竞争对手无法轻易复制品味。
注重意图,而非强度。 大胆的极繁主义和精致的极简主义都行得通;真正行不通的是缺乏鲜明的主张。每个视觉决策都应源自明确的概念方向。如果你无法说明为何做出某项选择,就应重新考虑。
选定一个方向,并精准执行。 不要在不同风格之间犹豫不决。一张彻底贯彻粗野主义风格的页面,永远胜过一张“什么都有一点”的页面。坚定方向,然后不断打磨。
绝不要做出千篇一律的“AI 垃圾美学”。 不要在白色背景上无端添加渐变。不要用素材插画拼凑千篇一律的 Hero 区域。不要采用平庸、容易被遗忘、看起来属于任何产品的安全布局。每个界面都应有鲜明主张,让人一眼就能认出。
2. 优先级层级
实现 UI 时,按以下优先级依次处理。较高优先级的事项不可妥协;较低优先级的打磨则能进一步提升整体质量。
| 优先级 | 级别 | 含义 |
|---|---|---|
| 无障碍性 | CRITICAL | 对比度达到 4.5:1、支持键盘导航、采用 ARIA 语义、焦点环清晰可见。绝不交付排斥用户的内容。 |
| 性能 | HIGH | 使用 WebP/AVIF 图片、对首屏以下内容延迟加载、CLS < 0.1、仅在合成器线程上运行动画变换。 |
| 排版 | HIGH | 字体平滑、使用 text-wrap balance/pretty、数据采用 tabular-nums、行长最多 65ch。 |
| 布局与空间 | HIGH | 采用 4/8px 网格、使用同心圆角、优先考虑视觉对齐而非几何对齐。 |
| 颜色与主题 | MEDIUM | 使用 HSL 自定义属性和语义化令牌,分别测试深色模式的颜色配对。 |
| 动效与交互 | MEDIUM | 根据出现频率决定动画策略、动画时长为 150-300ms、默认使用 ease-out。 |
| 精致度与细节 | LOW | 采用多层阴影而非边框、为按钮添加按压反馈、使用错开进入动画。 |
绝不要为了追求 LOW 项而跳过 CRITICAL/HIGH 项。无法通过键盘导航的按钮,即使动画再精美,整体效果仍然是负面的。
3. 美学方向
在写下第一行 CSS 之前,先坚定选择一个大胆的美学方向。AI 生成的 UI 最常见的问题,就是趋同于同一种安全、平庸、容易被遗忘的风格。
选择一种风格
选择一种,并贯彻到底:
- 极简主义 — 留白充足、等宽字体、强烈对比、几乎不加装饰
- 极繁主义混乱风 — 层叠纹理、冲突的字体大小、信息密集、有意营造视觉噪声
- 复古未来主义 — CRT 发光效果、等宽字体终端、扫描线、暗色背景上的霓虹色
- 自然有机风 — 大地色调、圆润造型、纸张纹理、手绘点缀
- 奢华精致风 — 衬线标题、柔和配色、充足留白、细腻的金色或奶油色点缀
- 编辑/杂志风 — 戏剧化的字体层级、铺满版面的图像、打破网格的布局
- 活泼大胆风 — 明亮的原色、粗壮的边框、夸张的阴影、轻快的动效
让复杂度匹配设计愿景
极繁主义设计需要精心编写代码——层叠背景、复杂网格结构、多套字体。极简主义设计则要求精准打磨——当没有任何东西可以掩饰瑕疵时,每个像素的间距都更重要。
禁用清单(没有 DESIGN.md 时)
在没有现成设计系统的情况下构建时,请避免使用这些过度泛滥、一看就像“AI 生成”的默认方案:
- 字体:Inter、Roboto、Arial、system-ui 作为展示字体,Space Grotesk
- 颜色:白色背景上的紫蓝渐变
- 模式:居中标题文字 + CTA + 素材插画的通用主视觉区块
在浅色和深色主题、不同字体搭配、不同美学方向之间灵活变换。不要让不同项目采用相同的选择。
视觉肌理
通过以下方式增添层次感:渐变网格、噪点/颗粒叠加(filter: url(#noise))、层叠透明效果、细腻的背景图案、双色调图像处理。
DESIGN.md 优先于本节的所有内容。 如果 DESIGN.md 指定使用 Inter,就使用 Inter。如果它指定使用紫色渐变,就使用紫色渐变。禁用清单仅适用于没有设计系统、需要从零开始做美学选择的情况。
4. 排版基础
排版是影响设计效果最大的单一元素。做好了,平庸的布局也会让人感觉舒服;做不好,其他任何设计都无法补救。
根布局设置
html {
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
text-rendering: optimizeLegibility;
}
在根布局应用字体平滑。在 macOS 上,默认的子像素渲染会让文字看起来比设计师预期的更粗。
文本换行
h1, h2, h3, h4, h5, h6 {
text-wrap: balance;
}
p, li, dd, blockquote {
text-wrap: pretty;
}
balance 会均匀分配标题的各行文字。pretty 会避免正文中出现落单的词。
数字显示
.data-value, .price, .counter, [data-numeric] {
font-variant-numeric: tabular-nums;
}
对于任何动态更新的数字——价格、计数器、表格列——都使用 tabular-nums。否则,随着数字宽度变化,布局会发生偏移。
比例与节奏
- 基础字号:正文至少为 16px。任何可读内容都不要小于 14px。
- 行高:正文为 1.5-1.75,大标题为 1.1-1.3。
- 最大行长:正文使用
max-width: 65ch。行过长会影响可读性。 - 字体比例:选择一套一致的比例并坚持使用:12 / 14 / 16 / 18 / 24 / 32 / 48 / 64。
字体搭配
将独特的展示字体与精致的正文字体搭配使用。展示字体彰显个性,正文字体保证可读性。在同一字体家族中使用 font-weight 建立层级:
- 标题:600-700(半粗体到粗体)
- 正文:400(常规)
- 标签/UI:500(中等)
始终提供字体栈回退选项:
--font-display: "Instrument Serif", "Georgia", serif;
--font-body: "Söhne", "Helvetica Neue", sans-serif;
--font-mono: "JetBrains Mono", "Fira Code", monospace;
5. 颜色与主题
HSL 自定义属性(shadcn 模式)
:root {
--background: 0 0% 100%;
--foreground: 222.2 84% 4.9%;
--primary: 222.2 47.4% 11.2%;
--primary-foreground: 210 40% 98%;
--secondary: 210 40% 96.1%;
--secondary-foreground: 222.2 47.4% 11.2%;
--muted: 210 40% 96.1%;
--muted-foreground: 215.4 16.3% 46.9%;
--accent: 210 40% 96.1%;
--accent-foreground: 222.2 47.4% 11.2%;
--destructive: 0 84.2% 60.2%;
--destructive-foreground: 210 40% 98%;
--border: 214.3 31.8% 91.4%;
--ring: 222.2 84% 4.9%;
--radius: 0.5rem;
}
定义语义令牌:primary、secondary、destructive、muted、accent、background、foreground。通过语义名称引用颜色——不要在组件中硬编码十六进制颜色值。
深色模式
.dark {
--background: 222.2 84% 4.9%;
--foreground: 210 40% 98%;
/* ... desaturated, lighter tonal variants — NOT simply inverted */
}
深色模式并非“反转颜色”。应使用降低饱和度、色调更浅的变体。背景应采用深色,但不要纯黑(#000);文字应采用浅色,但不要纯白(#fff)。请单独测试深色模式下的对比度——在浅色模式下达标的颜色,在深色模式下可能不达标。
对比度要求
- WCAG AA 最低标准:普通文本为 4.5:1,大号文本(18px+ 粗体或 24px+ 常规字重)为 3:1
- 切勿仅通过颜色传达信息 — 始终搭配图标、标签或图案
- 使用浏览器开发者工具中的对比度检查器或 axe-core 进行测试
色彩信心
鲜明的主色搭配醒目的点缀色,效果胜过犹豫不决、均匀分布的配色。选定一到两种主色,让调色板中的其他颜色退居次要位置。自信的配色层次分明;犹豫不决的配色将颜色均匀铺开,显得平淡。
6. 空间设计
同心圆角
这是最常见的导致嵌套 UI 元素看起来“不对劲”的问题:
outer_radius = inner_radius + padding
/* Correct: concentric */
.card { border-radius: 16px; padding: 8px; }
.card-inner { border-radius: 8px; } /* 16 - 8 = 8 */
/* Wrong: same radius on parent and child */
.card { border-radius: 12px; }
.card-inner { border-radius: 12px; } /* Looks bloated */
当几何居中看起来不协调时,改为进行视觉对齐。播放/暂停图标、下拉箭头和不对称字形通常需要手动微调 1-2px,才能看起来居中。
用阴影替代边框
使用多层透明的 box-shadow 值营造自然的纵深感,而不是使用边框:
.elevated {
box-shadow:
0 1px 2px rgba(0, 0, 0, 0.04),
0 2px 4px rgba(0, 0, 0, 0.04),
0 4px 8px rgba(0, 0, 0, 0.04);
}
不同扩散范围的多层阴影能模拟光线的效果。单一的硬阴影看起来很不自然。
图像轮廓
为图像和媒体添加细微的内描边,使其在不同背景下都能保持一致的纵深感:
img, video {
outline: 1px solid rgba(0, 0, 0, 0.06);
outline-offset: -1px;
}
间距刻度
使用 4px / 8px 为基数的递增系统。每个间距值都应为 4 的倍数:
4 / 8 / 12 / 16 / 24 / 32 / 48 / 64 / 96 / 128
点击区域
所有交互元素的最小尺寸为 44x44px。如果视觉元素更小,可使用伪元素扩展点击区域:
.small-button::before {
content: "";
position: absolute;
inset: -8px;
}
Z-Index 刻度
定义分层刻度,切勿使用随意指定的值:
--z-base: 0;
--z-dropdown: 10;
--z-sticky: 20;
--z-overlay: 40;
--z-modal: 100;
--z-toast: 1000;
7. 动效与交互
基于使用频率的决策框架
这是做出动画决策时最重要的思维模型:
| 频率 | 示例 | 动画 |
|---|---|---|
| 每天 100 次以上 | 键盘快捷键、命令面板操作、切换标签页 | 无。 不添加任何动画。立即响应。 |
| 每天几十次 | 悬停效果、列表项导航、切换开关 | 移除或大幅缩短。 最长 50-100ms。 |
| 偶尔 | 模态框、抽屉、提示消息、页面过渡 | 标准动画。 150-300ms。 |
| 很少 / 首次使用 | 引导流程、庆祝效果、空状态 | 可增添惊喜感。 300-500ms,可更复杂。 |
高频动画会让交互显得迟缓。低频交互若没有动效,则会显得突兀。应根据使用频率分配动画时长。
自定义缓动曲线
内置 CSS 缓动(ease、ease-in-out)效果太弱。请定义自定义曲线:
:root {
--ease-out: cubic-bezier(0.23, 1, 0.32, 1);
--ease-in-out: cubic-bezier(0.77, 0, 0.175, 1);
--ease-drawer: cubic-bezier(0.32, 0.72, 0, 1);
--ease-spring: cubic-bezier(0.34, 1.56, 0.64, 1);
}
时长指南
| 元素 | 时长 |
|---|---|
| 按钮、切换开关 | 100-160ms |
| 工具提示 | 125-200ms |
| 下拉菜单、弹出框 | 150-250ms |
| 模态框、抽屉 | 200-500ms |
| 页面过渡 | 250-400ms |
UI 动画应控制在 300ms 以内。切勿在 UI 动画中使用 ease-in — 它会让动画前段停顿过久,显得迟缓。
进入与退出的不对称性
退出动画应比进入动画更柔和、更快。进入动画若为 250ms,退出动画应为 150-200ms。
拆分进入动画并错开播放
多个元素进入视口时,应按语义分组错开播放,间隔约 50-100ms:
.stagger-item {
animation: fadeSlideIn 300ms var(--ease-out) both;
}
.stagger-item:nth-child(1) { animation-delay: 0ms; }
.stagger-item:nth-child(2) { animation-delay: 60ms; }
.stagger-item:nth-child(3) { animation-delay: 120ms; }
缩放动画
切勿从 scale(0) 开始动画。应从 scale(0.9) 或更高的值开始,并结合不透明度变化:
@keyframes scaleIn {
from { opacity: 0; transform: scale(0.95); }
to { opacity: 1; transform: scale(1); }
}
按压反馈
所有可按压元素在 :active 状态下都应稍微缩小:
button:active {
transform: scale(0.97);
}
可中断性
交互状态变化应使用 CSS 过渡(而非关键帧动画)。过渡可以在进行中被打断;关键帧动画则不能。这对于悬停状态、切换开关,以及任何用户可能快速交互的元素都很重要。
弹出框的变换原点
弹出框的变换原点应与触发元素相关联 — 它们应从触发元素处展开,而不是从中心展开。例外:模态框始终从中心展开。
工具提示悬停延迟
后续悬停时跳过工具提示延迟。如果用户已经等待过一个工具提示,则立即显示下一个。
减少动态效果
@media (prefers-reduced-motion: reduce) {
*, *::before, *::after {
animation-duration: 0.01ms !important;
transition-duration: 0.01ms !important;
}
}
尊重 prefers-reduced-motion。减少动画,但不要完全取消不透明度和颜色过渡,因为它们能提供重要的反馈。
悬停门控
通过媒体查询控制悬停动画,避免触屏设备触发悬停状态后无法恢复:
@media (hover: hover) and (pointer: fine) {
.card:hover { transform: translateY(-2px); }
}
参考
references/animation-playbook.md,深入了解弹簧物理、手势驱动动画和复杂编排。
8. 组件打磨
基础组件
使用 Radix UI 基础组件,构建易于访问且不带样式的基础。使用 CVA (class-variance-authority) 实现类型安全的组件变体:
import { cva } from "class-variance-authority";
const buttonVariants = cva(
"inline-flex items-center justify-center rounded-md font-medium transition-colors focus-visible:outline-none focus-visible:ring-2",
{
variants: {
variant: {
default: "bg-primary text-primary-foreground hover:bg-primary/90",
destructive: "bg-destructive text-destructive-foreground hover:bg-destructive/90",
outline: "border border-input hover:bg-accent hover:text-accent-foreground",
ghost: "hover:bg-accent hover:text-accent-foreground",
},
size: {
sm: "h-9 px-3 text-sm",
default: "h-10 px-4 py-2",
lg: "h-11 px-8 text-lg",
},
},
defaultVariants: { variant: "default", size: "default" },
}
);
按钮
- 按下时缩小(在
:active上设置transform: scale(0.97)) - 显示可见的焦点环(绝不要在没有替代方案的情况下设置
outline: none) - 加载状态下用旋转指示器替换标签,同时保持按钮尺寸不变
- 禁用状态设置为
opacity: 0.5和pointer-events: none
卡片
- 卡片与内部元素的圆角保持同心
- 使用分层阴影(而非边框)营造层次感
- 悬停状态:轻微提升(
translateY(-1px))并增强阴影
对话框 / 模态框
- 限制焦点(键盘焦点无法移至后方元素)
- 按 ESC 关闭,点击遮罩层外部关闭
- 使用
transform-origin: center,进入动画采用淡入 + 缩放 - 设置
aria-modal="true"、role="dialog"、aria-labelledby
表单
- 始终显示标签,绝不要只使用占位符输入框
- 在字段附近显示错误消息,并使用
aria-live="polite"向屏幕阅读器提供提示 - 渐进式披露:仅在需要时显示高级字段
- 使用 React Hook Form + Zod 进行验证
主题
所有组件颜色均使用 shadcn CSS 变量模式(HSL 格式)。将客户端交互组件封装在服务端组件中,以兼容 Next.js App Router。
参考
references/component-patterns.md,查看包含可复制粘贴实现的完整组件目录。
9. 无障碍基础
优先使用语义化 HTML
优先使用 <button>、<nav>、<main>、<header>、<footer>、<article>、<section>,再考虑使用 ARIA。<button> 自带键盘处理、焦点管理和屏幕阅读器语义。<div onClick> 则没有这些功能。
键盘导航
- Tab / Shift+Tab:在可聚焦元素间移动
- Enter / Space:激活按钮和链接
- 方向键:在列表、菜单、标签页、单选组内导航
- Escape:关闭模态框、弹出层、下拉菜单
- Home / End:跳转至列表中的首项 / 末项
焦点管理
- 所有交互元素都要有可见的焦点环——绝不要在没有替代方案的情况下使用
outline: none - 在模态框内限制焦点(Tab 焦点在模态框内循环,而不是移至其后方)
- 模态框 / 弹出层关闭时,将焦点还原至触发元素
- 使用
focus-visible,仅为键盘用户显示焦点环,而不响应鼠标点击:
:focus-visible {
outline: 2px solid var(--ring);
outline-offset: 2px;
}
ARIA 属性
- 图标按钮使用
aria-label:<button aria-label="Close menu">X</button> - 使用
aria-labelledby将标题与区块关联 - 使用
aria-describedby将帮助文本或错误消息关联至输入框 - 动态内容更新(提示消息、表单错误)使用
aria-live="polite" - 装饰性元素(文本标签旁的图标)使用
aria-hidden="true" - 可切换元素(下拉菜单、手风琴)使用
aria-expanded
颜色与对比度
- WCAG AA:普通文本对比度为 4.5:1,大号文本为 3:1
- 绝不要只用颜色作为唯一提示——应搭配图标、文本或图案
- 在浅色和深色模式下都进行测试
图像与媒体
- 有意义的图像使用描述性
alt文本:alt="Dashboard showing 23% revenue growth" - 纯装饰性图像使用空
alt="" - 为视频添加字幕,为音频提供文字稿
导航辅助
- 跳过链接:第一个可聚焦元素,在获得焦点前隐藏:
<a href="#main-content" class="sr-only focus:not-sr-only">
Skip to main content
</a>
- 标题层级:按顺序使用 h1 至 h6,不跳级。每页仅使用一个
<h1>。
触控目标
- 交互区域至少为 44x44px
- 相邻触控目标之间至少间隔 8px
- 为较小的可视元素添加不可见内边距或伪元素,以扩大触控区域
测试
- 自动化:在 CI 中运行 axe-core,Lighthouse 无障碍评分达到 90+
- 手动:完整测试仅使用键盘进行导航
- 屏幕阅读器:使用 VoiceOver(macOS)或 NVDA(Windows)进行测试
- 视觉:将缩放比例调至 200%,检查是否有元素错位或重叠
完整的审查指南及通过/失败标准,请参阅
references/accessibility-checklist.md。
10. 交付前审查
在确认任何 UI 实现已完成之前,请逐项检查以下清单:
排版
- 已应用字体平滑(
-webkit-font-smoothing: antialiased) - 标题使用
text-wrap: balance - 动态数字使用
font-variant-numeric: tabular-nums
颜色
- 所有颜色均通过语义化令牌引用,组件中没有硬编码的十六进制颜色值
- 颜色对比度符合 WCAG AA(普通文本为 4.5:1,大号文本为 3:1)
- 已单独测试深色模式下的对比度
空间
- 嵌套圆角元素使用同心圆角
- 间距始终遵循 4px/8px 比例
- 交互元素的最小点击区域为 44x44px
- 适合时使用阴影代替边框
动效
- 动画频率与使用频率相匹配(高频操作不添加动画)
- 不使用
transition: all,仅指定具体属性 - 多个元素出现时,入场动画分开并错开播放
- 遵循
prefers-reduced-motion设置
无障碍
- 所有交互元素均可通过键盘访问
- 键盘导航时焦点环清晰可见(除非有替代方案,否则绝不使用
outline: none) - 优先使用语义化 HTML,再使用 ARIA
- 动态内容更新时使用
aria-live
扩展版 30 项清单(含严重性评级和自动化测试命令),请参阅
references/review-checklist.md。