# Design Knowledge: Layout, Spacing & Motion

Compiled from Refactoring UI, Material Design, MDN, GSAP, Apple HIG, Linear, Vercel, and award-winning site analysis (20 Awwwards SOTD/SOTM/SOTY winners).

---

## 4. Layout & Composition

### Grid System Selection
RULE: When choosing a grid, apply:
- **4px base grid** for dense data interfaces (admin panels, dashboards) because fine granularity supports tight spacing
- **8px base grid** for standard web UI (most common, good balance) because it scales cleanly (8, 16, 24, 32, 48, 64)
- **12-column grid** for responsive marketing pages because 12 divides into 2, 3, 4, and 6 columns
- **Baseline grid** (aligned to body text line-height) for text-heavy editorial because vertical rhythm improves readability

### Whitespace Theory
RULE: When spacing elements, start with MORE whitespace than feels natural and tighten as needed because it is easier to remove space than to figure out where to add it. Whitespace is not "empty" — it is a design element that creates grouping, hierarchy, and breathing room. (Source: Refactoring UI)

RULE: When differentiating macro vs micro whitespace, apply:
- **Micro** (4-16px): within components — between label and input, icon and text, button padding
- **Medium** (16-32px): between related elements — between fields in a form, between nav items
- **Macro** (48-120px): between page sections — between hero and features, between footer sections

### Container Width
RULE: When setting max content width, apply:
- **Text-heavy content**: 680-760px (optimal reading width)
- **Marketing pages**: 1100-1200px (comfortable with side padding)
- **Full-bleed sections**: 100% width with inner content container at 1100-1200px
- **Dashboards**: 1280-1440px (data density)

because content width controls readability and visual comfort.

### F-Pattern and Z-Pattern
RULE: When designing for scanning behavior:
- **Z-pattern** for pages with minimal text (landing pages, hero sections): eye moves top-left → top-right → bottom-left → bottom-right. Place logo top-left, CTA top-right, content bottom-left, secondary CTA bottom-right.
- **F-pattern** for text-heavy pages (blogs, docs, search results): eye scans horizontally at top, then moves down in vertical sweeps. Place important content on the left, use headings and bullets to break vertical scanning.

### Asymmetric Composition
RULE: When creating visual interest, apply a 60/40 or 2/3 + 1/3 split instead of 50/50 because equal splits feel static and "template-y." Asymmetry signals intentional design. Place key content on the left (for LTR layouts) in the larger portion.

### Visual Weight
RULE: When balancing a layout, understand that visual weight is created by: size (larger = heavier), color saturation (more saturated = heavier), density (more content = heavier), isolation (surrounded by whitespace = heavier), and complexity (more detail = heavier). Balance heavy elements with multiple lighter elements.

### Container vs Edge-to-Edge
RULE: When mixing containment, apply contained content (max-width with centered layout) for text and controls, and edge-to-edge (full-width) for background treatments, images, and dividers because the contrast between contained and full-width creates visual depth.

---

## 5. Spacing & Proportion

### Spacing Scale — 8px Base
RULE: When defining a spacing system, apply these values from an 8px base:
```
4   — micro (icon gaps, tight padding)
8   — small (button padding, inline gaps)
12  — compact (dense list items)
16  — standard (component padding, field gaps)
20  — comfortable (card padding)
24  — medium (between component groups)
32  — large (between sections on compact pages)
40  — section (between major content blocks)
48  — spacious (hero to content transition)
64  — major section (marketing page section gap)
80  — generous (full-page section breaks)
96  — expansive (landing page hero padding)
128 — dramatic (hero vertical centering offset)
```

### Section Spacing
RULE: When spacing major page sections, apply 64-96px on desktop and 40-64px on mobile because sections that are too close blur together and sections that are too far feel disconnected.

### Component Internal vs External Spacing
RULE: When designing components, apply a 1:1.5 to 1:2 ratio of internal padding to external spacing (e.g., 16px internal padding, 24-32px between components) because components should feel self-contained but not isolated.

