Install
openclaw skills install ui-designComprehensive UI design skill covering fundamentals, patterns, and anti-patterns. Layout, typography, color, spacing, accessibility, motion, and component design. Use when building any web interface, reviewing design quality, or creating distinctive UIs.
openclaw skills install ui-designThe definitive guide for building production-grade web interfaces. Covers the full stack of design decisions from layout to motion.
ui design, web design, layout, typography, color palette, spacing, visual hierarchy, responsive design, accessibility, motion design, component design, design tokens, frontend, css, tailwind
| Factor | Impact | Time Investment |
|---|---|---|
| Typography | 40% | Choose 1-2 fonts well |
| Spacing | 25% | Use consistent scale |
| Color | 20% | Limit palette, ensure contrast |
| Everything else | 15% | Shadows, borders, motion |
Focus on typography and spacing first. They're 65% of perceived quality.
Mediocrity is forgettable. Pick an extreme:
| Direction | Characteristics | Use When |
|---|---|---|
| Brutally Minimal | Stark, essential, nothing extra | Developer tools, productivity |
| Luxury/Refined | Premium, subtle elegance | High-end products, fashion |
| Playful | Fun, bright, approachable | Consumer apps, games |
| Editorial | Type-forward, grid-based | Content sites, magazines |
| Industrial | Function-forward, robust | B2B, enterprise |
| Layout Need | Tool | Why |
|---|---|---|
| Page-level structure | CSS Grid (grid-template-areas) | Named regions, explicit control |
| Navigation bars | Flexbox | Single-axis, gap spacing |
| Card grids | Grid (auto-fill/auto-fit) | Responsive without media queries |
| Centering | Grid (place-items: center) | Shortest, most reliable |
| Sidebar + content | Grid (250px 1fr) | Fixed + fluid |
| Stacking/overlaps | Grid + grid-area: 1/1 | No position: absolute needed |
/* Standard content width */
.container {
width: 100%;
max-width: 1280px;
margin-inline: auto;
padding-inline: clamp(1rem, 5vw, 3rem);
}
/* Full-bleed with contained content */
.full-bleed {
width: 100vw;
margin-left: calc(50% - 50vw);
}
| Mistake | Problem | Fix |
|---|---|---|
| Mixing container widths | Inconsistent alignment | Use single max-w-* value |
| Content behind fixed navbar | Hidden content | Add pt-[navbar-height] |
| No mobile padding | Edge-to-edge text | Add px-4 minimum |
| Centered everything | Weak hierarchy | Left-align body text |
Typography carries 90% of a design's personality.
| Context | Display Font | Body Font | Example |
|---|---|---|---|
| Editorial | High-contrast serif | Neutral humanist | Playfair + Source Sans |
| SaaS | Geometric sans | Matching sans | DM Sans + DM Mono |
| Luxury | Thin modern serif | Elegant sans | Cormorant + Jost |
| Developer | Monospace display | Monospace body | JetBrains Mono + IBM Plex |
| Playful | Rounded/quirky | Clean readable | Nunito + Outfit |
--text-xs: 0.64rem; /* 10px - captions */
--text-sm: 0.8rem; /* 13px - secondary */
--text-base: 1rem; /* 16px - body */
--text-lg: 1.25rem; /* 20px - lead */
--text-xl: 1.563rem; /* 25px - h4 */
--text-2xl: 1.953rem; /* 31px - h3 */
--text-3xl: 2.441rem; /* 39px - h2 */
--text-4xl: 3.052rem; /* 49px - h1 */
| Rule | Value | Why |
|---|---|---|
| Minimum body size | 16px | Below is hard to read |
| Body line-height | 1.5-1.75 | Improves readability |
| Heading line-height | 1.1-1.2 | Tighter for large text |
| Line length | 60-75 characters | Optimal reading |
| Paragraph spacing | 1.5em | Clear separation |
| Mistake | Problem | Fix |
|---|---|---|
| System fonts only | Generic look | Use Google Fonts or variable fonts |
| Too many fonts | Visual chaos | Max 2 families |
| Weak weight contrast | Poor hierarchy | Bold headings (600+), regular body |
| Long lines | Hard to read | Add max-w-prose (65ch) |
Every palette needs five functional roles:
| Role | Purpose | Usage |
|---|---|---|
| Primary | Brand identity | Buttons, links, active states |
| Neutral | Text, backgrounds | Body text, cards, dividers |
| Accent | Secondary actions | Tags, badges, highlights |
| Semantic | Feedback | Success/warning/error states |
| Surface | Layered backgrounds | Cards, modals, overlays |
Create depth through lightness, not shadows:
:root {
--surface-0: hsl(220 15% 8%); /* page background */
--surface-1: hsl(220 15% 12%); /* card */
--surface-2: hsl(220 15% 16%); /* raised element */
--surface-3: hsl(220 15% 20%); /* popover/modal */
}
| Text Size | Minimum Ratio | Enhanced (AAA) |
|---|---|---|
| Normal text (<18px) | 4.5:1 | 7:1 |
| Large text (≥18px bold, ≥24px) | 3:1 | 4.5:1 |
| UI components | 3:1 | — |
| Mistake | Problem | Fix |
|---|---|---|
| Purple gradient on white | "AI aesthetic" cliché | Use intentional brand colors |
| Low contrast text | Accessibility fail | Test with contrast checker |
| Color-only indicators | Colorblind users excluded | Add icons/text |
| Too many colors | Visual noise | 3-5 colors maximum |
| Light gray text on white | Unreadable | slate-600 minimum |
--space-1: 0.25rem; /* 4px - tight gaps */
--space-2: 0.5rem; /* 8px - input padding */
--space-3: 0.75rem; /* 12px - button padding */
--space-4: 1rem; /* 16px - default spacing */
--space-6: 1.5rem; /* 24px - section padding */
--space-8: 2rem; /* 32px - section gaps */
--space-12: 3rem; /* 48px - major breaks */
--space-16: 4rem; /* 64px - page rhythm */
| Rule | Implementation |
|---|---|
Use gap not margins | display: flex; gap: var(--space-4) |
| Consistent padding | Same values on all cards/sections |
| More space between groups | Less space within groups (Gestalt) |
| No arbitrary values | Only use scale tokens |
| Mistake | Problem | Fix |
|---|---|---|
| Arbitrary pixel values | Inconsistent rhythm | Use spacing scale only |
| Margin on children | Margin collapse bugs | Use gap on parent |
| Equal spacing everywhere | No visual grouping | More between, less within |
| Tight mobile padding | Cramped feeling | Minimum p-4 on mobile |
Guide the eye through deliberate contrast.
| Technique | How | Impact |
|---|---|---|
| Size | Hero 3-4x body | Immediate focal point |
| Weight | Bold headings, regular body | Scannability |
| Color | Primary vs muted | Information layers |
| Space | Isolation creates emphasis | Draws attention |
| Position | Top-left anchors reading | Natural flow |
Eyebrow ← xs, uppercase, muted color
Title ← xl, semibold, primary color
Body ← base, secondary color, 1.6 line-height
Action ← spaced apart, mt-4 minimum
| Breakpoint | Target | Key Changes |
|---|---|---|
| < 640px | Mobile | Single column, stacked nav, 44px touch targets |
| 640-1024px | Tablet | Two columns, collapsible sidebars |
| 1024-1440px | Desktop | Full layout, hover enabled |
| > 1440px | Wide | Max-width container, prevent ultra-wide lines |
/* Fluid typography */
h1 { font-size: clamp(2rem, 1.5rem + 2.5vw, 3.5rem); }
/* Fluid spacing */
section { padding-block: clamp(2rem, 1rem + 4vw, 6rem); }
/* Intrinsic grid */
.grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(min(100%, 20rem), 1fr));
gap: var(--space-6);
}
| Mistake | Problem | Fix |
|---|---|---|
| No viewport meta | Broken mobile | Add width=device-width |
| Fixed widths | Overflow on mobile | Use max-w-* and % |
| Tiny touch targets | Frustrating taps | Minimum 44x44px |
| Hidden horizontal scroll | Broken layout | Test at 375px width |
Accessibility is not optional.
| Requirement | Implementation | Standard |
|---|---|---|
| Color contrast | 4.5:1 normal, 3:1 large | WCAG 2.1 AA |
| Keyboard navigation | Tab order matches visual | WCAG 2.1.1 |
| Focus indicators | Visible :focus-visible ring | WCAG 2.4.7 |
| Semantic HTML | <button>, <nav>, <main> | WCAG 1.3.1 |
| Alt text | Descriptive for images | WCAG 1.1.1 |
| Motion safety | prefers-reduced-motion | WCAG 2.3.3 |
| Touch targets | 44×44px minimum | WCAG 2.5.8 |
:focus-visible {
outline: 2px solid var(--color-primary);
outline-offset: 2px;
}
/* Remove default only if custom exists */
:focus:not(:focus-visible) {
outline: none;
}
@media (prefers-reduced-motion: reduce) {
*, *::before, *::after {
animation-duration: 0.01ms !important;
transition-duration: 0.01ms !important;
}
}
Use motion to communicate, not decorate.
| Interaction | Duration | Easing |
|---|---|---|
| Button hover | 150ms | ease-out |
| Modal open | 250ms | ease-out |
| Modal close | 200ms | ease-in |
| Page transition | 300ms | ease-in-out |
| Stagger delay | 50-80ms per item | — |
| Micro-feedback | 100ms | ease-out |
.item {
opacity: 0;
translate: 0 1rem;
animation: reveal 0.5s ease-out forwards;
}
.item:nth-child(1) { animation-delay: 0ms; }
.item:nth-child(2) { animation-delay: 60ms; }
.item:nth-child(3) { animation-delay: 120ms; }
@keyframes reveal {
to { opacity: 1; translate: 0 0; }
}
| Mistake | Problem | Fix |
|---|---|---|
| Animating width/height | Performance hit | Use transform only |
| > 500ms duration | Feels sluggish | 150-300ms for most |
| Motion everywhere | Overwhelming | Focus on entrances/exits |
| No reduced-motion | Accessibility fail | Always check preference |
Every interactive element needs clear states.
| State | Visual Treatment |
|---|---|
| Default | Base styling |
| Hover | Subtle background/shadow shift |
| Active/Pressed | Slight inset, reduced shadow |
| Focus | High-visibility ring |
| Disabled | 50% opacity, not-allowed cursor |
| Loading | Spinner or skeleton |
.btn {
transition: all 150ms ease-out;
}
.btn:hover {
background: var(--color-primary-600);
}
.btn:active {
transform: scale(0.98);
}
.btn:focus-visible {
outline: 2px solid var(--color-primary);
outline-offset: 2px;
}
.btn:disabled {
opacity: 0.5;
cursor: not-allowed;
}
Structure tokens in three layers:
/* Layer 1: Primitives */
--blue-500: oklch(0.55 0.2 250);
--gray-100: oklch(0.95 0.005 250);
--radius-md: 0.5rem;
/* Layer 2: Semantic */
--color-primary: var(--blue-500);
--color-surface: var(--gray-100);
--radius-button: var(--radius-md);
/* Layer 3: Component */
--btn-bg: var(--color-primary);
--btn-radius: var(--radius-button);
--btn-padding: var(--space-2) var(--space-4);
This allows theme switching by remapping Layer 2 only.
transform/opacitytransform and opacityslate-600 minimum on whiteui-ux-pro-max — Searchable design databases with CLIfrontend-design — Creative aesthetics, avoiding "AI slop"theme-factory — Applying themes to artifactsdesign-system-patterns — Token architecture and theming