
🚩 2026 年「术哥无界」系列实战文档 X 篇原创计划 第 19 篇,Skills 最佳实战「2026」系列第 9 篇 大家好,欢迎来到 术哥无界 | ShugeX | 运维有术。 我是术哥,一名专注于 AI 编程、AI 智能体、Agent Skills、MCP、云原生、Milvus 向量数据库的技术实践者与开源布道者! Talk is cheap, let's explore。无界探索,有术而行。
前几期我们已经分享过:
上周末,我帮朋友审查一个电商项目的前端代码。打开一看,心里凉了半截 - 几十个按钮组件,竟然没有一个加 aria-label,表单输入框也没有 autocomplete 属性,图片全都是没有尺寸的 lazy loading。
这哥们跟我说:AI 生成的代码,能用就行了,还管这么多?
说实话,我当时就回了他一句:你能用,但你的用户可能用不了。
问题来了:AI 写的代码,怎么保证符合 Web 设计规范?人工审查太慢,自动检查又太死板。
今天要聊的这个工具,正好解决了这个痛点: web-design-guidelines,Vercel 官方出品的 Web 界面设计指南审查技能,目前在 skills.sh 排名第三,超越了昨天排名第三的remotion-best-practices, ,装机量高达 76.4K。

web-design-guidelines 在 skills.sh 上的排名和装机数据
web-design-guidelines(官方名称:Web Interface Guidelines)是 Vercel Labs 出品的一个 AI 编码技能,核心功能就是自动审查你的 UI 代码是否符合 Vercel 的 Web 界面设计规范。
它的 GitHub 仓库:https://github.com/vercel-labs/web-interface-guidelines,目前有 547 个 star,39 个 fork,MIT 许可证。
说实话,Vercel 这个团队我挺佩服的。他们不仅把 Next.js 做成了前端开发的标准,现在连 AI 编码工具的生态都玩得这么溜。
让我给你看一组数据:
指标 | 数值 |
|---|---|
总装机量 | 76.4K |
周装机量 | 63.5K |
skills.sh 排名 | 第 3 名 |
支持工具数 | 7 个 |
这个技能能火到 skills.sh 探花的位置,我觉得有三个原因:
第一,AI 代码质量问题的爆发。
现在大家都在用 Claude、Cursor 这些工具写代码,效率是上去了,但质量参差不齐。特别是 UI 组件这块,AI 生成的代码往往在可访问性、性能优化、用户体验这些细节上做得不够到位。
第二,Vercel 的品牌背书。
Vercel 自家产品(Next.js、Vercel 平台)的设计规范是经过实战检验的。他们把这套规范打包成一个 AI 技能,相当于把十几年的经验直接给你。
第三,无缝集成的体验。
这个技能支持 7 种主流 AI 编码工具:Claude Code、Cursor、OpenCode、Windsurf、Antigravity、Gemini CLI、Amp Code。你只需要装一次,就能在不同的工具里用同一个命令。
说实话,当我第一次看到这套规则体系的时候,我都惊了 - 竟然涵盖了 18 个类别,从可访问性到动画性能,从表单设计到深色模式,基本覆盖了 Web 界面设计的方方面面。
让我挑几个重点给你说说:
这是最核心的一块,也是被忽视得最厉害的。
规则要点:
aria-label<label> 或 aria-labelalt 属性aria-hidden="true"aria-live="polite"// ❌ 不规范的写法
<button onClick={handleClick}>
<Icon name="close" />
</button>
// ✅ 规范的写法
<button onClick={handleClick} aria-label="关闭">
<Icon name="close" aria-hidden="true" />
</button>
动画做得好是加分项,做得不好就是负分。
规则要点:
prefers-reduced-motion(尊重用户的减少动画偏好)transform 和 opacity(这两个属性性能最好)transition: all - 必须明确列出要动画的属性/* ❌ 反模式 */
transition: all 0.3sease;
/* ✅ 正确写法 */
transition: transform 0.3sease, opacity 0.3sease;
/* ✅ 减少动画偏好 */
@media (prefers-reduced-motion: reduce) {
* {
animation-duration: 0.01ms!important;
animation-iteration-count: 1!important;
transition-duration: 0.01ms!important;
}
}
这块规则全是实战经验,每一条都能帮你避免性能坑。
规则要点:
getBoundingClientRect 等)<link rel="preconnect">// ❌ 性能杀手
function LargeList({ items }) {
return (
<div>
{items.map(item => (
<div key={item.id} style={{ height: item.offsetHeight }}>
{/* 这里会触发强制同步布局 */}
</div>
))}
</div>
);
}
// ✅ 虚拟化方案
import { useVirtualizer } from '@tanstack/react-virtual';
function LargeList({ items }) {
const parentRef = useRef();
const virtualizer = useVirtualizer({
count: items.length,
getScrollElement: () => parentRef.current,
estimateSize: () => 50,
});
return (
<div ref={parentRef} style={{ height: '400px', overflow: 'auto' }}>
<div style={{ height: `${virtualizer.getTotalSize()}px` }}>
{virtualizer.getVirtualItems().map(item => (
<div key={item.key} style={{ position: 'absolute', top: 0, left: 0, width: '100%', transform: `translateY(${item.start}px)` }}>
{items[item.index].content}
</div>
))}
</div>
</div>
);
}