### Density Levels
RULE: When choosing density:
- **Compact** (8px component padding, 4-8px gaps, 36-40px row height) — data tables, admin panels, developer tools
- **Comfortable** (16px component padding, 12-16px gaps, 48px row height) — standard UI, SaaS products
- **Spacious** (24-32px component padding, 16-24px gaps, 64px+ row height) — marketing/editorial, luxury brands

### Responsive Spacing
RULE: When scaling spacing across breakpoints, apply 60-70% of desktop spacing on tablet and 50-60% on mobile because the same spacing on mobile proportionally takes more screen real estate. Desktop 96px → Tablet 64px → Mobile 48px.

### Fibonacci in Spacing
RULE: When creating spacing variety, the Fibonacci sequence (1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89) mapped to 4px base (4, 4, 8, 12, 20, 32, 52, 84px) produces naturally harmonious proportions because the Fibonacci ratio converges on the golden ratio.

---

## 6. Motion & Interaction

### 12 Animation Principles Adapted for UI
RULE: When adding motion, understand these translations from Disney's principles:
- **Squash & Stretch** → Button press feedback (scale 0.95-0.98 on active)
- **Anticipation** → Pre-action hints (subtle movement before main animation)
- **Staging** → Direct attention to the animating element (fade background, highlight target)
- **Follow-Through** → Overshoot on spring animations (scale to 1.05 then settle to 1.0)
- **Slow-In/Slow-Out** → Easing curves (never linear for organic motion)
- **Arcs** → Natural motion paths (circular reveals instead of straight slides)
- **Secondary Action** → Ripple effects, shadow changes alongside primary motion
- **Timing** → Duration standards (see below)
- **Exaggeration** → Delight moments (overshoot, bounce on playful brands)
- **Solid Drawing** → Material feel (shadows respond to elevation changes)
- **Appeal** → Personality (custom easing curves that feel "right" for the brand)

### Duration Standards
RULE: When setting animation durations, apply:
- **Micro-interactions** (button hover, toggle, ripple): 100-200ms
- **Small transitions** (dropdown, tooltip, color change): 200-300ms
- **Medium transitions** (modal open, card expand, slide-in): 300-500ms
- **Large transitions** (page transition, hero animation): 500-700ms
- **Complex animations** (multi-element reveals): 700-1000ms

because too fast (< 100ms) is imperceptible and too slow (> 1000ms) feels broken.

### Easing Curves — The Standard Library
RULE: When choosing easing curves:

**Entrances (elements appearing):**
- `cubic-bezier(0, 0, 0.58, 1)` (ease-out) — standard, clean
- `cubic-bezier(0, 0, 0.2, 1)` — Material standard deceleration
- `cubic-bezier(0.32, 0.72, 0, 1)` — Ravi Klaassens "move" curve, fast start gentle finish

**Exits (elements leaving):**
- `cubic-bezier(0.42, 0, 1, 1)` (ease-in) — standard departure
- `cubic-bezier(0.4, 0, 1, 1)` — Material standard acceleration

**State changes (bidirectional):**
- `cubic-bezier(0.42, 0, 0.58, 1)` (ease-in-out) — symmetric
- `cubic-bezier(0.4, 0, 0.2, 1)` — Material standard easing

**Playful/Brand (overshoot):**
- `cubic-bezier(0.34, 2.27, 0.64, 1)` — Ravi Klaassens "bounce" curve
- `cubic-bezier(0.59, 1, 0.88, 1.01)` — Ravi Klaassens "transform" curve (slight overshoot)
- `cubic-bezier(0.5, -0.5, 1, 1.5)` — generic overshoot/bounce

**Linear:**
- `linear` — only for continuous loops (rotation, marquee, loading spinners)

### GSAP Easing Reference
RULE: When using GSAP, the default ease is `power1.out`. Progressive intensity options:
- `power1` — light (quad) — subtle, professional
- `power2` — medium (cubic) — standard UI
- `power3` — strong (quart) — dramatic
- `power4` — very strong (quint) — maximum emphasis
- `back` — overshoots then returns (playful)
- `elastic` — spring oscillation (fun, use sparingly)
- `expo` — exponential (dramatic starts/stops)

