关于 ui-design
面向 UI 开发者的界面设计技能,汇集组件、布局、表单、响应式和无障碍设计实践。它建议先读取项目设计上下文,并通过截图检查实现效果。
主要功能
- 01按原子设计组织组件
- 02提供视觉层级与交互状态规范
- 03涵盖导航、表单和反馈模式
- 04指导响应式与无障碍设计
- 05通过截图验证页面效果
适用场景
- 01规划页面组件与视觉层级
- 02设计表单及加载、错误状态
- 03检查移动端和桌面端布局
MCP 相关
文档提到在用户提供 Figma URL 时,使用 Figma MCP 的 get_design_context 和 get_screenshot 获取设计上下文与截图。
安装
复制下面的命令,在终端中运行。
$
npx skills add https:/ / github.com/ arnavpuri/ designskills --skill ui-design安装后在 Claude Code 中输入/ui-design确认已加载。
详细介绍
UI 设计模式
开始之前:加载设计上下文
- 阅读
.agents/design-context.md(由design-context技能编写)。如果该文件不存在,请在tailwind.config.*或:rootCSS 变量中查找令牌。如果没有任何内容,请使用默认值(主色#2563EB、辅助色#7C3AED、强调色#F59E0B、Tailwind 灰色中性色、标题和正文使用 Inter、极简风格),并告知用户使用了默认值——建议运行design-context。 - 将令牌映射到 CSS 变量一次,然后只使用这些变量:
--color-primary、--color-primary-light、--color-primary-dark、--color-secondary、--color-accent、--color-neutral-50…--color-neutral-900、--color-success/-warning/-error、--font-heading、--font-body、--font-mono、--radius,以及以 4px 为基准的间距比例。 - **Tailwind:**以
primary、primary-light、primary-dark、secondary、accent、neutral-*、font-heading、font-body的名称公开相同变量(v3 使用theme.extend,v4 使用@theme)。以下示例中的indigo-*/gray-*类是这些令牌的占位符。 - **Figma:**如果用户提供了 Figma URL,请使用 Figma MCP(
get_design_context、get_screenshot)获取设计并与之匹配;对于该设计,它优先于上下文文件。 - 让风格原型决定圆角、阴影深度,以及第 9 节(趋势)的采用程度——极简风格和企业风格完全不采用。
1. 组件设计原则(原子设计)
分层构建 UI。绝不要从完整页面开始——从最小的部分开始。
层级
- 令牌 — 颜色、间距、圆角、阴影、排版比例
- 原子 — 按钮、输入框、徽章、头像、图标
- 分子 — 搜索栏(输入框 + 按钮)、表单字段(标签 + 输入框 + 错误提示)、卡片标题(头像 + 名称 + 时间戳)
- 有机体 — 导航栏、首屏区域、评论串、定价表
- 模板 — 由有机体组成的页面布局
- 页面 — 使用真实数据的模板
规则
- 每个组件都应在其根元素作用域内拥有自己的一组 CSS 自定义属性。
- 优先采用组合而非配置。带有
children的Card优于带有 15 个属性的Card。 - 组件默认应为无状态。将状态提升到更高层级。
/* Token layer — values come from .agents/design-context.md (defaults shown) */
:root {
--color-primary: #2563EB;
--color-surface: #FFFFFF;
--radius-md: 0.75rem;
--shadow-sm: 0 1px 2px oklch(0% 0 0 / 0.05);
--space-1: 0.25rem;
--space-2: 0.5rem;
--space-3: 0.75rem;
--space-4: 1rem;
--space-6: 1.5rem;
--space-8: 2rem;
--space-12: 3rem;
--space-16: 4rem;
}
**标准间距比例(适用于所有 UI 技能):**以 4px 为基准——4、8、12、16、24、32、48、64px(Tailwind 1, 2, 3, 4, 6, 8, 12, 16)。不要使用比例之外的数值。
2. 视觉层级框架
控制视线的落点。按重要性排列每个元素,并使用以下手段进行调整:
| 手段 | 高强调 | 中强调 | 低强调 |
|---|---|---|---|
| 尺寸 | 2rem+ 标题 | 1rem 正文 | 0.75rem 说明文字 |
| 字重 | 700–800 粗体 | 500 中等 | 400 常规 |
| 颜色 | 主色或高对比度文本 | 弱化文本(neutral-600) | 柔和文本(neutral-500——在白色背景上仍能达到 4.5:1 对比度的最浅灰色) |
| 间距 | 周围留出更多空白 | 标准间距 | 更紧凑的间距 |
| 位置 | 左上或居中 | 页面中部 | 底部或侧边栏 |
眯眼测试
眯起眼睛或将页面缩小到 25%。如果仍能辨认主要操作和主标题,说明层级处理有效。
Tailwind 实现
<h1 class="text-4xl font-extrabold tracking-tight text-gray-950">
Ship faster with AI
</h1>
<p class="mt-4 text-lg text-gray-600 max-w-2xl">
Build production-ready components in minutes, not hours.
</p>
<span class="text-xs text-gray-500 uppercase tracking-wide">
Updated 2 hours ago
</span>
3. 交互状态
每个交互元素都需要包含全部五种状态,无一例外。
状态定义
.btn-primary {
/* Default */
background: var(--color-primary);
color: white;
border-radius: var(--radius-md);
padding: var(--space-2) var(--space-4);
font-weight: 600;
transition: background-color 150ms ease, box-shadow 150ms ease, transform 150ms ease, filter 150ms ease;
/* Hover — subtle lift or brightness shift */
&:hover {
filter: brightness(1.1);
box-shadow: 0 4px 12px oklch(0% 0 0 / 0.15);
transform: translateY(-1px);
}
/* Active — pressed feel */
&:active {
transform: translateY(0);
filter: brightness(0.95);
box-shadow: var(--shadow-sm);
}
/* Focus — visible ring for keyboard users */
&:focus-visible {
outline: 2px solid var(--color-primary);
outline-offset: 2px;
}
/* Disabled — dimmed, no hover/active effects (don't add pointer-events: none — it hides the not-allowed cursor) */
&:disabled {
opacity: 0.5;
cursor: not-allowed;
transform: none;
box-shadow: none;
filter: none;
}
}
Tailwind 简写
<button class="bg-indigo-600 text-white px-4 py-2 rounded-lg font-semibold
hover:bg-indigo-500 hover:-translate-y-0.5 hover:shadow-lg
active:translate-y-0 active:bg-indigo-700
focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-indigo-600
disabled:opacity-50 disabled:cursor-not-allowed disabled:pointer-events-none
transition-all duration-150">
Click me
</button>
4. 反馈模式
加载状态
- **优先使用骨架屏,而非加载动画。**展示即将出现的内容形状。
- 在占位块上使用
motion-safe:animate-pulse,并将区域标记为aria-busy="true",同时添加 sr-only 的 "Loading…" 标签。 - 在触发加载的操作附近内联显示加载状态。
<div class="motion-safe:animate-pulse space-y-3" aria-busy="true">
<span class="sr-only">Loading…</span>
<div class="h-48 bg-gray-200 rounded-xl"></div>
<div class="h-4 bg-gray-200 rounded w-3/4"></div>
<div class="h-4 bg-gray-200 rounded w-1/2"></div>
</div>
成功状态
- 使用绿色强调色、勾选图标和简短的确认文本。
- 使用
role="status"播报(礼貌型实时区域)。在 5 秒或更长时间后自动消失;包含操作的消息绝不能自动消失。
错误状态
- 使用红色强调色、描述性消息和恢复操作。
- 别只说“错误”。说明出了什么问题,以及该怎么做。
- 不要只依赖红色:搭配图标和文本;对于提交后出现的错误,使用
role="alert"。
空状态
- 使用插图或图标、说明,以及用于解决问题的主要操作。
<div class="text-center py-16">
<svg class="mx-auto h-12 w-12 text-gray-400" aria-hidden="true"></svg>
<h3 class="mt-4 text-lg font-semibold text-gray-900">No messages yet</h3>
<p class="mt-2 text-sm text-gray-500">Start a conversation to see messages here.</p>
<button type="button" class="mt-6 bg-indigo-600 text-white px-4 py-2 rounded-lg">
New message
</button>
</div>
5. 导航模式
侧边栏导航
- 桌面端宽度:240–280px,可折叠至 64px(仅显示图标)。
- 按类别对项目分组,并使用低调的分区标题。
- 当前项目:使用填充背景、粗体文本、左侧强调条,以及
aria-current="page"。
顶部导航
- 固定或粘贴在顶部。高度:56–64px。
- Logo 在左侧,导航链接居中或靠左,操作项在右侧。
- 移动端:在
md断点折叠为汉堡菜单。
标签页
- 用于切换同一上下文中的视图。
- 当前标签页:使用主色的底部边框(2–3px)和粗体文本。使用
role="tablist"/role="tab",并设置aria-selected和方向键导航(如果每个标签页都有自己的 URL,则使用普通链接)。 - 标签页不得超过 7 个。更多内容使用下拉溢出菜单。
面包屑
- 使用
/或>作为分隔符。 - 当前页面不是链接,只显示文本。
- 路径较长时截断中间项目。
6. 表单设计
规则
- 标签置于输入框上方——不要使用浮动标签或行内标签。始终保持可见。
- 单列布局——多列表单会降低完成率。
- 使用低调的分区分隔线将相关字段分组。
- 行内验证——在失焦时验证,而不是每次按键都验证。
- 错误消息显示在字段下方,使用红色,并提供具体指导。
- 主要操作在表单底部左对齐。次要操作使用文本链接。
<div class="space-y-1.5">
<label for="email" class="block text-sm font-medium text-gray-700">
Email address
</label>
<input
type="email"
id="email"
class="block w-full rounded-lg border border-gray-300 px-3 py-2
text-gray-900 placeholder:text-gray-400
focus:border-indigo-500 focus:ring-2 focus:ring-indigo-500/20
transition-colors"
placeholder="[email protected]"
autocomplete="email"
aria-describedby="email-error"
/>
<p id="email-error" class="text-sm text-red-600 hidden">Please enter a valid email address.</p>
</div>
7. 将无障碍作为设计的一部分
无障碍不是事后才考虑的事项,而是从一开始就应纳入的设计约束。
对比度
- 普通文本:最低对比度为 4.5:1(WCAG 2.2 AA)。
- 大号文本(常规字重 ≥24px,或粗体 ≥18.66px):最低对比度为 3:1。
- 非文本 UI(输入框边框、图标、焦点环、图表标记):与相邻颜色的对比度至少为 3:1。
- 占位文本不能替代标签;如果占位文本承载信息,其对比度也应达到 4.5:1。
- 使用 oklch 色彩空间进行感知均匀的对比度调整。
焦点指示器
- 移除
outline时,必须提供替代样式。 - 使用
focus-visible(而非focus),避免鼠标点击时显示焦点环。 - 焦点环:2px 实线,偏移 2px,使用主色,并确保与背景的对比度达到 3:1。
- 聚焦元素不得被粘贴式页眉或页脚遮挡(WCAG 2.4.11)——将
scroll-padding-top设置为与页眉等高。
目标尺寸
- WCAG 2.5.8(AA):指针目标至少为 24×24 CSS px(或者彼此间隔足够远,使直径 24px 的圆不会与相邻目标重叠)。
- 平台触控指南:44×44pt(Apple HIG)、48×48dp(Material)。主要触控目标使用 44px 或更大尺寸。
语义结构
- 每页一个
<h1>。 - 标题按顺序排列(
h1>h2>h3)。不要跳过级别。 - 使用
<nav>、<main>、<aside>、<footer>地标。 - 操作使用按钮,导航使用链接。不要使用
<div onclick>。 - 仅含图标的按钮应设置
aria-label。
动效
@media (prefers-reduced-motion: reduce) {
*, *::before, *::after {
animation-duration: 0.01ms !important;
animation-iteration-count: 1 !important;
transition-duration: 0.01ms !important;
scroll-behavior: auto !important;
}
}
8. 响应式断点策略
断点(Tailwind 默认值——所有 UI 技能的规范值)
| 名称 | 宽度 | 适用设备 |
|---|---|---|
sm | 640px | 横屏大屏手机 |
md | 768px | 平板电脑 |
lg | 1024px | 小型笔记本电脑 |
xl | 1280px | 台式电脑 |
2xl | 1536px | 大屏幕 |
移动优先规则
- 从移动端布局开始,在较大的断点上增加复杂度。
- 移动端使用堆叠列,在
md及以上断点使用并排布局。 - 在
md以下,导航变为汉堡菜单。 - 逐步增大字号:
text-2xl md:text-4xl lg:text-5xl。 - 移动端使用宽松的触控内边距:
p-4;桌面端收紧为:lg:p-2。
容器查询(现代 CSS)
.card-container {
container-type: inline-size;
}
@container (min-width: 400px) {
.card {
display: grid;
grid-template-columns: 200px 1fr;
}
}
9. 现代 UI 趋势
玻璃拟态
.glass {
background: oklch(100% 0 0 / 0.1);
backdrop-filter: blur(16px) saturate(180%);
border: 1px solid oklch(100% 0 0 / 0.15);
border-radius: 1rem;
}
玻璃效果只适用于繁杂的背景——请根据其后方最亮的区域检查文本对比度,并提供纯色回退方案:@supports not (backdrop-filter: blur(1px)) { .glass { background: oklch(20% 0.02 265 / 0.9); } }。
Bento 网格
.bento {
display: grid;
grid-template-columns: repeat(4, 1fr);
grid-auto-rows: minmax(200px, auto); /* fixed 200px rows clip long content */
gap: 1rem;
}
@media (max-width: 767px) { .bento { grid-template-columns: 1fr; } .bento .featured { grid-column: auto; grid-row: auto; } }
.bento .featured {
grid-column: span 2;
grid-row: span 2;
}
极光/网格渐变背景
.aurora {
background: linear-gradient(135deg, oklch(85% 0.15 280), oklch(80% 0.2 320), oklch(75% 0.18 200));
background-size: 400% 400%;
animation: aurora-shift 8s ease infinite;
}
@keyframes aurora-shift {
0%, 100% { background-position: 0% 50%; }
50% { background-position: 100% 50%; }
}
10. 高级 CSS 技术
:has() — 父级选择器
/* Highlight form group when input is focused */
.form-group:has(input:focus-visible) {
background: oklch(97% 0.01 265);
border-color: var(--color-primary);
}
/* Card changes layout when it contains an image */
.card:has(img) {
grid-template-rows: 200px 1fr;
}
Subgrid
.card-grid {
display: grid;
grid-template-columns: repeat(3, 1fr);
gap: 1.5rem;
}
.card {
display: grid;
grid-template-rows: subgrid;
grid-row: span 3; /* header, body, footer align across cards */
}
滚动驱动动画
/* Progressive enhancement: only where supported and motion is OK */
@supports (animation-timeline: view()) {
@media (prefers-reduced-motion: no-preference) {
.fade-in {
animation: fade-in linear both;
animation-timeline: view();
animation-range: entry 0% entry 100%;
}
}
}
@keyframes fade-in {
from { opacity: 0; transform: translateY(2rem); }
to { opacity: 1; transform: translateY(0); }
}
验证:渲染并检查
不要交付未经检查的代码。生成代码后:
- 在移动端和桌面端宽度下截图,例如运行
npx playwright screenshot --full-page --viewport-size=390,844 file://$PWD/index.html mobile.png,然后再使用--viewport-size=1440,900截图(或指向开发服务器 URL)。 - 打开两张图片并检查:没有水平滚动或文本裁切/重叠;层级一目了然;已应用品牌设计令牌;图片以正确的宽高比加载。
- 用 Tab 键遍历一次:每个交互元素都有可见的焦点环,且顺序合理。
- 至少检查一次你实现的每种状态(悬停、焦点、禁用、加载、空白、错误),并检查弱化文本的对比度。
- 修复发现的问题,并在报告完成前重新截图。
快速参考:设计检查清单
交付任何 UI 组件之前,请确认:
- 视觉层级清晰(眯眼测试通过)
- 所有交互元素都有悬停、激活、焦点可见和禁用状态
- 色彩对比度符合 WCAG 2.2 AA(文本为 4.5:1,大号文本和 UI 组件为 3:1)
- 目标区域 ≥24×24px(主要触控目标为 44px+)
- 已在 390px 和 1440px 下完成渲染并截图(参见“验证”)
- 焦点顺序合理(用 Tab 键遍历页面)
- 在所有断点下均能自适应(320px 至 1920px)
- 已设计加载、空白和错误状态
- 间距采用 4px 基准比例(4、8、12、16、24、32、48、64)
- 字体大小限制为 4–6 种
- 动效遵循
prefers-reduced-motion - 使用语义化 HTML(地标、标题、按钮与链接的区分)
评论
支持 Markdown