虚拟化前后的性能对比(数据来自实际项目测试)
表单是用户交互的核心,也是最容易出问题的地方。
规则要点:
autocomplete 和有意义的 nametype(email、tel、url、number)和 inputmodehtmlFor 或包裹控件)spellCheck={false})// ❌ 表单设计的反面教材
<form onSubmit={handleSubmit}>
<input type="text" placeholder="Email" onPaste={(e) => e.preventDefault()} />
<button type="submit">Continue</button>
</form>
// ✅ 符合规范的表单
<form onSubmit={handleSubmit}>
<div>
<label htmlFor="email">邮箱地址</label>
<input
id="email"
type="email"
name="email"
autoComplete="email"
spellCheck={false}
placeholder="your@email.com"
required
/>
</div>
<button type="submit">登录账户</button>
</form>
除了上面这四个核心类别,还有:

18个规则类别全景图
说实话,这套指南的全面程度,我个人认为是目前市面上最全的之一。Vercel 团队把他们在开发 Vercel 平台、Next.js 文档这些大型项目时积累的经验,都沉淀到了这套规则里。
这套指南有两种获取方式:
方式一:作为命令使用
curl -fsSL https://vercel.com/design/guidelines/install | bash
这行命令会:
方式二:作为项目配置使用
# 下载 AGENTS.md 到项目根目录
curl -o AGENTS.md https://raw.githubusercontent.com/vercel-labs/web-interface-guidelines/main/AGENTS.md
# 或者使用符号链接
ln -s ~/.claude/commands/web-interface-guidelines.md ./AGENTS.md
这样 AI 在生成代码时就会自动应用这套规范。
当你执行 /web-interface-guidelines <file-or-pattern> 命令时,技能会:
关键点是,这个检查不是简单的关键词匹配,而是理解代码上下文。比如它会知道:
<button onClick={...}> 是个交互元素,需要有焦点环<input type="email"> 应该有 autocomplete="email"<img> 标签必须有 width 和 height 来防止 CLS
工作流程图
技能的输出格式是这样的:
## src/components/Button.tsx
src/components/Button.tsx:15 - icon button missing aria-label
src/components/Button.tsx:23 - input lacks label
src/components/Button.tsx:45 - animation missing prefers-reduced-motion
src/components/Button.tsx:67 - transition: all → list properties
## src/components/Card.tsx
✓ pass
这个格式设计得很用心:
file:line 格式在 VS Code 里可以直接点击跳转我第一次用的时候就被这个输出格式惊艳到了 - 每一行都是干货,没有多余的废话,直接告诉你问题在哪,怎么改。
场景一:AI 代码审查
你用 Claude Code 或 Cursor 生成了一个 UI 组件,跑一遍这个技能,马上就知道有没有违反规范。
/web-interface-guidelines src/components/NewFeature.tsx
场景二:项目级代码检查
新项目开始前,把所有 UI 组件跑一遍,建立质量基线。
/web-interface-guidelines src/components/
场景三:持续集成 (CI/CD)
在 PR 流程中集成,自动检查 UI 代码质量。
# .github/workflows/ui-review.yml
name:UIGuidelinesReview
on:[pull_request]
jobs:
review:
runs-on:ubuntu-latest
steps:
-uses:actions/checkout@v3
-name:ReviewUICode
run:claude/web-interface-guidelinessrc/components/
场景四:新手学习
刚接触 Web 开发的新人,用这个技能学习最佳实践,比看文档直观多了。
场景一:纯后端代码
这技能是针对 UI/前端代码的,你拿去检查 Node.js 控制器逻辑,那是浪费时间。
场景二:CSS-in-JS 框架深度定制
如果你用了像 styled-components、emotion 这种深度定制的 CSS-in-JS 框架,有些规则可能需要特殊处理。
场景三:极其特殊的设计风格
如果你的项目有完全不同于 Vercel 的设计规范(比如游戏界面),这套指南的某些规则可能不适用。
第一步:检查你的 AI 工具
确认你至少安装了以下工具之一:
第二步:运行安装命令
curl -fsSL https://vercel.com/design/guidelines/install | bash
第三步:验证安装成功
安装完成后,你会看到类似这样的输出:
✅ Installed for Claude Code: ~/.claude/commands/web-interface-guidelines.md
✅ Installed for Cursor: ~/.cursor/commands/web-interface-guidelines.md
✅ Installed for Windsurf: ~/.codeium/windsurf/memories/global_rules.md
第四步:测试一下
在你的 AI 工具里输入:
/web-interface-guidelines --help
或者检查一个文件:
/web-interface-guidelines some-file.tsx
如果能看到输出,恭喜你,安装成功!
问题1:提示找不到命令
解决方案:
问题2:安装多个工具后只显示一个
解决方案:
ls -la ~/.claude/commands/ 检查目录问题3:输出格式混乱
解决方案:
command.md 文件是否完整下载问题场景:朋友写的登录按钮,看起来没问题,但用技能一查,发现 5 个问题。
// src/components/LoginButton.tsx(原始代码)
import { Button } from './Button';
export function LoginButton({ onClick }) {
return (
<button
onClick={onClick}
className="transition-all duration-300"
>
<Icon name="login" />
登录
</button>
);
}
运行检查:
/web-interface-guidelines src/components/LoginButton.tsx
输出结果:
## src/components/LoginButton.tsx
src/components/LoginButton.tsx:8 - icon button missing aria-label
src/components/LoginButton.tsx:6 - transition: all → list properties
src/components/LoginButton.tsx:7 - icon lacks aria-hidden
src/components/LoginButton.tsx:6 - button missing hover state
src/components/LoginButton.tsx:5 - onClick handler on generic element
修复后的代码:
// src/components/LoginButton.tsx(修复后)
import { Button } from './Button';
export function LoginButton({ onClick }) {
return (
<button
type="button"
onClick={onClick}
aria-label="登录账户"
className="transition-transform duration-300 hover:scale-105 focus-visible:ring-2 focus-visible:ring-offset-2"
>
<Icon name="login" aria-hidden="true" />
登录
</button>
);
}
修复说明:
type="button" 防止表单意外提交aria-label 给屏幕阅读器使用aria-hidden="true" 标记为装饰性transition-all 改成 transition-transform问题场景:一个注册表单,用户体验很差。
// src/components/RegisterForm.tsx(原始代码)
export function RegisterForm() {
return (
<form>
<input type="text" placeholder="Full Name" />
<input type="text" placeholder="Email" />
<input type="password" placeholder="Password" />
<button>Continue</button>
</form>
);
}
运行检查:
/web-interface-guidelines src/components/RegisterForm.tsx
输出结果:
## src/components/RegisterForm.tsx
src/components/RegisterForm.tsx:3 - input lacks label
src/components/RegisterForm.tsx:4 - input lacks label, missing autocomplete
src/components/RegisterForm.tsx:5 - input lacks label, missing autocomplete
src/components/RegisterForm.tsx:6 - button label too generic
修复后的代码:
// src/components/RegisterForm.tsx(修复后)
export function RegisterForm() {
return (
<form onSubmit={handleSubmit}>
<div>
<label htmlFor="fullname">全名</label>
<input
id="fullname"
type="text"
name="fullname"
autoComplete="name"
placeholder="张三"
required
/>
</div>
<div>
<label htmlFor="email">邮箱地址</label>
<input
id="email"
type="email"
name="email"
autoComplete="email"
spellCheck={false}
placeholder="your@email.com"
required
/>
</div>
<div>
<label htmlFor="password">密码</label>
<input
id="password"
type="password"
name="password"
autoComplete="new-password"
placeholder="••••••••"
minLength={8}
required
/>
</div>
<button type="submit">创建账户</button>
</form>
);
}
修复说明:
<label> 和 htmlFortype 和 autocompletespellCheck={false}
图3:修复前的表单(左)vs 修复后的表单(右)
问题场景:一个用户列表,渲染 1000 条数据,页面卡得要死。
// src/components/UserList.tsx(原始代码)
export function UserList({ users }) {
return (
<div>
{users.map(user => (
<div key={user.id} className="user-card">
<img src={user.avatar} alt={user.name} />
<div>{user.name}</div>
<div>{user.email}</div>
</div>
))}
</div>
);
}
运行检查:
/web-interface-guidelines src/components/UserList.tsx
输出结果:
## src/components/UserList.tsx
src/components/UserList.tsx:4 - large list without virtualization
src/components/UserList.tsx:5 - img lacks width/height (CLS risk)
修复后的代码:
// src/components/UserList.tsx(修复后)
import { useVirtualizer } from '@tanstack/react-virtual';
export function UserList({ users }) {
const parentRef = useRef();
const virtualizer = useVirtualizer({
count: users.length,
getScrollElement: () => parentRef.current,
estimateSize: () => 80, // 每行高度 80px
overscan: 5, // 预渲染 5 行
});
return (
<div ref={parentRef} style={{ height: '600px', overflow: 'auto' }}>
<div style={{ height: `${virtualizer.getTotalSize()}px` }}>
{virtualizer.getVirtualItems().map(item => (
<UserCard
key={item.key}
user={users[item.index]}
style={{
position: 'absolute',
top: 0,
left: 0,
width: '100%',
transform: `translateY(${item.start}px)`,
}}
/>
))}
</div>
</div>
);
}
function UserCard({ user, style }) {
return (
<div style={style} className="user-card">
<img
src={user.avatar}
alt={user.name}
width={48}
height={48}
loading="lazy"
/>
<div>{user.name}</div>
<div>{user.email}</div>
</div>
);
}
修复说明:
@tanstack/react-virtual 实现虚拟滚动width 和 height 防止 CLSloading="lazy" 懒加载性能对比:
这个技能和 ESLint 不冲突,反而是互补关系。
// .eslintrc.json
{
"extends": [
"next/core-web-vitals",
"plugin:jsx-a11y/recommended"
],
"rules": {
"jsx-a11y/alt-text": "error",
"jsx-a11y/anchor-is-valid": "warn"
}
}
ESLint 负责语法层面的检查,这个技能负责设计规范层面的检查,两者配合使用,代码质量更有保障。
虽然这套指南已经很全面了,但你可以根据项目需求添加自定义规则。
# AGENTS.md(添加自定义规则)
## Custom Rules for Our Project
- MUST: All buttons must have loading state
- SHOULD: Use our custom color palette only
- NEVER: Use external icons without SVG
把 AGENTS.md 放到项目根目录,确保所有团队成员的 AI 工具都遵循同一套规范。
# 在项目根目录
echo "Copy AGENTS.md to all team members' AI tools" > README.md
集成到 GitHub Actions,每次 PR 都自动检查 UI 代码质量。
# .github/workflows/pr-check.yml
name:PRUIGuidelinesCheck
on:
pull_request:
paths:
-'src/components/**'
-'src/app/**'
jobs:
check-ui:
runs-on:ubuntu-latest
steps:
-uses:actions/checkout@v3
-name:SetupClaude
run:npminstall-g@anthropic-ai/claude-code
-name:CheckUIGuidelines
run:claude/web-interface-guidelinessrc/
这套指南是持续更新的,记得定期获取最新版本。
# 每月更新一次
curl -fsSL https://vercel.com/design/guidelines/install | bash
Q1:这个技能能完全替代人工代码审查吗?
A:不能。AI 能帮你检查规则性的东西,但设计决策、业务逻辑这些还是需要人来判断。把它当作第一道防线,人工审查作为第二道防线。
Q2:规则太多了,是不是要全部遵守?
A:看情况。如果项目对可访问性有要求,那 Accessibility 部分是必须的。如果只是内部工具,某些规则可以适当放宽。
Q3:和 a11y eslint 插件有什么区别?
A:a11y eslint 插件更侧重于语法层面的检查,这个技能更侧重于设计规范和用户体验层面的检查。两者配合使用效果最好。
Q4:非 Vercel 项目能用吗?
A:当然可以。这套指南虽然来自 Vercel,但大部分规则都是 Web 开发的通用最佳实践,适用于任何 Web 项目。
Q5:性能检查规则会不会太严格?
A:说实话,确实有点严格。但如果你关注性能和用户体验,这些规则是值得遵守的。可以根据项目实际情况调整。
说到底,web-design-guidelines 这个技能的核心价值在于:
我看好这个技能的未来,有几个原因:
AI 辅助开发会成为标配。随着 Claude、Cursor 这些工具的普及,AI 代码质量工具也会越来越重要。
用户体验要求越来越高。用户对可访问性、性能、体验的要求在提升,开发工具也需要跟上。
设计规范会标准化。越来越多的团队会意识到设计规范的重要性,像 web-design-guidelines 这样的工具会有更大市场。
社区生态会越来越丰富。目前已经支持 7 种 AI 工具,未来可能会有更多。
说实话,我觉得这个技能是 AI 编码工具生态的一个重要补充。AI 写代码快,但质量需要工具来保证。web-design-guidelines 正好解决了这个痛点。
如果你也在用 AI 编码工具,我强烈建议你试试这个技能。特别是如果你是前端开发者,或者你的团队重视 UI/UX 质量。
别犹豫了,先装上试试:
curl -fsSL https://vercel.com/design/guidelines/install | bash
好啦,谢谢你观看我的文章,如果喜欢可以点赞转发给需要的朋友,我们下一期再见!敬请期待。