### Stagger Patterns
RULE: When animating lists or grids, apply stagger delays of 30-50ms between items because this creates a wave effect that feels natural. For grid items, add column offset: `delay = (row * 50ms) + (col * 30ms)`.

RULE: When staggering text line reveals (award-winning technique from Artem Shcherban), use GSAP SplitText to break text into lines, mask each line with `overflow: hidden`, and animate from `yPercent: 100` to `0` with 50-80ms stagger between lines.

### Scroll-Linked Animations
RULE: When using scroll-driven animations, apply:
- **Parallax**: Background moves at 0.3-0.7x scroll speed (never more than 0.7x or it causes nausea)
- **Reveal on scroll**: Elements fade in + translate up 20-40px as they enter viewport
- **Progress indicators**: Scroll progress bar fills based on scroll position
- **Sticky sections**: Content pins while scroll drives inner animations

### Page Transitions (Award-Winning Technique)
RULE: When implementing page transitions, apply a three-phase pattern:
1. **Out**: Current content fades + translates down 20-40px (200-300ms, ease-in)
2. **Loading**: Overlay covers viewport, preloader shows (Barba.js pattern)
3. **In**: New content reveals + translates up from 20-40px below (300-500ms, ease-out)

because seamless page transitions make a site feel like an application, not a series of pages.

### Text Reveal System (Ravi Klaassens Technique)
RULE: When creating premium button/menu interactions, use CSS Grid stacking with clip-path:
- Stack two text layers using `display: grid; grid-template-areas: "stack"` with both children in the same cell
- Default state: primary text visible, secondary text hidden via `clip-path: inset(100% 0 0 0)`
- Hover state: primary text clips away from bottom (`clip-path: inset(100% 0 0 0)`), secondary reveals (`clip-path: inset(0 0 0 0)`)
- Add `translate: 0 0.25em` on outgoing text for "pushed away" illusion
- Sequence: background scales first, text swap follows with 75ms delay

### 3D Card Fold (Ravi Klaassens Technique)
RULE: When adding hover depth to cards, apply `perspective: 1000px` on the container and `rotateY(-32deg) rotateX(5deg)` on hover to the inner element because subtle 3D rotation creates a paper-fold effect that feels tactile.

### Squish & Scale Button Effect (Ravi Klaassens Technique)
RULE: When adding tactile feedback to buttons, apply inverse scaling:
- Container: `scale: 0.975 0.945` (compresses)
- Inner content: `scale: calc(1/0.975), calc(1/0.945)` (counter-scales to maintain text size)
because this creates a physical "press" illusion without distorting text.

### Reduced Motion
RULE: When users have `prefers-reduced-motion: reduce`, disable ALL non-essential animations and replace with instant state changes because animations can cause motion sickness. Essential animations (like indicating an element appeared) should use opacity-only transitions under 150ms.

### Performance Rules
RULE: When building animations, only animate `transform` and `opacity` because these properties are compositor-friendly and can run at 60fps without triggering layout recalculations. Apply `will-change: transform, opacity` on elements that will animate, and remove it after animation completes.

---

## 7. Award-Winning Motion Techniques (From Awwwards SOTD/SOTM/SOTY Analysis)

### Easing Systems — What Winners Actually Use
RULE: When building an award-level site, do NOT use standard CSS easings (ease, ease-in-out). Instead, define a curated system of 5-18 custom cubic-bezier curves. Analysis of 20 Awwwards winners reveals these most-used curves:

