
Web Interface Design
- 104 installs
- 49 repo stars
- Updated February 11, 2026
- ratacat/claude-skills
Helps with design & ui/ux tasks.
About
web-interface-design is a Claude Code skill for design & ui/ux. It helps solo builders move faster with AI-assisted coding.
- web-interface-design
- Design & UI/UX
- AI-coding skill
Web Interface Design by the numbers
- 104 all-time installs (skills.sh)
- Ranked #1,109 of 1,880 Design & UI/UX skills by installs in the Skillselion catalog
- Data as of Jul 28, 2026 (Skillselion catalog sync)
npx skills add https://github.com/ratacat/claude-skills --skill web-interface-designAdd your badge
Show developers this skill is listed on Skillselion. Paste this into your README.
| Installs | 104 |
|---|---|
| repo stars | ★ 49 |
| Last updated | February 11, 2026 |
| Repository | ratacat/claude-skills ↗ |
What it does
Helps with design & ui/ux tasks.
Files
Web Interface Design
Overview
Design exists to separate the primary from the secondary. Users should instantly recognize what matters. Good interface design is invisible—users accomplish goals without noticing the interface.
This skill orchestrates domain-specific reference files. Read only what you need for the task.
Reference File Index
| Task | Load Reference |
|---|---|
| Font sizes, line spacing, heading hierarchy, vertical rhythm | references/typography.md |
| Input fields, validation, checkboxes, radios, selects, textareas | references/forms-and-inputs.md |
| Button hierarchy, sizing, states, CTAs, ghost buttons | references/buttons.md |
| Color palettes, dark mode, tints/shades, state colors | references/color-systems.md |
| Navigation, cards, tabs, accordions, modals, tables, toasts | references/ui-components.md |
| Grids, spacing scales, responsive patterns, whitespace | references/layout-and-spacing.md |
| Focus techniques, hierarchy principles, action pyramid | references/visual-hierarchy.md |
| Contrast ratios, focus states, screen readers, WCAG | references/accessibility.md |
| CSS implementation patterns, variables, common styles | references/css-patterns.md |
Quick Decision: Which Reference?
What's the problem?
├─ Text hard to read, spacing feels off → typography.md
├─ Form not working well, validation issues → forms-and-inputs.md
├─ Users don't know what to click → buttons.md OR visual-hierarchy.md
├─ Colors look wrong, dark mode broken → color-systems.md
├─ Need nav/cards/tabs/modals/tables → ui-components.md
├─ Spacing inconsistent, layout cramped → layout-and-spacing.md
├─ Everything competes for attention → visual-hierarchy.md
├─ Accessibility audit or contrast issues → accessibility.md
└─ Need CSS implementation → css-patterns.mdUniversal Quick Reference
Spacing Scale (4px base)
4, 8, 12, 16, 20, 24, 32, 40, 48, 64, 80, 96
Typography Baseline
- Body: 16px, line-height 1.5
- Heading:body ratio max 1:3 (48px heading for 16px body)
- Paragraph spacing: line-height ÷ 1.5
Touch Targets
- Minimum: 44×44px
- Recommended: 48×48px
Contrast Minimums (WCAG)
- Normal text: 4.5:1
- Large text (18px+ or 14px+ bold): 3:1
- UI components: 3:1
Button Hierarchy
| Level | Use For | Treatment |
|---|---|---|
| Primary | Main action (ONE per view) | Solid fill, high contrast |
| Secondary | Alternative actions | Outlined or subtle fill |
| Tertiary | Minor actions | Text-only or ghost |
Dark Mode Essentials
- Background: #121212 (not pure black)
- Text: #E0E0E0 (not pure white)
- Reduce color saturation
Common Mistakes Checklist
- [ ] Multiple primary buttons per view
- [ ] Placeholder used as only label
- [ ] Pure white on pure black
- [ ] Thin/light font weights
- [ ] Color-only error indicators
- [ ] Long centered text
- [ ] Inconsistent spacing values
Design Review Protocol
1. Hierarchy: Is primary action obvious? Can you tell what matters? 2. Readability: Text contrast OK? Line length reasonable (45-75 chars)? 3. Forms: Labels above fields? Touch targets 44px+? Helpful errors? 4. Spacing: Consistent scale? Breathing room around elements? 5. Accessibility: Color not sole indicator? Focus states visible?
When NOT to Use This Skill
- Pure visual branding/identity work
- Marketing copy decisions
- Backend architecture
- Mobile native patterns (iOS/Android differ)
Sources
- Web Interface Handbook by Aleksei Baranov (Imperavi)
- User Interface Typography by Imperavi
- Refactoring UI by Wathan & Schoger
- WCAG 2.1 accessibility guidelines
Accessibility Reference
Core Principle
Build accessibility from project start. Retrofitting is harder and produces worse results.
---
Contrast Requirements (WCAG)
| Element | Minimum Ratio |
|---|---|
| Normal text | 4.5:1 |
| Large text (18px+ or 14px+ bold) | 3:1 |
| UI components | 3:1 |
| Non-essential decorative | No requirement |
Testing: Don't rely on vision alone. Use accessibility checkers.
---
Font Weight Rules
Critical: Never use thin or light fonts in interfaces. Almost always unreadable.
On dark backgrounds: Reduce bold weight to Regular or Semibold for balance.
---
Color Guidelines
Problem Colors
- Gray text: Almost always unreadable
- Yellow text: Very difficult to read
- Pure white on black: Too contrasting for extended reading
Solutions
- White on black: Use light gray (#E0E0E0) instead
- Gray text: Ensure meets 4.5:1 ratio
- Use color checkers to verify
---
Beyond Color
Never rely on color alone to convey meaning:
- Add icons to error states
- Include text labels with colored indicators
- Ensure patterns work in grayscale
Examples
❌ Color only
<input class="error">✓ Color + icon + text
<input class="error" aria-describedby="email-error">
<span id="email-error">
⚠️ Enter a valid email address
</span>---
Focus States
Every interactive element needs visible focus:
.interactive:focus-visible {
outline: 2px solid var(--primary);
outline-offset: 2px;
}Never: Remove focus outlines without providing alternative.
---
Hidden vs Visible Hints
Bad: Hints hidden behind icons (tooltip on hover).
- Doesn't work for screen readers
- Doesn't work for vision issues
- Requires hover (no touch support)
Good: Visible hints displayed directly.
- "Well read by any user and screen readers"
---
Form Accessibility
Labels
- Every input needs a visible label
- Connect with
for/idattributes - Never use placeholder as only label
<label for="email">Email Address</label>
<input type="email" id="email">Error Messages
- Use
aria-live="assertive"for dynamic validation - Connect with
aria-describedby - Don't rely on color alone
<input id="password" aria-describedby="password-error">
<div id="password-error" role="alert" aria-live="assertive">
Password must be at least 8 characters
</div>Fieldsets
- Group related inputs (radio buttons, checkboxes)
- Use
fieldsetandlegend
<fieldset>
<legend>Notification preferences</legend>
<label><input type="checkbox"> Email</label>
<label><input type="checkbox"> SMS</label>
</fieldset>---
Keyboard Navigation
Requirements
- All interactive elements keyboard accessible
- Logical tab order
- Focus trap in modals
- Escape key closes modals/dropdowns
Tab Patterns
| Component | Keyboard Behavior |
|---|---|
| Tabs | Tab to list, arrows between tabs, Enter activates |
| Accordions | Tab to headers, Enter/Space toggles |
| Modals | Focus trapped, Escape closes |
| Dropdowns | Arrows navigate, Enter selects, Escape closes |
---
Touch Accessibility
Touch targets:
- Minimum: 44×44px
- Recommended: 48×48px
Spacing between targets: 8px minimum to prevent mis-taps.
---
Testing Requirements
1. Contrast ratio checker (WebAIM, Stark) 2. Color blind vision simulators 3. Screen reader testing (VoiceOver, NVDA) 4. Keyboard-only navigation test 5. Zoom to 200% test
Don't rely on: "Looks fine to me"
---
Quick Checklist
Text
- [ ] All text meets contrast requirements
- [ ] No thin/light fonts
- [ ] No pure white on pure black for long text
Color
- [ ] Color not sole indicator for errors/states
- [ ] Works in grayscale
Forms
- [ ] Labels above fields (visible)
- [ ] Error messages specific and helpful
- [ ] Touch targets ≥ 44px
Focus
- [ ] Focus states visible
- [ ] Logical tab order
- [ ] Focus trapped in modals
Screen Readers
- [ ] Form labels connected
- [ ] Images have alt text
- [ ] Dynamic content announced (
aria-live)
Buttons Reference
Making Buttons Look Clickable
Users must instantly recognize something is a button.
Universal cues:
- Drop shadows (even in flat design)
- Rounded corners
- Distinct shape from surrounding content
- Depth/elevation appearance
---
Button Hierarchy
Three weight levels:
| Level | Use For | Visual Treatment |
|---|---|---|
| Primary | Main action, CTA | Filled, high contrast, prominent |
| Secondary | Alternative actions | Outlined or lower contrast fill |
| Tertiary | Minor actions | Text-only or very subtle |
Rule: One primary button per view. Multiple primary buttons confuse priority.
---
CTA Button Design
Contrast is essential. CTA must stand out from everything.
Effective techniques:
- Complementary color to background
- Larger size than secondary buttons
- Strategic placement in scan path
- White space around button
Research finding: Red buttons can outperform green—test what works.
---
Button Sizing
Touch targets:
- Minimum: 44×44px
- Preferred: 48×48px
Research: Larger buttons boost engagement by ~20%, but don't make them unprofessionally large.
Padding ratios: Horizontal typically 1.5–2× vertical.
.button {
padding: 12px 24px; /* 1:2 ratio */
min-height: 44px;
}---
Ghost Buttons
Definition: Transparent background, border only.
Finding: Ghost buttons grab less attention than solid CTAs.
Use for:
- Secondary actions alongside solid primary
- When you need button but not visual weight
- Image overlays where solid would obscure content
Avoid for:
- Primary conversions
- Critical actions
- Anywhere visibility crucial
---
Button States
| State | Purpose | Treatment |
|---|---|---|
| Default | Ready for interaction | Standard appearance |
| Hover | User considering action | Slight color shift, cursor pointer |
| Active/Pressed | Being clicked | Darker shade, slight depression |
| Focused | Keyboard navigation | Clear focus ring |
| Disabled | Not available | 50% opacity, cursor change |
| Loading | Processing | Spinner, disabled interaction |
---
Common Button CSS
:root {
--btn-height: 44px;
--btn-padding-x: 24px;
--btn-padding-y: 12px;
--btn-radius: 6px;
--btn-font-weight: 600;
}
.btn {
display: inline-flex;
align-items: center;
justify-content: center;
min-height: var(--btn-height);
padding: var(--btn-padding-y) var(--btn-padding-x);
border-radius: var(--btn-radius);
font-weight: var(--btn-font-weight);
font-size: 1rem;
text-decoration: none;
cursor: pointer;
transition: all 0.15s ease;
}
.btn-primary {
background: var(--primary);
color: white;
border: none;
}
.btn-primary:hover {
background: var(--primary-dark);
}
.btn-secondary {
background: transparent;
color: var(--primary);
border: 2px solid var(--primary);
}
.btn-secondary:hover {
background: var(--primary-light);
}
.btn-tertiary {
background: transparent;
color: var(--primary);
border: none;
padding: var(--btn-padding-y) 0;
}
.btn:focus-visible {
outline: 2px solid var(--primary);
outline-offset: 2px;
}
.btn:disabled {
opacity: 0.5;
cursor: not-allowed;
}---
Good vs Bad Examples
❌ Multiple primary buttons
<div class="actions">
<button class="btn-primary">Save Draft</button>
<button class="btn-primary">Preview</button>
<button class="btn-primary">Publish</button>
</div>✓ Clear hierarchy
<div class="actions">
<button class="btn-tertiary">Save Draft</button>
<button class="btn-secondary">Preview</button>
<button class="btn-primary">Publish</button>
</div>---
Destructive Actions
Destructive buttons (Delete, Remove) should:
- Use warning/red color
- NOT be primary unless destruction is the page's purpose
- Require confirmation for irreversible actions
Color Systems Reference
Base Colors to Select
Essential Palette
- Primary/Brand: Main accent for buttons, links, labels
- Black and White: Foundation for text and backgrounds
- Night and Smoke: Dark theme alternatives (night = dark bg, smoke = light text)
- State colors: Informative (blue), Negative (red), Positive (green), Notice (yellow/orange)
Extended Palette
- Secondary/tertiary accents
- Product-specific category colors
- Gradient colors
- Chart colors (distinct warm and cool scales)
- Illustration colors
---
Dark Mode Design
Background: Don't use pure black. Use "night" (#121212) for softer appearance.
Text: Pure white is too bright—creates glowing halo. Use "smoke" (#E0E0E0) for body text.
Key insight: High contrast white-on-black is harder to read than reduced contrast.
Dark Mode Adjustments
- Reduce color saturation
- Increase shadow opacity
- Use surface color elevation instead of shadows alone
---
Mirrored Tints and Shades
Create matching light and dark theme colors:
Light theme: a1, a2, a3, a4, a5, a6, a7, a8, a9
Dark theme: b1, b2, b3, b4, b5, b6, b7, b8, b9Usage: If a4 for background in light theme, use b4 for same background in dark theme.
This enables automatic theme switching.
---
Creating Tints and Shades
The Color Builder Method
Tints: Base color with transparency over white background Shades: Base color with transparency over dark background
Base blue: #2563EB
Tint: rgba(37, 99, 235, 0.1) on white → light blue
Shade: rgba(37, 99, 235, 0.3) on dark → deep blueFine-tuning
- Increase saturation for muted tints (especially greens)
- Shift hue toward red for yellow/orange shades (avoid muddiness)
---
Transparency Layer
Create transparent scales for white, black, night, smoke:
black-a5: 5% opacity
black-a10: 10% opacity
black-a20: 20% opacity
...
black-a90: 90% opacityPlus specialized: 2%, 7% for subtle effects.
---
Quantity Guidelines
- Recommended: 17 values per color (comprehensive)
- Minimum: 3 values (base + one tint + one shade)
More values = flexibility for complex interfaces.
---
Testing Colors
Validate all tints/shades on actual UI:
- Check contrast ratios
- Verify visual balance across backgrounds
- Test in both light and dark themes
- Use accessibility checkers
---
CSS Implementation
:root {
/* Light theme */
--primary: #2563eb;
--primary-light: #eff6ff;
--primary-dark: #1d4ed8;
/* State colors */
--success: #16a34a;
--success-bg: #f0fdf4;
--error: #dc2626;
--error-bg: #fef2f2;
--warning: #d97706;
--warning-bg: #fffbeb;
--info: #0284c7;
--info-bg: #f0f9ff;
/* Neutrals */
--text-primary: #111827;
--text-secondary: #6b7280;
--text-tertiary: #9ca3af;
--border: #e5e7eb;
--bg-page: #ffffff;
--bg-surface: #f9fafb;
--bg-hover: #f3f4f6;
}
/* Dark theme */
[data-theme="dark"] {
--bg-page: #121212; /* Night */
--bg-surface: #1e1e1e;
--bg-hover: #2a2a2a;
--border: #333333;
--text-primary: #e0e0e0; /* Smoke */
--text-secondary: #a0a0a0;
--text-tertiary: #707070;
--primary: #60a5fa;
--primary-light: rgba(96, 165, 250, 0.15);
--primary-dark: #3b82f6;
}---
Good vs Bad Examples
❌ Pure white on pure black
.dark-theme {
background: #000000;
color: #FFFFFF;
}✓ Muted dark theme
.dark-theme {
background: #121212;
color: #E0E0E0;
}CSS Implementation Patterns
Typography System
:root {
/* Font sizes */
--text-xs: 0.75rem; /* 12px */
--text-sm: 0.875rem; /* 14px */
--text-base: 1rem; /* 16px */
--text-lg: 1.125rem; /* 18px */
--text-xl: 1.25rem; /* 20px */
--text-2xl: 1.5rem; /* 24px */
--text-3xl: 2rem; /* 32px */
--text-4xl: 2.5rem; /* 40px */
/* Line heights */
--leading-tight: 1.1;
--leading-snug: 1.25;
--leading-normal: 1.5;
--leading-relaxed: 1.7;
/* Letter spacing */
--tracking-tight: -0.02em;
--tracking-normal: 0;
--tracking-wide: 0.02em;
}
h1 {
font-size: var(--text-4xl);
line-height: var(--leading-tight);
letter-spacing: var(--tracking-tight);
font-weight: 700;
}
h2 {
font-size: var(--text-3xl);
line-height: var(--leading-tight);
font-weight: 600;
}
h3 {
font-size: var(--text-2xl);
line-height: var(--leading-snug);
font-weight: 600;
}
body {
font-size: var(--text-base);
line-height: var(--leading-normal);
color: #333;
}---
Spacing System
:root {
/* 4px base unit */
--space-1: 0.25rem; /* 4px */
--space-2: 0.5rem; /* 8px */
--space-3: 0.75rem; /* 12px */
--space-4: 1rem; /* 16px */
--space-5: 1.25rem; /* 20px */
--space-6: 1.5rem; /* 24px */
--space-8: 2rem; /* 32px */
--space-10: 2.5rem; /* 40px */
--space-12: 3rem; /* 48px */
--space-16: 4rem; /* 64px */
}
/* Paragraph spacing */
p + p { margin-top: var(--space-4); }
/* Heading spacing */
h2 {
margin-top: var(--space-8);
margin-bottom: var(--space-3);
}
h3 {
margin-top: var(--space-6);
margin-bottom: var(--space-2);
}---
Color System
:root {
/* Primary */
--primary: #2563eb;
--primary-light: #eff6ff;
--primary-dark: #1d4ed8;
/* State colors */
--success: #16a34a;
--success-bg: #f0fdf4;
--error: #dc2626;
--error-bg: #fef2f2;
--warning: #d97706;
--warning-bg: #fffbeb;
--info: #0284c7;
--info-bg: #f0f9ff;
/* Neutrals */
--text-primary: #111827;
--text-secondary: #6b7280;
--text-tertiary: #9ca3af;
--border: #e5e7eb;
--bg-page: #ffffff;
--bg-surface: #f9fafb;
--bg-hover: #f3f4f6;
}
[data-theme="dark"] {
--bg-page: #121212;
--bg-surface: #1e1e1e;
--bg-hover: #2a2a2a;
--border: #333333;
--text-primary: #e0e0e0;
--text-secondary: #a0a0a0;
--text-tertiary: #707070;
--primary: #60a5fa;
--primary-light: rgba(96, 165, 250, 0.15);
}---
Button System
:root {
--btn-height: 44px;
--btn-padding-x: 24px;
--btn-padding-y: 12px;
--btn-radius: 6px;
}
.btn {
display: inline-flex;
align-items: center;
justify-content: center;
min-height: var(--btn-height);
padding: var(--btn-padding-y) var(--btn-padding-x);
border-radius: var(--btn-radius);
font-weight: 600;
font-size: 1rem;
cursor: pointer;
transition: all 0.15s ease;
}
.btn-primary {
background: var(--primary);
color: white;
border: none;
}
.btn-primary:hover { background: var(--primary-dark); }
.btn-secondary {
background: transparent;
color: var(--primary);
border: 2px solid var(--primary);
}
.btn-secondary:hover { background: var(--primary-light); }
.btn-tertiary {
background: transparent;
color: var(--primary);
border: none;
}
.btn:focus-visible {
outline: 2px solid var(--primary);
outline-offset: 2px;
}
.btn:disabled {
opacity: 0.5;
cursor: not-allowed;
}---
Form Input System
:root {
--input-height: 44px;
--input-padding-x: 16px;
--input-radius: 6px;
--input-border: 1px solid #d1d5db;
}
.form-group { margin-bottom: var(--space-5); }
.form-label {
display: block;
margin-bottom: var(--space-2);
font-weight: 500;
font-size: var(--text-sm);
}
.form-input {
width: 100%;
height: var(--input-height);
padding: 0 var(--input-padding-x);
border: var(--input-border);
border-radius: var(--input-radius);
font-size: var(--text-base);
transition: border-color 0.15s;
}
.form-input:focus {
outline: none;
border-color: var(--primary);
box-shadow: 0 0 0 3px rgba(37, 99, 235, 0.1);
}
.form-input.error { border-color: var(--error); }
.form-error {
display: flex;
align-items: center;
gap: var(--space-2);
margin-top: var(--space-2);
color: var(--error);
font-size: var(--text-sm);
}---
Elevation System
:root {
--shadow-sm: 0 1px 2px rgba(0,0,0,0.05);
--shadow-md: 0 4px 6px rgba(0,0,0,0.1);
--shadow-lg: 0 10px 15px rgba(0,0,0,0.1);
--shadow-xl: 0 20px 25px rgba(0,0,0,0.15);
/* Two-shadow technique */
--shadow-card:
0 1px 3px rgba(0,0,0,0.12),
0 1px 2px rgba(0,0,0,0.06);
--shadow-dropdown:
0 4px 6px rgba(0,0,0,0.1),
0 2px 4px rgba(0,0,0,0.06);
--shadow-modal:
0 20px 50px rgba(0,0,0,0.2),
0 10px 20px rgba(0,0,0,0.1);
}---
Animation Patterns
:root {
--ease-out: cubic-bezier(0.25, 0, 0.25, 1);
--ease-in: cubic-bezier(0.5, 0, 0.75, 0.5);
--ease-in-out: cubic-bezier(0.45, 0, 0.55, 1);
}
/* Button press */
.btn:active {
transform: scale(0.98);
transition: transform 0.1s var(--ease-out);
}
/* Modal entrance */
@keyframes modalIn {
from {
opacity: 0;
transform: scale(0.95) translateY(-10px);
}
to {
opacity: 1;
transform: scale(1) translateY(0);
}
}
.modal { animation: modalIn 0.2s var(--ease-out); }
/* Skeleton loading */
@keyframes shimmer {
from { background-position: 200% 0; }
to { background-position: -200% 0; }
}
.skeleton {
background: linear-gradient(90deg, #f0f0f0 25%, #e0e0e0 50%, #f0f0f0 75%);
background-size: 200% 100%;
animation: shimmer 1.5s infinite;
}
/* Reduced motion */
@media (prefers-reduced-motion: reduce) {
*, *::before, *::after {
animation-duration: 0.01ms !important;
transition-duration: 0.01ms !important;
}
}---
Responsive Breakpoints
:root {
--bp-sm: 640px;
--bp-md: 768px;
--bp-lg: 1024px;
--bp-xl: 1280px;
--bp-2xl: 1536px;
}
/* Fluid typography */
:root {
--text-base: clamp(1rem, 0.9rem + 0.5vw, 1.125rem);
--text-lg: clamp(1.125rem, 1rem + 0.75vw, 1.5rem);
--text-xl: clamp(1.5rem, 1.25rem + 1.25vw, 2.5rem);
}---
Utility Classes
/* Text colors */
.text-primary { color: var(--text-primary); }
.text-secondary { color: var(--text-secondary); }
.text-error { color: var(--error); }
.text-success { color: var(--success); }
/* Backgrounds */
.bg-surface { background: var(--bg-surface); }
.bg-page { background: var(--bg-page); }
/* Flexbox */
.flex { display: flex; }
.flex-col { flex-direction: column; }
.items-center { align-items: center; }
.justify-between { justify-content: space-between; }
.gap-2 { gap: var(--space-2); }
.gap-4 { gap: var(--space-4); }
/* Spacing */
.p-4 { padding: var(--space-4); }
.mt-4 { margin-top: var(--space-4); }
.mb-4 { margin-bottom: var(--space-4); }---
Card Component
.card {
background: var(--bg-page);
border-radius: 8px;
box-shadow: var(--shadow-card);
overflow: hidden;
}
.card-body { padding: var(--space-4); }
.card-title {
font-size: var(--text-lg);
font-weight: 600;
margin-bottom: var(--space-2);
}
.card:hover {
box-shadow: var(--shadow-md);
transform: translateY(-2px);
transition: all 0.2s var(--ease-out);
}---
Modal Component
.modal-overlay {
position: fixed;
inset: 0;
background: rgba(0, 0, 0, 0.5);
display: flex;
align-items: center;
justify-content: center;
z-index: 1000;
}
.modal {
background: var(--bg-page);
border-radius: 8px;
max-width: 560px;
width: 90%;
max-height: 90vh;
overflow-y: auto;
box-shadow: var(--shadow-modal);
}
.modal-header {
display: flex;
justify-content: space-between;
align-items: center;
padding: var(--space-4);
border-bottom: 1px solid var(--border);
}
.modal-body { padding: var(--space-4); }
.modal-footer {
display: flex;
justify-content: flex-end;
gap: var(--space-3);
padding: var(--space-4);
border-top: 1px solid var(--border);
}Forms and Inputs Reference
Form Design Philosophy
Core insight: "The easier the input, the faster the goal. Fewer refusals, higher conversion."
Every field creates friction. Every unclear label causes hesitation. Every validation error damages trust.
---
Required vs Optional Fields
Recommendation: If a form has both required and optional fields, remove optional fields entirely.
Benefits:
- Removes asterisks and "required" indicators
- Simplifies visual design
- Reduces user decision-making
If optional fields are necessary:
- Mark with "(optional)" text
- Never rely solely on asterisks
- Place indicator after label, not inside field
---
Input Field Design
States
Every input needs these states:
| State | Visual Treatment |
|---|---|
| Default | Standard border, ready for input |
| Focused | Clear indicator (border color, glow) |
| Filled | May show checkmark for valid content |
| Error | Red border, error message visible |
| Disabled | Grayed out, cursor change |
| Read-only | Distinct from disabled, content copyable |
Labels
Placement: Above the field, not inside.
✓ Email Address
[ ]
❌ [ Email Address ] ← disappears on focusLabels vs Placeholders:
- Labels: Identify what field is for
- Placeholders: Hint on format/example (optional)
Never use placeholder as only label.
Sizing
Touch targets: Minimum 44×44px.
Field height: Consistent across form (40px, 44px, or 48px).
Field width: Indicate expected content length:
- ZIP code: short
- Street address: long
- Phone: medium
---
Validation and Errors
Timing
Inline validation: Show errors as user leaves field, not while typing.
Form-level validation: On submit, scroll to first error and focus that field.
Error Message Design
Visual treatment:
- Red border on problem field
- Error message directly below field
- Icon optional but helpful
- Semitransparent red background
Message content:
- Specific: "Password must be at least 8 characters" not "Invalid password"
- Constructive: Tell how to fix
- Polite: Never blame user
❌ Wrong format
❌ Error: Invalid input
✓ Enter a valid email (example: name@company.com)
✓ Password needs at least one numberAccessibility
- Use
aria-live="assertive"for dynamic validation - Connect error messages with
aria-describedby - Don't rely on color alone—include text and/or icon
---
Form Control Types
Checkboxes
When to use: Multiple options can be selected. Binary yes/no.
Label position: Right of checkbox.
Touch target: Entire label clickable.
<label class="checkbox-label">
<input type="checkbox" name="subscribe">
<span>Subscribe to newsletter</span>
</label>Indeterminate state: For "select all" when some children selected.
Grouping: Use fieldset and legend for related checkboxes.
<fieldset>
<legend>Notification preferences</legend>
<label><input type="checkbox"> Email</label>
<label><input type="checkbox"> SMS</label>
</fieldset>Radio Buttons
When to use: Mutually exclusive options. User must choose exactly one.
Minimum options: Always 2+ (otherwise use checkbox).
Pre-selection: Consider pre-selecting most common, but never pre-select options with cost/commitment.
Layout:
- Vertical: Labels long, 3+ options, scanning important
- Horizontal: Only 2-3 options with short labels
.radio-group {
display: flex;
flex-direction: column;
gap: 12px;
}Select Dropdowns
When to use:
- Many options (7+)
- Saving vertical space critical
- Options well-known
When NOT to use:
- Fewer than 5 options (use radios)
- User needs to see all options
- Options need explanation
Native vs custom: Native has better accessibility and mobile support.
Searchable select: Required when 15+ items.
Placeholder: Use "Select an option" not empty text.
<select>
<option value="" disabled selected>Select a country</option>
<option value="us">United States</option>
</select>Text Areas
Default size: Match expected content length.
Resize behavior:
- Allow vertical resize
- Disable horizontal resize (breaks layout)
- Consider auto-resize
textarea {
resize: vertical;
min-height: 120px;
}Character count: Show when limits exist. Update real-time.
Message
[ ]
247/500Toggle Switches
When to use:
- Immediate effect (no submit needed)
- Binary on/off states
- Settings that apply instantly
When NOT to use:
- Forms requiring submission
- Effect isn't immediate
Visual states:
- Off: Gray/neutral
- On: Colored (primary/success)
- Disabled: Reduced opacity
Label position: Left of toggle.
.toggle {
width: 48px;
height: 28px;
border-radius: 14px;
background: var(--toggle-off);
transition: background 0.2s;
}
.toggle.on { background: var(--primary); }
.toggle-handle {
width: 24px;
height: 24px;
border-radius: 50%;
background: white;
transition: transform 0.2s;
}
.toggle.on .toggle-handle {
transform: translateX(20px);
}Date Pickers
Input format: Show expected format as placeholder/helper.
Calendar popup:
- Open on focus or icon click
- Allow manual text input
- Show current date
- Easy month/year navigation
Date range:
- Clear start/end fields
- Visual indication of range
- Prevent invalid ranges
Accessibility:
- Keyboard navigation (arrows for days)
- Screen reader announcements
- Clear focus indicators
Search Fields
Anatomy:
┌────────────────────────────────────┐
│ 🔍 Search products... [X]│
└────────────────────────────────────┘
↑ ↑
Icon Clear buttonPlaceholder: Describe what can be searched: "Search products..." not just "Search..."
Clear button: Show only when field has value.
Submit behavior: Instant search OR explicit submit—never require both.
Empty state: Helpful message with alternatives.
No results for "xyz"
Try searching for:
• Product category
• Brand nameLayout and Spacing Reference
Grid Fundamentals
Modules: Building blocks where rows and columns intersect.
Spatial zones: Clusters of modules grouping content with shared purpose.
Gutters: Spaces between columns/rows—give design breathing room.
Margins: Outer spacing around the grid.
---
The Baseline Grid Misconception
Myth: Baseline grids automatically create harmony.
Reality: They only unify height dimensions. Harmony comes from:
- Contrast and variety
- Repetitive spacing patterns
- Harmonious relationships between values
When to Use Baseline Grids
Use for:
- Fixed-height environments (apps)
- Print design
- Precise vertical alignment needs
Don't force for:
- Responsive websites
- Flexible content areas
- Variable content lengths
---
Spacing Scales
4px Base Unit (Recommended)
4, 8, 12, 16, 20, 24, 32, 40, 48, 64, 80, 96Best for most web projects.
8px Base Unit
8, 16, 24, 32, 40, 48, 64, 80, 96For larger, more spacious designs.
CSS Implementation
:root {
--space-1: 0.25rem; /* 4px */
--space-2: 0.5rem; /* 8px */
--space-3: 0.75rem; /* 12px */
--space-4: 1rem; /* 16px */
--space-5: 1.25rem; /* 20px */
--space-6: 1.5rem; /* 24px */
--space-8: 2rem; /* 32px */
--space-10: 2.5rem; /* 40px */
--space-12: 3rem; /* 48px */
--space-16: 4rem; /* 64px */
}---
Two-Scale Strategy
Complex projects mixing content and UI often need two independent scales:
- Content scale (line-spacing based): For articles, documentation
- Module scale (unit-based): For cards, navigation, forms
This prevents conflict between typography rhythm and component spacing.
---
Spacing in Different Contexts
Long-form Content
Vertical rhythm and typography spacing rules apply strictly.
UI Modules (cards, navigation)
Contrast, grouping, composition matter more than strict rhythm.
---
Responsive Considerations
Pattern Adaptations
Tabs → Accordions: At narrow widths, horizontal tabs should become vertical accordions.
Navigation:
- Desktop: Horizontal with all items
- Tablet: Horizontal with overflow menu
- Mobile: Hamburger or bottom nav
Tables:
- Desktop: Full table
- Tablet: Priority columns, horizontal scroll
- Mobile: Card transformation
Cards:
- Desktop: 3-4 column grid
- Tablet: 2-column
- Mobile: Single column stack
Forms:
- Desktop: Multi-column for related fields
- Tablet: Two-column for short fields
- Mobile: Single column always
Breakpoints
--bp-sm: 640px; /* Large phones */
--bp-md: 768px; /* Tablets */
--bp-lg: 1024px; /* Laptops */
--bp-xl: 1280px; /* Desktops */
--bp-2xl: 1536px; /* Large desktops */Touch Considerations
Touch targets: 44×44px min, 48×48px recommended.
Spacing between targets: 8px minimum.
Hover states: Don't rely on hover—touch has none.
Gestures: Supplement with visible controls.
---
Whitespace Principles
Start with too much: Easier to remove than add.
Cramped = cheap: Whitespace communicates quality.
Group related elements: Use spacing to show relationships.
---
Good vs Bad Examples
❌ Inconsistent spacing
.card { padding: 15px; }
.section { margin-bottom: 30px; }
.header { padding: 18px 25px; }✓ Consistent scale
.card { padding: 16px; }
.section { margin-bottom: 32px; }
.header { padding: 16px 24px; }Typography Reference
The Three Typography Decisions
Every project requires three fundamental choices:
1. Body Font Selection The main text font used everywhere—button labels, body copy, long reads. This determines the project's overall typographic style.
2. Heading Font Choice Either match body typeface or select a contrasting font for visual distinction.
3. Accent Font For captions, quotations, code snippets:
- Monospaced: good for short captions
- Serif: suits quotes and callouts
- Can match body if not needed
---
Heading Design
Sizing
Optimal ratio: Heading to body text max 1:3.
Body: 16px → Heading max: 48px (16 × 3)Ratios exceeding 1:3 upset harmony and distract from content.
Spacing Rules
Space BEFORE heading: 1.25× to 2× paragraph spacing
Space AFTER heading: 0.375× to 0.75× body line spacingExample:
- Paragraph spacing: 20px
- Space before heading: 40px (20 × 2)
- Space after heading: 15px
Why more space above: Headings belong to content below, not above. More space above signals new section.
Critical rule: Always follow a heading with a paragraph—not a list, image, or table.
Line Spacing for Headings
| Heading Size | Line Spacing |
|---|---|
| Large (h1-h2) | 1.1 to 1.2 |
| Medium (h3-h4) | 1.2 to 1.3 |
| Small (h5-h6) | 1.3 to 1.4 |
Sweet spot: 1.2
Bold headings need tighter line spacing—their weight already creates separation.
Weight and Color
Font weight creates hierarchy:
- Bold/ExtraBold/Heavy for main headings
- Only ONE heading per screen at maximum weight
- Too many bold headings = oversaturation
Color for lower-level headings:
- h4–h6 may be same size as body text
- Different color creates enough contrast
All Caps Headings
Problems:
- Large all-caps hard to read (especially multi-line)
- Appears as "single solid black line"
Solutions:
- Increase letter spacing significantly
- Reserve for small decorative headings only
Dividers with Headings
Correct: Divider ABOVE heading
─────────────────────────
## New Section Heading
Content that belongs to this heading...Wrong: Divider between heading and content (breaks semantic connection)
---
Body Text and Line Spacing
Recommended Values
| Text Type | Line Spacing |
|---|---|
| Body (long reads) | 1.5 to 1.7 |
| Body (interfaces) | 1.3 to 1.5 |
| Headings | 1.1 to 1.4 |
| Captions/small text | 1.4 to 1.6 |
Starting point: 1.5 for long texts.
Adjustment Factors
Font characteristics:
- High x-height fonts → increase spacing
- Low x-height fonts → can reduce spacing
Line length:
- Shorter lines → less spacing needed
Critical insight: Line spacing is independent of font SIZE.
Paragraph Spacing
Formula: Paragraph spacing = Line spacing ÷ 1.5
Line spacing: 24px
Paragraph spacing: 16px (24 ÷ 1.5)---
Vertical Rhythm
What It Actually Is
Misconception: Baseline grids automatically create harmony.
Reality: True rhythm requires:
- Contrast and variety of elements
- Repetitive spacing patterns
- Harmonious relationships between values
Three Spacing Scale Approaches
1. Unit-Based Scale (Recommended for interfaces)
Base: 4px or 8px
Scale: 4, 8, 12, 16, 20, 24, 32, 40, 48, 64...Best for dashboards, apps, mixed content.
2. Line Spacing-Based Scale (Recommended for content)
Body line spacing: 24px
Scale: 24, 48, 72, 96...Best for articles, documentation, long reads.
3. Body Font Size-Based Scale (Avoid)
Body: 16px → Scale: 16, 32, 48, 64..."Most controversial and highly questionable." Text height ≠ pixel value.
Two-Scale Strategy
Complex projects may need two independent scales:
- Content scale (line-spacing based): For articles, documentation
- Module scale (unit-based): For cards, navigation, forms
---
Readability Fundamentals
The Core Principle
"If the text is difficult to read, all other design is irrelevant."
Color and Contrast
Serif fonts: Use pure black on white—thinner letterforms handle high contrast.
Sans-serif fonts: Tone down black (use #333) to avoid excessive contrast.
Dark backgrounds:
- Reduce white text intensity (use light gray)
- Pure white creates "glowing halo" effect
- Good for short text, challenging for long reads
Colored text: Reserve for feedback (errors, success).
Contrast Guidelines
| Situation | Recommendation |
|---|---|
| White on gray | Avoid—hard to read |
| White on dark/bright | Much better |
| Black on white (sans-serif) | Tone down the black |
| Black on white (serif) | Pure black works |
| White on black | Reduce white intensity |
Testing: Don't rely on vision alone. Use accessibility checkers.
Alignment
Center alignment: Only for brief content—3-4 lines maximum.
❌ Long centered paragraphs are hard to read
because the eye must find each new line start.
✓ Short centered text
works fine.Left alignment: Preferred for extended passages.
---
Scanning vs Reading
Two Different Design Modes
Scanning interfaces:
- Short texts, captions, headings, indicators
- Dashboards, control panels, marketing sites
- Users rapidly scan headings and images
- Design: Heavy emphasis on focal points, contrast, color
Reading interfaces:
- Long-form: articles, guides, documentation
- Users read beginning to end
- Design: Vertical layout, focus without distraction, careful body text parameters
Different Typography for Each
Mixed interfaces (homepage with linked articles) may need two separate typographic systems:
- Scanning: More color, more contrast
- Reading: Careful line length, spacing, rhythm
---
Links
Color Selection
Blue remains most familiar. However:
- Red links work within red-accented interfaces
- Match link color to overall accent system
Underlining Standards
In body text: Use underline + different color. Color alone "gets lost."
Exceptions to underlining:
- Navigation menus
- Dedicated CTA blocks
- All-caps links
Best practice: Users shouldn't expend cognitive effort determining clickability.
Link Density
"Principle of one link": Limit to one link per paragraph.
Multiple links? Relocate to separate block:
Paragraph text without inline links.
**Related resources:**
- Link to first resource
- Link to second resourceLink States
Hover: Clear contrast from normal appearance.
Active menu state: Explicit differentiation—underline removal or decorative elements.
UI Components Reference
Navigation
Primary Navigation
Position: Top or left side—users expect it there.
Visual weight: Visible but not overwhelming. Infrastructure, not main event.
Current state: Always indicate location:
- Bold text
- Background color change
- Underline or border accent
- Icon change
.nav-item.active {
background: var(--primary-light);
color: var(--primary);
font-weight: 600;
}Mobile Navigation
- Hamburger menus reduce discoverability—consider bottom nav for critical actions
- Touch targets: 44px minimum height
- Thumb zone: Place frequent items within easy reach
Breadcrumbs
When to use:
- Hierarchical sites (3+ levels)
- Users need location awareness
- Users may navigate up the tree
Separator: Use > or / consistently.
Current page: Not a link (redundant).
Home > Products > Electronics > Smartphones
↑ link ↑ link ↑ current (no link)---
Cards
Anatomy
┌─────────────────────────────────────┐
│ [Image/Media] │
├─────────────────────────────────────┤
│ Category Label │ ← Optional eyebrow
│ Card Title │ ← Primary info
│ Supporting text... │ ← Secondary info
├─────────────────────────────────────┤
│ [Action Button] [Secondary] │ ← Actions at bottom
└─────────────────────────────────────┘Design Rules
Consistent sizing: Cards in grid should be same size.
Image ratios: Pick one (16:9, 4:3, 1:1) and use consistently.
Padding: Consistent internal spacing (16px, 20px, 24px).
Clickable cards:
.card:hover {
box-shadow: 0 4px 12px rgba(0,0,0,0.15);
transform: translateY(-2px);
cursor: pointer;
}Content Hierarchy
1. Image (catches eye first) 2. Title (primary info) 3. Description (supporting) 4. Metadata (least important) 5. Actions (clear next steps)
Never: Put actions above title.
---
Tabs
When to Use
Good for:
- Switching related views
- Equally important content
- Quick access needed
- 2-5 options
Bad for:
- Sequential processes (use stepper)
- More than 5-6 sections
- Content needing comparison
- Long labels
Design Rules
Alignment: Left-align. Centered only for 2-3 short labels.
Active indicator:
.tab.active {
font-weight: 600;
color: var(--primary);
border-bottom: 2px solid var(--primary);
}
.tab:not(.active) {
color: var(--text-secondary);
border-bottom: 2px solid transparent;
}Keyboard: Tab to list, arrows to switch, Enter to activate.
Responsive Behavior
- Scrollable tabs with indicators
- Dropdown collapse
- Convert to accordions
Don't: Let tabs wrap to multiple lines.
---
Accordions
When to Use
Good for:
- Long expandable content
- FAQs
- Mobile navigation
- Clear section boundaries
Bad for:
- Frequently compared content
- Very short content
- Desktop primary navigation
Design Rules
Expand indicator: Chevron or +/- with animation.
Open behavior: Decide one-at-a-time or multiple.
Clickability: Entire header row, not just icon.
.accordion-header {
display: flex;
justify-content: space-between;
align-items: center;
padding: 16px;
cursor: pointer;
}
.accordion-icon {
transition: transform 0.2s;
}
.accordion.open .accordion-icon {
transform: rotate(180deg);
}---
Data Tables
Alignment
- Text: Left-align
- Numbers: Right-align (decimal alignment)
- Dates: Left-align
- Status: Center
.table td { text-align: left; }
.table td.numeric {
text-align: right;
font-variant-numeric: tabular-nums;
}
.table td.status { text-align: center; }Row height
- Minimum: 48px (touch accessible)
- Dense: 40px acceptable
Headers
- Sticky for long tables
- Sortable arrows
- Active sort: bold/colored
Responsive Options
1. Horizontal scroll 2. Card transformation 3. Priority columns only
Never: Let tables break layout.
---
Modals
Anatomy
┌─────────────────────────────────────┐
│ [X] Title │
├─────────────────────────────────────┤
│ Modal content │
├─────────────────────────────────────┤
│ [Cancel] [Confirm] │
└─────────────────────────────────────┘
↓ Dimmed overlay behindRules
Size: Don't fill screen—leave visible backdrop edge.
Max width: 480-640px for dialogs.
Close options: X button, Cancel, Escape, click outside (non-critical).
Focus trap: Tab cycles within modal.
.modal-overlay {
position: fixed;
inset: 0;
background: rgba(0, 0, 0, 0.5);
display: flex;
align-items: center;
justify-content: center;
}
.modal {
background: white;
border-radius: 8px;
max-width: 560px;
width: 90%;
max-height: 90vh;
overflow-y: auto;
}Destructive Actions
❌ Are you sure? [OK] [Cancel]
✓ Delete "Project Alpha"?
This will permanently delete 47 files.
This action cannot be undone.
[Cancel] [Delete Project] ← red---
Toast Notifications
Position: Top-right or bottom-center.
Duration:
- Success: 3-5 seconds
- Error: Stay until dismissed
- Info: 5-7 seconds
Stacking: Multiple toasts should stack, not replace.
.toast {
position: fixed;
bottom: 24px;
right: 24px;
padding: 12px 16px;
border-radius: 8px;
display: flex;
align-items: center;
gap: 12px;
box-shadow: 0 4px 12px rgba(0,0,0,0.15);
}
.toast.success {
background: var(--success-bg);
border-left: 4px solid var(--success);
}
.toast.error {
background: var(--error-bg);
border-left: 4px solid var(--error);
}Visual Hierarchy Reference
The Core Principle
Design exists to separate the primary from the secondary.
Users should instantly recognize what matters. When everything competes for attention, nothing matters.
---
Primary vs Secondary Elements
Typical primary elements:
- Headings
- Buttons
- Links
- Images
- Navigation
- Controls
Secondary elements:
- Body text
- Hints and help text
- Metadata
- Decorative elements
Exception: Content-oriented sites (news, docs) reverse this—body text becomes primary.
---
Five Techniques for Creating Focus
| Technique | How It Works |
|---|---|
| Shape | Distinctive forms attract attention (icons draw eye) |
| Color | Bright/contrasting colors indicate importance |
| Size | Larger elements signal importance |
| Weight | Bolder weight creates attention chain |
| Combination | Multiple techniques reinforce focus |
Warning: Using all techniques on everything negates their power. Reserve strong emphasis for truly important elements.
---
Three Levers of Hierarchy (Beyond Size)
1. Font Weight
Instead of making primary too large and secondary too small:
- Primary: 600-700 weight
- Secondary: 400-500 weight
- Avoid below 400 (accessibility)
.primary-text { font-weight: 600; color: #111; }
.secondary-text { font-weight: 400; color: #555; }
.tertiary-text { font-weight: 400; color: #888; }2. Color Proximity
De-emphasize by moving toward background color:
- Dark gray (#333) for primary
- Medium gray (#666) for secondary
- Light gray (#999) for tertiary
3. Contrast × Surface Area
Balance inversely:
- Large elements: lower contrast OK
- Small elements: need higher contrast
- Small + low contrast = invisible
- Large + high contrast = overwhelming
---
Semantic Color Usage
Limit accent colors to meaningful contexts:
- Blue: links and interactive elements
- Red: errors and destructive actions
- Green: success states
- Yellow/Orange: warnings
Don't use accent colors for decoration. Every colored element should mean something.
---
The Action Pyramid
Every page has: 1. One primary action — The main thing 2. Few secondary actions — Important but not critical 3. Several tertiary actions — Rarely needed
| Level | Treatment |
|---|---|
| Primary | Solid fill, high contrast, largest |
| Secondary | Outline or subtle fill |
| Tertiary | Text-only or ghost |
Common mistake: Making destructive actions look primary. Unless destruction IS the purpose.
---
The Consistency Principle
Same patterns should work the same way everywhere:
- Same button style = same type of action
- Same spacing rhythm throughout
- Same interaction patterns
- Same feedback mechanisms
Inconsistency tax: Every deviation forces relearning.
---
The Forgiveness Principle
Interfaces must tolerate error:
- Every action reversible
- Destructive operations require confirmation
- Recovery always possible
---
Design Process Tips
Start with Features, Not Layouts
Don't design layout first. Start with:
- What does this feature need?
- What elements required?
- How do they relate?
Layout emerges from features.
Work in Grayscale First
Design without color to establish hierarchy through:
- Size
- Weight
- Spacing
- Position
Why: If design doesn't work in grayscale, it relies too heavily on color. Color should enhance hierarchy, not create it.
Start with Too Much Whitespace
Begin generous, reduce as needed:
- Easier to remove than add
- Cramped feels cheap
- Whitespace = quality and clarity
Design Mobile-First
Mobile constraints force better decisions:
- Prioritize ruthlessly
- Simplify navigation
- Focus on essential
- Scale up is easier
---
Troubleshooting
"It looks cluttered"
- Too many elements competing?
- Not enough whitespace?
- Inconsistent spacing?
- Hierarchy unclear?
Fix: Remove non-essential, increase spacing, reduce secondary element weight.
"Users don't know what to click"
- Links not styled distinctly?
- Buttons look like labels?
- Ghost buttons blending in?
- No hover states?
Fix: Underline + color for links, shadows on buttons, solid primary CTAs.
"Everything competes for attention"
- Multiple primary actions?
- Too many accent colors?
- Same visual weight everywhere?
Fix: One primary action, semantic colors only, vary weight/color.