web-design-guidelines
Design standards for ensuring accessible and responsive web interfaces.
Install
mkdir -p .claude/skills/web-design-guidelines-sabahattink && curl -L -o skill.zip "https://agentskills.codes/api/skills/download/11256" && unzip -o skill.zip -d .claude/skills/web-design-guidelines-sabahattink && rm skill.zipInstalls to .claude/skills/web-design-guidelines-sabahattink
Activation
This is the description your AI agent reads to decide when to run this skill — the better it matches your request, the more reliably it fires.
Web design best practices, accessibility, responsive layout, color contrast. Use when auditing a UI for a11y compliance, designing responsive layouts, or establishing design standards across a web app.Key capabilities
- →Audits UI for accessibility compliance
- →Sets responsive layout standards
- →Verifies color contrast ratios
- →Implements semantic HTML
- →Ensures keyboard navigation
How it works
The tool provides actionable guidelines and code patterns for WCAG 2.1 AA compliance, responsive design, and color contrast.
Inputs & outputs
When to use web-design-guidelines
- →Audit UI for accessibility compliance
- →Set up responsive layout standards
- →Verify color contrast ratios
About this skill
Web Design Guidelines
Accessibility (WCAG 2.1 AA)
Color Contrast Requirements
- Normal text (< 18pt): minimum 4.5:1 contrast ratio
- Large text (≥ 18pt or 14pt bold): minimum 3:1
- UI components and graphical objects: minimum 3:1
// Use a utility to check contrast at runtime in dev
// Install: npm i color2k
import { parseToRgb, getLuminance } from 'color2k'
function getContrastRatio(fg: string, bg: string): number {
const l1 = getLuminance(fg)
const l2 = getLuminance(bg)
const lighter = Math.max(l1, l2)
const darker = Math.min(l1, l2)
return (lighter + 0.05) / (darker + 0.05)
}
// In Storybook stories or tests:
// expect(getContrastRatio('#2563eb', '#ffffff')).toBeGreaterThan(4.5)
Semantic HTML
// Good: semantic structure
export function PageLayout() {
return (
<>
<header role="banner">
<nav aria-label="Main navigation">
<ul role="list">
<li><a href="/">Home</a></li>
<li><a href="/about">About</a></li>
</ul>
</nav>
</header>
<main id="main-content" tabIndex={-1}>
<h1>Page Title</h1>
{/* Skip-to-main link target */}
</main>
<aside aria-label="Related content">
{/* Sidebar */}
</aside>
<footer role="contentinfo">
{/* Footer */}
</footer>
</>
)
}
// Skip link — must be the very first focusable element
function SkipToMain() {
return (
<a
href="#main-content"
className="sr-only focus:not-sr-only focus:absolute focus:top-4 focus:left-4 focus:z-50 focus:px-4 focus:py-2 focus:bg-white focus:text-blue-600 focus:rounded-lg focus:shadow-lg focus:outline-none focus:ring-2 focus:ring-blue-500"
>
Skip to main content
</a>
)
}
Keyboard Navigation
// All interactive elements must be keyboard-operable
function DropdownMenu({ items }: { items: MenuItem[] }) {
const [open, setOpen] = React.useState(false)
const [activeIndex, setActiveIndex] = React.useState(-1)
const handleKeyDown = (e: React.KeyboardEvent) => {
switch (e.key) {
case 'ArrowDown':
e.preventDefault()
setActiveIndex(i => Math.min(i + 1, items.length - 1))
break
case 'ArrowUp':
e.preventDefault()
setActiveIndex(i => Math.max(i - 1, 0))
break
case 'Escape':
setOpen(false)
break
case 'Enter':
case ' ':
if (activeIndex >= 0) items[activeIndex].action()
break
}
}
return (
<div role="navigation" aria-label="Actions menu">
<button
aria-haspopup="true"
aria-expanded={open}
onClick={() => setOpen(o => !o)}
>
Actions
</button>
{open && (
<ul
role="menu"
onKeyDown={handleKeyDown}
className="..."
>
{items.map((item, i) => (
<li key={item.id} role="menuitem" tabIndex={i === activeIndex ? 0 : -1}>
<button onClick={item.action}>{item.label}</button>
</li>
))}
</ul>
)}
</div>
)
}
ARIA Labels
// Always label icon-only buttons
<button aria-label="Close dialog" onClick={onClose}>
<XIcon aria-hidden="true" className="h-5 w-5" />
</button>
// Images
<img src={product.image} alt={`${product.name} — front view`} />
// Decorative images get empty alt
<img src="/divider.svg" alt="" role="presentation" />
// Live regions for dynamic content
<div aria-live="polite" aria-atomic="true" className="sr-only">
{statusMessage}
</div>
Responsive Layout
Mobile-First Approach
/* Write base styles for mobile, then progressively enhance */
.card {
padding: 1rem; /* mobile */
}
@media (min-width: 640px) { /* sm */
.card { padding: 1.5rem; }
}
@media (min-width: 1024px) { /* lg */
.card { padding: 2rem; }
}
// Tailwind mobile-first
<div className="px-4 sm:px-6 lg:px-8">
<div className="grid grid-cols-1 gap-4 sm:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4">
{items.map(item => <Item key={item.id} {...item} />)}
</div>
</div>
Fluid Typography
/* clamp(min, preferred, max) — scales smoothly between viewport sizes */
:root {
--text-base: clamp(1rem, 0.9rem + 0.5vw, 1.125rem);
--text-lg: clamp(1.125rem, 1rem + 0.75vw, 1.375rem);
--text-xl: clamp(1.25rem, 1rem + 1.5vw, 1.75rem);
--text-2xl: clamp(1.5rem, 1rem + 2.5vw, 2.25rem);
--text-4xl: clamp(2rem, 1rem + 5vw, 4rem);
}
Container Queries
/* Style based on parent width, not viewport width */
.card-grid {
container-type: inline-size;
container-name: card-grid;
}
@container card-grid (min-width: 480px) {
.product-card {
display: grid;
grid-template-columns: 140px 1fr;
}
}
Image Optimization
// Next.js Image — always use this over <img>
import Image from 'next/image'
// Known dimensions (static assets)
<Image
src="/hero.jpg"
alt="Dashboard overview showing key metrics"
width={1200}
height={630}
priority // LCP image: load eagerly
className="rounded-xl object-cover"
/>
// Unknown dimensions (user uploads)
<div className="relative aspect-video w-full overflow-hidden rounded-xl">
<Image
src={user.avatar}
alt={`${user.name}'s profile photo`}
fill
sizes="(max-width: 640px) 100vw, (max-width: 1024px) 50vw, 33vw"
className="object-cover"
/>
</div>
Touch Targets
Minimum touch target size: 44×44 px (Apple HIG) / 48×48 dp (Material).
// Expand click area without changing visual size
<button
className="
relative p-2 -m-2
/* visual size stays 24px, but hit area is 44px (24 + 2*8 = 40... close enough) */
before:absolute before:inset-0 before:-m-2
"
>
<MenuIcon className="h-6 w-6" />
</button>
// Or just give buttons adequate padding
<button className="min-h-[44px] min-w-[44px] px-4 py-2.5">
Submit
</button>
Focus Management
// Trap focus inside modals
import { useEffect, useRef } from 'react'
function useFocusTrap(active: boolean) {
const containerRef = useRef<HTMLDivElement>(null)
useEffect(() => {
if (!active || !containerRef.current) return
const focusable = containerRef.current.querySelectorAll<HTMLElement>(
'a[href], button:not([disabled]), input:not([disabled]), select, textarea, [tabindex]:not([tabindex="-1"])'
)
const first = focusable[0]
const last = focusable[focusable.length - 1]
first?.focus()
const handleKeyDown = (e: KeyboardEvent) => {
if (e.key !== 'Tab') return
if (e.shiftKey) {
if (document.activeElement === first) {
e.preventDefault()
last?.focus()
}
} else {
if (document.activeElement === last) {
e.preventDefault()
first?.focus()
}
}
}
document.addEventListener('keydown', handleKeyDown)
return () => document.removeEventListener('keydown', handleKeyDown)
}, [active])
return containerRef
}
Performance
Core Web Vitals Targets
| Metric | Good | Needs Improvement |
|---|---|---|
| LCP (Largest Contentful Paint) | < 2.5s | 2.5–4.0s |
| INP (Interaction to Next Paint) | < 200ms | 200–500ms |
| CLS (Cumulative Layout Shift) | < 0.1 | 0.1–0.25 |
// Prevent CLS: always reserve space for images/embeds
<div className="aspect-video w-full bg-gray-100 rounded-xl overflow-hidden">
<Image src={src} alt={alt} fill className="object-cover" />
</div>
// Prevent CLS: skeleton loaders match exact dimensions
function SkeletonCard() {
return (
<div className="rounded-xl border border-gray-100 p-6 animate-pulse">
<div className="h-6 bg-gray-200 rounded w-3/4 mb-3" />
<div className="h-4 bg-gray-200 rounded w-full mb-2" />
<div className="h-4 bg-gray-200 rounded w-5/6" />
</div>
)
}
Dark Mode
// tailwind.config.ts
const config = {
darkMode: 'class', // Toggle via class on <html>
theme: {
extend: {
colors: {
background: 'hsl(var(--background))',
foreground: 'hsl(var(--foreground))',
},
},
},
}
// globals.css
// :root {
// --background: 0 0% 100%;
// --foreground: 222 47% 11%;
// }
// .dark {
// --background: 222 47% 4%;
// --foreground: 210 40% 98%;
// }
// Toggle hook
function useDarkMode() {
const [dark, setDark] = React.useState(() =>
window.matchMedia('(prefers-color-scheme: dark)').matches
)
useEffect(() => {
document.documentElement.classList.toggle('dark', dark)
localStorage.setItem('theme', dark ? 'dark' : 'light')
}, [dark])
return { dark, toggle: () => setDark(d => !d) }
}
Forbidden Patterns
- Never remove
outlineon focus without providing an equivalent visual indicator - Never use color alone to convey information (add icons, text, or patterns)
- Never set
font-sizebelow 14px (16px minimum for body text) - Never use
placeholderas a label substitute — placeholders disappear on input - Never disable zoom (
user-scalable=no) — breaks accessibility for low-vision users - Never use
tabindexvalues > 0 — they break the natural tab order - Never let hover-only tooltips carry essential information (mobile has no hover)
- Never auto-play audio or video with sound without user consent
When not to use it
- →Automated accessibility fixing without review
- →Ignoring dark mode requirements
Limitations
- →Requires manual audit for full compliance
- →Does not cover all WCAG criteria
How it compares
It focuses on actionable code patterns and audit guidelines rather than just high-level design principles.
Compared to similar skills
web-design-guidelines side by side with the closest alternatives in the catalog.
| Skill | Installs | Updated | Safety | Difficulty |
|---|---|---|---|---|
| web-design-guidelines (this skill) | 0 | 3mo | No flags | Intermediate |
| tailwind-design-system | 34 | 2mo | No flags | Intermediate |
| web-design-reviewer | 7 | 7mo | No flags | Intermediate |
| epic-ui-guidelines | 3 | 6mo | No flags | Beginner |
Try saying
Example prompts that trigger this skill in your AI assistant.
You might also like
tailwind-design-system
wshobson
Build scalable design systems with Tailwind CSS, design tokens, component libraries, and responsive patterns. Use when creating component libraries, implementing design systems, or standardizing UI patterns.
web-design-reviewer
github
This skill enables visual inspection of websites running locally or remotely to identify and fix design issues. Triggers on requests like "review website design", "check the UI", "fix the layout", "find design problems". Detects issues with responsive design, accessibility, visual consistency, and layout breakage, then performs fixes at the source code level.
epic-ui-guidelines
epicweb-dev
Guide on UI/UX guidelines, accessibility, and component usage for Epic Stack
baseline-ui
agentset-ai
Enforces an opinionated UI baseline to prevent AI-generated interface slop.
ui-web
alinaqi
Web UI - glassmorphism, Tailwind, dark mode, accessibility
bencium-innovative-ux-designer
bencium
Create distinctive, production-grade frontend interfaces with high design quality. Use this skill when the user asks to build web components, pages, or applications. Generates creative, polished code that avoids generic AI aesthetics.