| Curve | Name | Feel | Source |
|-------|------|------|--------|
| `cubic-bezier(0.65, 0.05, 0, 1)` | Lando unified | Fast-start, slight overshoot | landonorris.com |
| `cubic-bezier(0.32, 0.72, 0, 1)` | RK move | Fast start, gentle finish | raviklaassens.com |
| `cubic-bezier(0.59, 1, 0.88, 1.01)` | RK transform | Slight overshoot bounce | raviklaassens.com |
| `cubic-bezier(0.34, 2.27, 0.64, 1)` | RK bounce | Heavy overshoot, playful | raviklaassens.com |
| `cubic-bezier(0.4, 0, 0.2, 1)` | Material standard | Clean, professional | brand.dropbox.com |
| `cubic-bezier(0.6, 0, 0, 1)` | Swoop | Aggressive deceleration | brand.dropbox.com |
| `cubic-bezier(0, 0.8, 0.4, 1)` | Quick settle | Fast entry, smooth end | brand.dropbox.com |
| `cubic-bezier(0.625, 0.05, 0, 1)` | Expo settle | Strong ease-out | utopiatokyo.com, raviklaassens.com |
| `cubic-bezier(0.62, 0.05, 0.01, 0.99)` | Vast primary | Near-linear aggressive | vastspace.com |
| `cubic-bezier(0.4, 1.35, 0.5, 0.97)` | Vast overshoot | Bounce with settle | vastspace.com |
| `cubic-bezier(0.35, 0.35, 0, 1)` | Obsidian smooth | Clean ease-out | obsidianassembly.com |
| `cubic-bezier(0.6, 0.5, 0, 3)` | Obsidian bounce | Heavy overshoot | obsidianassembly.com |
| `cubic-bezier(0.22, 1, 0.36, 1)` | Expo out variant | Strong exit | utopiatokyo.com |
| `cubic-bezier(0.5, 0.5, 0, 1)` | Lando page | Page transition | landonorris.com |

because award-winning sites use custom easing as a brand element — the curves define how the site "feels."

### Advanced Easing — CSS linear() for Spring Physics
RULE: When you need spring/bounce physics without JS, use CSS `linear()` with multiple stops because it enables complex multi-step easing in pure CSS:
```css
/* Award-winning elastic ease (raviklaassens.com, utopiatokyo.com) */
--elastic-ease: linear(
  0, 0.5737 7.6%, 0.8382 11.87%, 0.9463 14.19%, 1.0292 16.54%,
  1.0886 18.97%, 1.1258 21.53%, 1.137 22.97%, 1.1424 24.48%,
  1.1423 26.1%, 1.1366 27.86%, 1.1165 31.01%, 1.0507 38.62%,
  1.0219 42.57%, 0.9995 46.99%, 0.9872 51.63%, 0.9842 58.77%,
  1.0011 81.26%, 1
);
```
This creates a spring with overshoot to ~1.14, settling oscillation, and convergence. The peak at 32% and settle by 85% feels organic.

### Duration Standards — Award-Winning Timing
RULE: When setting durations, apply these ranges verified from actual winners:

| Context | Duration | Source |
|---------|----------|--------|
| Button hover / micro | 0.2-0.4s | Dropbox, Vast, RK |
| State transitions / nav | 0.3-0.6s | All winners |
| Content reveals / panels | 0.5-0.75s | Lando, Dropbox, RK |
| Menu / full-screen overlays | 0.6-0.9s | RK, Obsidian, Artem |
| Text line reveals | 0.6-1.0s | Artem, Obsidian, RK |
| Logo / hero animations | 1.0-1.5s | Dropbox, Obsidian |
| Page transitions | 0.6-1.0s | RK, Artem, Dropbox |
| Ambient / background loops | 1.9-3.0s | Utopia, Dropbox |
| Continuous marquees | 30s infinite | Lando, Obsidian |

### Unified vs Curated Approach
RULE: When choosing between a single unified easing vs multiple curated easings, pick based on site personality:
- **Unified (1 curve, 1 duration)**: landonorris.com uses `cubic-bezier(0.65, 0.05, 0, 1)` at `0.75s` for EVERYTHING. Creates extreme consistency. Best for luxury/minimal brands.
- **Curated (5-18 curves)**: brand.dropbox.com defines 18 unique curves for different contexts. Creates richer interaction feel. Best for expressive/creative brands.
because the choice IS the personality — unified = restrained elegance, curated = expressive depth.

