Rauno 两年前在 GitHub 上分享的 Web 界面指南,现在结合了 Vercel 的工程师与设计师的经验,发布了全新的版本。它提供了一系列关于如何设计高质量、易用且性能良好的 Web 界面的建议和最佳实践。
最佳实践,你需要通过在项目中维护 AGENTS.md 文件来确保生成的界面符合这些指南。 原文
键盘可访问所有功能。 所有操作都应可用键盘完成,并遵循 WAI-ARIA Authoring Patterns。
清晰的焦点指示。 每个可聚焦元素都要有可见的焦点样式。优先使用 :focus-visible
而非 :focus
,避免干扰鼠标用户;对控件分组使用 :focus-within
。
管理焦点。 需要时使用焦点陷阱,并按 WAI-ARIA 规范移动与归还焦点。
视觉目标与点击目标一致。 如视觉元素小于 24px,应将可点击区域扩展到 ≥ 24px;移动端最小 44px。
移动端输入框尺寸。 <input>
在移动端字体 ≥ 16px,避免 iOS Safari 聚焦时的自动缩放/平移;或设置 <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1" />
。
尊重缩放功能。 不要禁用浏览器缩放。
水合安全的输入框。 水合(hydration)后输入框不应丢失焦点或当前值。
不要阻止粘贴。 不要在 <input>
或 <textarea>
禁用粘贴。
按钮的加载态。 显示加载指示器,同时保留原按钮文案。
加载态的最短显示时长。 使用旋转器/骨架屏时,加入短暂显示延迟(约 150–300ms)和最短可见时间(约 300–500ms),避免快速返回时闪烁。React 的 <Suspense>
已内置类似机制。
URL 即状态。 将状态持久化到 URL,确保分享、刷新、前进/后退都能正确工作(如使用 nuqs 管理查询参数)。
乐观更新。 成功概率高时先行更新 UI,并与服务端结果对账;失败时给出错误提示并回滚或提供撤销。
省略号表示后续输入。 需要进一步输入的菜单项(如“重命名…”)用省略号结尾。
确认破坏性操作。 需要确认,或提供带缓冲时间的撤销。
避免控件双击触发缩放。 设置 touch-action: manipulation
。
点击高亮按设计控制。 设置 -webkit-tap-highlight-color
。
交互要有容错性。 宽松的点击目标、清晰的可用性暗示、可预测的行为,降低误操作(如利用“预测锥”概念)。
工具提示时机。 组内第一个工具提示延迟显示;同组后续提示不延迟。
过度滚动处理。 在模态/抽屉等场景有意设置 overscroll-behavior: contain
。
滚动位置持久化。 前进/后退应恢复上次滚动位置。
合适的自动聚焦。 桌面端如只有一个主要输入项可自动聚焦;移动端尽量少自动聚焦,以免键盘弹出导致布局抖动。
无“死区”。 看起来可交互的区域就应可交互,不要让用户猜哪里能点。
一切都能深链接。 过滤器、标签页、分页、展开面板等(凡是用到 useState 的地方)都应可通过 URL 定位。
干净的拖拽体验。 拖拽时禁用文本选择,并对不应交互的元素应用 inert
,避免选择/悬停与拖拽竞争。
链接就用链接。 导航使用 <a>
或 <Link>
,保证浏览器默认行为(Cmd/Ctrl + 点击、中键、右键新标签)可用;不要用 <button>
或 <div>
代替导航。
宣告异步更新。 提示与内联校验使用礼貌级别的 aria-live
。
本地化键盘快捷键。 适配非 QWERTY 布局;显示平台特定符号。
尊重 prefers-reduced-motion
。 提供减少动效的替代方案。
实现优先级。 能用 CSS 就不用主线程 JS。
优先级: CSS > Web Animations API > JS 动画库(如 motion)。
合成器友好。 优先动画 transform
、opacity
等 GPU 加速属性,避免触发布局/重绘(如 width
、height
、top
、left
)。
确有其必要。 只在有明确因果或能带来有意的愉悦时使用动画。
合适的缓动。 根据变化的尺寸、距离、触发方式选择缓动曲线。
可中断。 用户输入应能取消动画。
输入驱动。 避免自动播放;以用户操作为触发。
正确的变换原点。 让运动从“物理上合理”的位置出发。
不要用 transition: all
。 明确列出要过渡的属性(通常是 opacity
、transform
)。all
容易让影响布局的属性参与动画而卡顿。
跨浏览器的 SVG 变换。 将 CSS 变换/动画作用在 <g>
包裹上,并设置 transform-box: fill-box; transform-origin: center;
。Safari 曾在 SVG 的 transform-origin 上有兼容问题,分组可避免原点计算错误。
光学对齐。 当观感优先于几何准确时,可做 ±1px 的微调。
有意对齐。 每个元素都要有对齐依据:网格、基线、边缘或光学中心,不要“随便放”。
文本与图标的均衡。 并排时通过粗细、大小、间距或颜色让它们不打架。比如细线图标放在中等字重文本旁可能需要加粗描边。
响应式覆盖。 在手机、笔记本与超宽屏上验证;模拟超宽屏可把页面缩放到 50% 观察。
尊重安全区域。 使用安全区域变量,照顾刘海与系统内边距。
没有多余滚动条。 只渲染必要的滚动;修复溢出避免冗余滚动条。可在 macOS 开启“始终显示滚动条”来模拟 Windows 体验。
让浏览器做布局。 优先用 flex/grid/内在尺寸,避免 JS 测量;减少抖动,让 CSS 处理流动、换行与对齐。
内联帮助优先。 优先用内联说明;工具提示作为最后手段。
稳定的骨架屏。 骨架应尽量镜像最终内容,避免布局位移。
准确的页面标题。 <title>
要反映当前上下文。
没有死胡同。 每个界面都提供下一步或返回路径。
设计所有状态。 空、稀疏、密集与错误态都要覆盖。
排版引号。 优先用弯引号(“ ”),而非直引号(" ").
避免孤行寡行。 控制断行与对齐,让段落边缘自然整洁。
比较用等宽数字。 使用 font-variant-numeric: tabular-nums
或等宽字体(如 Geist Mono)。
冗余信号。 不要只靠颜色表达状态,需同时给出文本标签。
图标要有标签。 为视障用户提供等价文字。
没有“仅展示”模式。 视觉上可省略标签,但必须保留可访问的名称/标签供辅助技术使用。
使用省略号字符。 用 …
而不是三个点 ...
。
锚定标题。 章节链接时为标题设置合适的 scroll-margin-top
。
适应用户生成内容。 布局能兼容很短、一般、很长的内容。
区域感知格式。 按用户区域格式化日期、时间、数字、分隔符与货币。
语言优先于位置。 通过 Accept-Language 与 navigator.languages
检测语言;不要用 IP/GPS 判断语言。
可访问的内容。 准确命名(aria-label
)、隐藏装饰元素(aria-hidden
),并在可访问性树中核验。
仅图标按钮需要命名。 提供清晰的 aria-label
。
语义优先于 ARIA。 优先用原生元素(button
、a
、label
、table
)而非堆砌 aria-*
。
标题与跳过链接。 合理分层的 <h1–h6>
与“跳转到内容”的跳过链接。
从徽标直达品牌资产。 支持在导航徽标上右键快速访问品牌资源。
用不换行空格粘连术语。 用
把单位、快捷键、名称连在一起:10 MB → 10 MB,⌘ + K → ⌘ + K,Vercel SDK → Vercel SDK。无空格粘连可用 ⁠
。
回车即可提交。 文本输入聚焦时,回车提交表单。
文本区域的回车规则。 在 <textarea>
中:⌘/⌃ + 回车提交,回车换行。
处处有标签。 每个控件都有 <label>
,或能与标签关联以供辅助技术使用。
标签可激活。 点击 <label>
应聚焦到关联控件。
提交约束。 提交前按钮保持可用;发起请求后禁用按钮、显示加载指示,并包含幂等键。
不要阻止输入。 即便字段只接受数字,也允许自由输入并给出校验反馈;屏蔽按键会让用户摸不着头脑。
不要预先禁用提交。 允许提交不完整表单,以便显示校验反馈。
控件无“死区”。 复选框/单选与其标签应共享一个宽松的点击目标。
错误就近显示。 把错误显示在字段旁;提交时把焦点移到第一个错误上。
自动完成与 name。 设置正确的 autocomplete
与有意义的 name
,启用自动填充。
有选择地关闭拼写检查。 对邮箱、代码、用户名等禁用拼写检查。
正确的类型与输入模式。 选择合适的 type
与 inputmode
,获得更好的键盘与校验体验。
占位符表达“空”。 用省略号结尾。
占位符示例值。 占位符应是示例或模式,如 +1 (123) 456-7890、sk-012345679…。
未保存更改。 可能丢失数据时,在导航前警告。
密码管理器与 2FA。 确保兼容,并允许粘贴一次性验证码。
避免误触发密码管理器。 非认证字段(如“搜索”)避免使用保留名称(如 password),用 autocomplete="off"
或 OTP 专用的 autocomplete="one-time-code"
。
文本替换/扩展处理。 某些输入法会加尾随空格;提交前应修剪,避免莫名其妙的错误。
Windows 的 <select>
背景。 原生 <select>
要明确设置 background-color
与 color
,避免 Windows 深色模式下对比不够。
设备/浏览器矩阵。 记得测试 iOS 低电量模式与 macOS Safari。
可靠的测量。 禁用会加开销或改变运行时行为的浏览器扩展。
跟踪重渲染。 尽量减少并加速重渲染;用 React DevTools 或 React Scan。
分析时节流。 进行 CPU 与网络节流测试。
减少布局工作。 读/写合批,避免不必要的回流/重绘。
网络时延预算。 POST/PATCH/DELETE
争取 500ms 内完成。
按键开销。 优先使用非受控输入;让受控输入的更新闭环足够低开销。
大列表。 虚拟化(如 virtua)或用 content-visibility: auto
。
审慎预加载。 只预加载首屏图;其余延迟加载。
图像不引发 CLS。 明确指定图像尺寸并预留空间。
预连接外部源。 对资产/CDN 域使用 <link rel="preconnect">
(需要时加 crossorigin
),减少 DNS/TLS 往返。
预加载字体。 关键文本预加载字体,避免闪烁与位移。
字体子集化。 通过 unicode-range
仅投递所需码点/脚本(可变轴也仅保留必要),缩小体积。
避免主线程重活。 超长任务移到 Web Worker,避免阻塞交互。
分层阴影。 至少两层:环境光 + 直射光。
边框清晰。 边框与阴影结合;半透明边框能增强边缘清晰度。
圆角套圆角。 子元素圆角 ≤ 父元素,且保持同心,曲线对齐。
色调一致。 在非中性背景上,让边框/阴影/文字向同一色调轻微偏移。
可达的图表。 使用色盲友好的配色。
最低对比。 比起 WCAG 2,更推荐 APCA 的感知对比评估。
交互增强对比。 :hover
、:active
、:focus
的对比应高于静止态。
浏览器 UI 与背景一致。 用 <meta name="theme-color" content="#000000">
让浏览器主题色贴合页面背景。
设置合适的配色方案。 深色主题下在 <html>
标注 color-scheme: dark
,让滚动条等系统 UI 对比合适。
文本抗锯齿与变换。 文本缩放会影响平滑;优先给外层容器做动画而非文本节点。如有残影可用 translateZ(0)
或 will-change: transform
升层。
避免渐变色带。 某些颜色/显示器会出现色带;可用纹理或噪声遮罩改善。
这些偏好反映了 Vercel 的品牌与产品取向,并非通用指南。
不要说“CLI 将被安装”,而说“安装 CLI”。
标题与按钮用标题大小写(芝加哥风格)。 营销页使用句子式大小写。
清晰、简洁。 用最少的词表达清楚。
尽量用 & 而不是 and。
面向行动的语言。
不要说“你需要 CLI…”,而说“安装 CLI…”。
名词一致。 尽量减少独特术语的引入。
使用第二人称。 避免第一人称。
占位符一致。
字符串用:YOURAPITOKEN_HERE;数字用:0123456789。
不要写“八个部署”,而写“8 个部署”。
货币格式一致。 在同一上下文中要么都 0 位小数,要么都 2 位,不要混用。
数字与单位间留空格。
不要写 10MB,应写 10 MB(推荐不换行空格:10 MB)。
不要说“你的部署失败了”,而说“出了点问题——请重试或联系支持”。
不要说“无效的 API 密钥”,而说“你的 API 密钥不正确或已过期。请在账户设置中生成新密钥。”文案与按钮/链接要帮助用户采取明确行动。
不要用“继续”,而用“保存 API 密钥”。
AGENTS.md 文件为代理提供指导。将此 AGENTS.md 与你的代理一起使用,以确保你的界面遵循这些指南。我们建议审核所有生成的界面。