重要前提
安装AI Skills的关键前提是:必须科学上网,且开启TUN模式,这一点至关重要,直接决定安装能否顺利完成,在此郑重提醒三遍:科学上网,科学上网,科学上网。查看完整安装教程 →
web-design-guidelines by asyrafhussin/agent-skills
npx skills add https://github.com/asyrafhussin/agent-skills --skill web-design-guidelines构建包容、高性能 Web 界面的综合 UI/UX 和无障碍指南。包含 8 个类别下的 21 条规则,按 WCAG 合规性和用户影响优先级排序。
在以下情况下参考这些指南:
| 优先级 | 类别 | 影响 | 前缀 |
|---|---|---|---|
| 1 | 无障碍 - 语义结构 | 关键 | a11y- |
| 2 | 无障碍 - 键盘与焦点 | 关键 | a11y- |
| 3 | 无障碍 - 视觉与色彩 | 关键 | a11y- |
广告位招租
在这里展示您的产品或服务
触达数万 AI 开发者,精准高效
| 4 | 表单 - 输入与验证 | 关键 | form- |
| 5 | 表单 - 错误处理 | 高 | form- |
| 6 | 表单 - 用户体验 | 中 | form- |
| 7 | 动画与动效 | 关键 | motion- |
| 8 | 性能与用户体验 | 中 | perf- |
a11y-semantic-html - 使用语义化 HTML 元素a11y-heading-hierarchy - 保持正确的标题层级a11y-screen-reader - 优化屏幕阅读器兼容性a11y-skip-links - 提供导航跳过链接a11y-keyboard-nav - 确保完整的键盘导航a11y-focus-management - 妥善管理键盘焦点a11y-aria-labels - 为交互元素添加 ARIA 标签a11y-color-contrast - 确保足够的色彩对比度a11y-alt-text - 为图像提供有意义的替代文本form-autocomplete - 为表单使用自动完成属性form-input-types - 使用正确的输入类型form-labels - 将标签与表单输入关联form-error-display - 清晰地显示表单错误form-error-messages - 提供无障碍的错误信息form-validation-ux - 设计用户友好的表单验证form-inline-validation - 实现智能的内联验证form-multi-step - 设计高效的多步骤表单form-placeholder-usage - 适当使用占位符form-submit-feedback - 提供清晰的表单提交反馈motion-reduced - 尊重 prefers-reduced-motion 偏好设置// ❌ 滥用 div - 没有语义含义
<div className="header">
<div className="nav">
<div onClick={handleClick}>Home</div>
</div>
</div>
<div className="content">
<div className="title">Page Title</div>
<div className="text">Content here...</div>
</div>
// ✅ 语义化 HTML - 无障碍且有含义
<header>
<nav aria-label="Main navigation">
<a href="/">Home</a>
</nav>
</header>
<main>
<article>
<h1>Page Title</h1>
<p>Content here...</p>
</article>
</main>
// 交互元素需要无障碍名称
<button aria-label="Close dialog">
<XIcon />
</button>
<button aria-label="Add to cart">
<PlusIcon />
</button>
// 仅图标的链接
<a href="/settings" aria-label="Settings">
<SettingsIcon />
</a>
// 装饰性图标应被隐藏
<span aria-hidden="true">🎉</span>
// 所有交互元素必须可通过键盘访问
function Dialog({ isOpen, onClose, children }) {
// 将焦点限制在对话框内
const dialogRef = useRef<HTMLDivElement>(null)
useEffect(() => {
if (isOpen) {
dialogRef.current?.focus()
}
}, [isOpen])
// 处理 Escape 键
const handleKeyDown = (e: React.KeyboardEvent) => {
if (e.key === 'Escape') {
onClose()
}
}
return (
<div
ref={dialogRef}
role="dialog"
aria-modal="true"
tabIndex={-1}
onKeyDown={handleKeyDown}
>
{children}
<button onClick={onClose}>Close</button>
</div>
)
}
// ✅ 始终可见的焦点样式
<button className="
focus:outline-none
focus-visible:ring-2
focus-visible:ring-blue-500
focus-visible:ring-offset-2
">
Button
</button>
// ❌ 切勿在没有替代方案的情况下移除焦点轮廓
<button className="outline-none focus:outline-none">
Inaccessible
</button>
// ✅ 正确标记的表单
<form>
<div>
<label htmlFor="email">
Email address
<span aria-hidden="true" className="text-red-500">*</span>
</label>
<input
id="email"
type="email"
name="email"
required
aria-required="true"
aria-describedby="email-hint email-error"
autoComplete="email"
/>
<p id="email-hint" className="text-gray-500 text-sm">
We'll never share your email.
</p>
{error && (
<p id="email-error" role="alert" className="text-red-500 text-sm">
{error}
</p>
)}
</div>
<button type="submit">Subscribe</button>
</form>
/* CSS */
@media (prefers-reduced-motion: reduce) {
*,
*::before,
*::after {
animation-duration: 0.01ms !important;
animation-iteration-count: 1 !important;
transition-duration: 0.01ms !important;
}
}
<!-- Tailwind -->
<div className="
transition-transform duration-300
hover:scale-105
motion-reduce:transition-none
motion-reduce:hover:transform-none
">
Card
</div>
// JavaScript
const prefersReducedMotion = window.matchMedia(
'(prefers-reduced-motion: reduce)'
).matches
function animate() {
if (prefersReducedMotion) {
// 跳过或简化动画
return
}
// 完整动画
}
// ✅ 正确的图像实现
<img
src="/hero.webp"
alt="Team collaborating around a whiteboard"
width={1200}
height={600}
loading="lazy"
decoding="async"
/>
// ✅ 装饰性图像
<img src="/pattern.svg" alt="" aria-hidden="true" />
// ✅ 响应式图像
<picture>
<source
srcSet="/hero-mobile.webp"
media="(max-width: 768px)"
type="image/webp"
/>
<source srcSet="/hero.webp" type="image/webp" />
<img src="/hero.jpg" alt="Hero description" width={1200} height={600} />
</picture>
// ✅ 最小 44x44px 触摸目标
<button className="min-h-[44px] min-w-[44px] p-2">
<Icon className="w-6 h-6" />
</button>
// ✅ 触摸目标之间有足够的间距
<nav className="flex gap-2">
<a href="/" className="p-3">Home</a>
<a href="/about" className="p-3">About</a>
</nav>
/* WCAG AA 要求普通文本对比度 4.5:1,大文本 3:1 */
/* ❌ 对比度不足 */
.low-contrast {
color: #999999; /* 灰底白字:约 2.8:1 */
background: white;
}
/* ✅ 对比度足够 */
.good-contrast {
color: #595959; /* 深灰:约 7:1 */
background: white;
}
/* ✅ 不要仅依赖颜色 */
.error {
color: #dc2626;
border-left: 4px solid #dc2626; /* 视觉指示器 */
}
// 向屏幕阅读器播报动态内容
<div
role="status"
aria-live="polite"
aria-atomic="true"
className="sr-only"
>
{message}
</div>
// 通知提示
function Toast({ message }: { message: string }) {
return (
<div
role="alert"
aria-live="assertive"
className="fixed bottom-4 right-4 bg-gray-900 text-white p-4 rounded"
>
{message}
</div>
)
}
审核代码时,按此格式输出发现的问题:
file:line - [category] Description of issue
示例:
src/components/Button.tsx:15 - [a11y] Missing aria-label on icon-only button
src/pages/Home.tsx:42 - [perf] Image missing width/height attributes
src/components/Form.tsx:28 - [form] Input missing associated label
阅读单个规则文件以获取详细解释和代码示例:
rules/a11y-semantic-html.md
rules/form-autocomplete.md
rules/motion-reduced.md
rules/_sections.md
每个规则文件包含:
获取包含所有规则详细说明的完整指南:AGENTS.md
每周安装次数
45
仓库
GitHub 星标数
11
首次出现
2026年1月24日
安全审计
安装于
opencode35
gemini-cli34
codex34
claude-code32
cursor31
antigravity31
Comprehensive UI/UX and accessibility guidelines for building inclusive, performant web interfaces. Contains 21 rules across 8 categories, prioritized by WCAG compliance and user impact.
Reference these guidelines when:
| Priority | Category | Impact | Prefix |
|---|---|---|---|
| 1 | Accessibility - Semantic Structure | CRITICAL | a11y- |
| 2 | Accessibility - Keyboard & Focus | CRITICAL | a11y- |
| 3 | Accessibility - Visual & Color | CRITICAL | a11y- |
| 4 | Forms - Input & Validation | CRITICAL | form- |
| 5 | Forms - Error Handling | HIGH | form- |
| 6 | Forms - User Experience | MEDIUM | form- |
| 7 | Animation & Motion | CRITICAL | motion- |
| 8 | Performance & UX | MEDIUM | perf- |
a11y-semantic-html - Use semantic HTML elementsa11y-heading-hierarchy - Maintain proper heading hierarchya11y-screen-reader - Optimize for screen reader compatibilitya11y-skip-links - Provide skip links for navigationa11y-keyboard-nav - Ensure full keyboard navigationa11y-focus-management - Manage keyboard focus properlya11y-aria-labels - Add ARIA labels to interactive elementsa11y-color-contrast - Ensure sufficient color contrasta11y-alt-text - Provide meaningful alt text for imagesform-autocomplete - Use autocomplete attributes for formsform-input-types - Use correct input typesform-labels - Associate labels with form inputsform-error-display - Display form errors clearlyform-error-messages - Provide accessible error messagesform-validation-ux - Design user-friendly form validationform-inline-validation - Implement smart inline validationform-multi-step - Design effective multi-step formsform-placeholder-usage - Use placeholders appropriatelyform-submit-feedback - Provide clear form submission feedbackmotion-reduced - Respect prefers-reduced-motion preference// ❌ Div soup - no semantic meaning
<div className="header">
<div className="nav">
<div onClick={handleClick}>Home</div>
</div>
</div>
<div className="content">
<div className="title">Page Title</div>
<div className="text">Content here...</div>
</div>
// ✅ Semantic HTML - accessible and meaningful
<header>
<nav aria-label="Main navigation">
<a href="/">Home</a>
</nav>
</header>
<main>
<article>
<h1>Page Title</h1>
<p>Content here...</p>
</article>
</main>
// Interactive elements need accessible names
<button aria-label="Close dialog">
<XIcon />
</button>
<button aria-label="Add to cart">
<PlusIcon />
</button>
// Icon-only links
<a href="/settings" aria-label="Settings">
<SettingsIcon />
</a>
// Decorative icons should be hidden
<span aria-hidden="true">🎉</span>
// All interactive elements must be keyboard accessible
function Dialog({ isOpen, onClose, children }) {
// Trap focus inside dialog
const dialogRef = useRef<HTMLDivElement>(null)
useEffect(() => {
if (isOpen) {
dialogRef.current?.focus()
}
}, [isOpen])
// Handle Escape key
const handleKeyDown = (e: React.KeyboardEvent) => {
if (e.key === 'Escape') {
onClose()
}
}
return (
<div
ref={dialogRef}
role="dialog"
aria-modal="true"
tabIndex={-1}
onKeyDown={handleKeyDown}
>
{children}
<button onClick={onClose}>Close</button>
</div>
)
}
// ✅ Always visible focus styles
<button className="
focus:outline-none
focus-visible:ring-2
focus-visible:ring-blue-500
focus-visible:ring-offset-2
">
Button
</button>
// ❌ Never remove focus outlines without replacement
<button className="outline-none focus:outline-none">
Inaccessible
</button>
// ✅ Properly labeled form
<form>
<div>
<label htmlFor="email">
Email address
<span aria-hidden="true" className="text-red-500">*</span>
</label>
<input
id="email"
type="email"
name="email"
required
aria-required="true"
aria-describedby="email-hint email-error"
autoComplete="email"
/>
<p id="email-hint" className="text-gray-500 text-sm">
We'll never share your email.
</p>
{error && (
<p id="email-error" role="alert" className="text-red-500 text-sm">
{error}
</p>
)}
</div>
<button type="submit">Subscribe</button>
</form>
// CSS
@media (prefers-reduced-motion: reduce) {
*,
*::before,
*::after {
animation-duration: 0.01ms !important;
animation-iteration-count: 1 !important;
transition-duration: 0.01ms !important;
}
}
// Tailwind
<div className="
transition-transform duration-300
hover:scale-105
motion-reduce:transition-none
motion-reduce:hover:transform-none
">
Card
</div>
// JavaScript
const prefersReducedMotion = window.matchMedia(
'(prefers-reduced-motion: reduce)'
).matches
function animate() {
if (prefersReducedMotion) {
// Skip or simplify animation
return
}
// Full animation
}
// ✅ Proper image implementation
<img
src="/hero.webp"
alt="Team collaborating around a whiteboard"
width={1200}
height={600}
loading="lazy"
decoding="async"
/>
// ✅ Decorative images
<img src="/pattern.svg" alt="" aria-hidden="true" />
// ✅ Responsive images
<picture>
<source
srcSet="/hero-mobile.webp"
media="(max-width: 768px)"
type="image/webp"
/>
<source srcSet="/hero.webp" type="image/webp" />
<img src="/hero.jpg" alt="Hero description" width={1200} height={600} />
</picture>
// ✅ Minimum 44x44px touch targets
<button className="min-h-[44px] min-w-[44px] p-2">
<Icon className="w-6 h-6" />
</button>
// ✅ Adequate spacing between touch targets
<nav className="flex gap-2">
<a href="/" className="p-3">Home</a>
<a href="/about" className="p-3">About</a>
</nav>
/* WCAG AA requires 4.5:1 for normal text, 3:1 for large text */
/* ❌ Insufficient contrast */
.low-contrast {
color: #999999; /* Gray on white: ~2.8:1 */
background: white;
}
/* ✅ Sufficient contrast */
.good-contrast {
color: #595959; /* Darker gray: ~7:1 */
background: white;
}
/* ✅ Don't rely on color alone */
.error {
color: #dc2626;
border-left: 4px solid #dc2626; /* Visual indicator */
}
// Announce dynamic content to screen readers
<div
role="status"
aria-live="polite"
aria-atomic="true"
className="sr-only"
>
{message}
</div>
// Toast notifications
function Toast({ message }: { message: string }) {
return (
<div
role="alert"
aria-live="assertive"
className="fixed bottom-4 right-4 bg-gray-900 text-white p-4 rounded"
>
{message}
</div>
)
}
When auditing code, output findings in this format:
file:line - [category] Description of issue
Example:
src/components/Button.tsx:15 - [a11y] Missing aria-label on icon-only button
src/pages/Home.tsx:42 - [perf] Image missing width/height attributes
src/components/Form.tsx:28 - [form] Input missing associated label
Read individual rule files for detailed explanations and code examples:
rules/a11y-semantic-html.md
rules/form-autocomplete.md
rules/motion-reduced.md
rules/_sections.md
Each rule file contains:
For the complete guide with all rules expanded: AGENTS.md
Weekly Installs
45
Repository
GitHub Stars
11
First Seen
Jan 24, 2026
Security Audits
Gen Agent Trust HubPassSocketPassSnykPass
Installed on
opencode35
gemini-cli34
codex34
claude-code32
cursor31
antigravity31
前端设计系统技能:生产级UI设计、设计令牌与可访问性指南
8,500 周安装
NotebookLM 研究助手技能:基于 Google NotebookLM 的文档智能查询与自动化管理工具
1 周安装
NoSQL专家指南:Cassandra与DynamoDB分布式数据库设计模式与性能优化
1 周安装
Next.js Supabase 认证集成指南:App Router 中间件与服务器操作最佳实践
1 周安装
SaaS营销创意库:140个已验证策略,含SEO、内容营销、付费广告与竞争对手分析
1 周安装
LLM应用模式:生产级RAG架构、AI智能体与LLMOps最佳实践指南
1 周安装
SaaS产品发布策略指南:ORB框架与五阶段方法,打造成功功能发布与用户增长
1 周安装