### Text Animation — SplitText Reveal System
RULE: When animating text reveals, use GSAP SplitText with line-level masking because this is the most common award-winning text technique (used by artemshcherban.com, raviklaassens.com, obsidianassembly.com):
```css
/* Line mask container */
.split-line { clip-path: inset(0 0 100% 0); overflow: hidden; }
.split-line.revealed { clip-path: inset(-10% 0 -10% 0); }
```
- Each line starts hidden via `translateY(100%)` or `clip-path: inset(0 0 100% 0)`
- Reveals with stagger of **50-150ms** between lines
- Duration **0.6-1.0s** with strong ease-out
- Character-level splits for hero text: each char gets random stagger `var(--char-random) * 75ms` (obsidianassembly.com)

### Dual-Layer Text Swap (RK Technique)
RULE: When creating premium button/link hover effects, use CSS Grid stacking with clip-path because this creates the "text slides away, new text appears" pattern seen on raviklaassens.com:
```css
.button { display: grid; grid-template-areas: "stack"; }
.button span, .button::after {
  grid-area: stack;
  transition: clip-path 0.4s cubic-bezier(0.32, 0.72, 0, 1),
              translate 0.35s cubic-bezier(0.32, 0.72, 0, 1);
}
/* Outgoing text */
.button span { clip-path: inset(0 0 0 0); translate: 0 0; }
.button:hover span { clip-path: inset(100% 0 0 0); translate: 0 0.25em; }
/* Incoming text via ::after with content: attr(data-text) */
.button::after { clip-path: inset(100% 0 0 0); translate: 0 -0.25em; }
.button:hover::after { clip-path: inset(0 0 0 0); translate: 0 0; }
```
because the counter-movement (outgoing pushes down, incoming pushes up) creates depth.

### Velocity-Based Blur (Artem Shcherban Technique)
RULE: When building scroll-driven carousels, apply velocity-based blur because artemshcherban.com tracks scroll velocity to dynamically blur items during fast movement:
```js
// Track progress velocity
const speed = getProgressVelocity(loop.progress());
// Apply blur proportional to speed
gsap.set(element, {
  filter: `blur(${clamp(0, 15, speed * 10)}px)`
});
// Fade info text inversely
gsap.set(infoText, {
  opacity: 1 - clamp(0, 1, speed * 10)
});
```
because velocity-responsive feedback makes interactions feel physically real.

### Scroll-Driven Tile Explosion (Dropbox Brand Technique)
RULE: When creating dramatic scroll reveals, assign each tile a unique vector and translate it based on scroll progress because brand.dropbox.com's tile explosion is the most distinctive scroll effect analyzed:
```
Desktop vectors:
  Strategy:     [4, 2]    Voice:  [-0.1, 1]
  Logo:         [-1, -0.1] Type:   [-4, 2]
  Icons:        [4, -2]   Color:  [1, 0.1]
  Imagery:      [0.1, -1] Motion: [-4, -2]
```
- Scale zooms from 2x to 1x as scroll progresses
- Nav button shrinks through 3 discrete states based on scroll %
- All orchestrated with custom `cubicBezier(1, 0.25, 0.85, 1)` JS scroll easing

### 3D Card Fold Effect
RULE: When adding hover depth to cards, apply perspective + rotation because raviklaassens.com uses `perspective: 1000px` with `rotateY(-32deg) rotateX(5deg)` on hover for a paper-fold effect. The inner content counter-rotates to maintain readability.

### Squish & Scale Button Press
RULE: When adding tactile press feedback, use inverse scaling because raviklaassens.com applies:
```css
/* Container compresses */
.button:active { scale: 0.975 0.945; }
/* Inner content counter-scales to preserve text */
.button:active .content { scale: calc(1/0.975) calc(1/0.945); }
```
because this creates a physical "squish" without distorting text.

### Scroll Comet Indicator (RK Technique)
RULE: When building scroll indicators, animate a shape through multiple transform stages because raviklaassens.com uses a CSS-only comet with 6 keyframes over 2.8s that morphs scaleY, position, opacity, and clip-path shape simultaneously.

### Page Transition — Clip-Path Band Wipe (Obsidian Technique)
RULE: When implementing page transitions, use horizontal band wipe with stagger because obsidianassembly.com uses 5 horizontal bands (each 25% height) that wipe in with `scaleX(0→1)` staggered by `0.15s`, then wipe out in reverse order. Text counter-translates during the wipe to maintain visual continuity.

### Preloader — SVG Stroke Draw (Dropbox Technique)
RULE: When building preloaders, animate SVG stroke-dashoffset because brand.dropbox.com draws its logo over 1.25s with `stroke-dashoffset: 0`, then the container shrinks from full-viewport to icon size, then gridlines fade in over 3s, then body overflow unlocks at 1800ms. Total experience: ~3s.

### Preloader — Counter-Based Loading (Artem Technique)
RULE: When showing loading progress, use animated digit reels because artemshcherban.com uses 3 digit counters that progress through segments [0, 23, 54, 82, 100] at `0.6s` each with `expo.out` easing, creating a satisfying acceleration effect.

### Glitch Effect System (Utopia Tokyo Technique)
RULE: When adding glitch/digital effects, combine RGB split + scanlines + noise because utopiatokyo.com layers three effects:
- **RGB split**: `drop-shadow` with red (#ff2a2a) and cyan (#00f3ff) offset
- **Scanlines**: 1.9s infinite `translateY(0→12px)` with repeating gradient
- **Noise grain**: 0.9s `steps(2, end)` with translate3d jitter
because layering effects creates richness that single effects cannot.

### Reduced Motion — Award Standard
RULE: When implementing `prefers-reduced-motion`, set ALL durations to 0 because both brand.dropbox.com and utopiatokyo.com use `--motion: 1` with `@media (prefers-reduced-motion: reduce) { :root { --motion: 0 } }` so every `calc(0.65s * var(--motion))` becomes instant. This is cleaner than individual overrides.

### Animation Libraries — What Winners Use
RULE: When choosing animation libraries, understand the award-winning landscape:

| Library | Purpose | Sites |
|---------|---------|-------|
| **GSAP + ScrollTrigger** | Timeline animation, scroll-linked | RK, Artem, Vast, Active Theory |
| **GSAP SplitText** | Text line/char reveals | RK, Artem, Obsidian |
| **Lenis** | Smooth scrolling | Lando, Artem, Utopia, RK |
| **Barba.js** | SPA page transitions | RK, Lusion |
| **Three.js** | WebGL 3D rendering | Bruno Simon, Lusion, Active Theory |
| **Rapier** | Physics engine | Bruno Simon |
| **Rive** | Canvas animations | Lando |
| **Framer Motion** | React animation | Shopify |
| **Anime.js** | Lightweight JS animation | animejs.com |
| **None (custom CSS)** | Pure transitions | brand.dropbox.com (18 custom curves!) |

**Key finding**: brand.dropbox.com built everything with zero animation libraries — pure CSS transitions orchestrated by vanilla JS. It outperforms library-heavy sites.

### Award-Winning Motion Design Principles (Cross-Site)
RULE: When aiming for award-quality motion, follow these 8 principles derived from 20 SOTD/SOTY winners:

1. **Unified easing = brand identity**. Pick 1 curve (luxury) or 5-18 curves (expressive). Never mix random easings.
2. **Scroll is a design dimension**, not just navigation. Use it to drive zoom, position, opacity, and state changes simultaneously.
3. **Custom > library**. Dropbox's vanilla CSS outperforms GSAP-heavy sites. Libraries are tools, not substitutes for design.
4. **Physics-based motion feels different**. Spring physics (Anime.js `stiffness: 120, damping: 6`) and Rapier physics feel fundamentally better than eased keyframes.
5. **SVG is an animation medium**. Stroke-dashoffset draws, path morphing, bezier point repositioning — SVG enables unique effects CSS cannot.
6. **Stagger creates rhythm**. Not random delays — deliberate patterns: 40ms SVG, 75ms indicators, 150ms text lines, 200ms grid items.
7. **Accessibility is non-negotiable**. Every winner checks `prefers-reduced-motion`. Use `--motion: 0` multiplier pattern.
8. **Performance via compositor**. Only animate `transform` and `opacity`. Use `will-change` sparingly, remove after animation.
