Transition patterns
Transition patterns define HOW content moves between states in your UI. Each pattern conveys a specific spatial relationship to the user, helping them understand where content came from and where it went.
The 5 core patterns
| Pattern | Spatial message | When to use |
|---|---|---|
| Container Transform | "This IS that" | Shared element morphs between states |
| Shared Axis | "This is NEXT TO that" | Switching between peer content |
| Drill Forward/Back | "This is INSIDE that" | Navigating up/down hierarchy |
| Layer | "This is ON TOP of that" | Overlays, modals, dropdowns |
| Fade | "This REPLACES that" | In-place content changes |
Pattern selection decision tree
When choosing a transition pattern, ask these questions in order:
- Is there a shared visual element that should morph?
- YES → Container Transform
- NO → continue
- Is content appearing ON TOP (overlay)?
- YES → Layer
- NO → continue
- Is this navigation between hierarchical levels?
- Going deeper (parent → child) → Drill Forward
- Going back (child → parent) → Drill Back
- NO → continue
- Is this switching between peer content (same level)?
- YES → Shared Axis
- NO → continue
- Is content just changing in place?
- YES → Fade
Container Transform
Spatial message: "This IS that"
The user perceives that one element has transformed into another, maintaining visual identity and continuity.
When to use
- Card thumbnail expanding to full image
- List avatar morphing to profile header
- Compact view expanding to detailed view
- FAB transforming into a dialog
When to avoid
- No shared visual element exists between states
- Elements are semantically different (not the same "thing")
Implementation
// Enter: element grows from origin
className="origin-center scale-95 opacity-0"
// Active: element at full size
className="origin-center scale-100 opacity-100"
// Duration: normal (300ms), Easing: out-quart
Shared Axis
Spatial message: "This is NEXT TO that"
Content slides horizontally or vertically, indicating sibling/peer relationship at the same hierarchical level.
When to use
- Tab switching
- Carousel / slider navigation
- Segmented control switching
- Pagination
- Onboarding step progression
When to avoid
- Hierarchical navigation (use Drill)
- Overlay content (use Layer)
Direction rule
- Going forward / next: content slides LEFT
- Going back / previous: content slides RIGHT
Implementation
// Enter from right (forward navigation)
className="translate-x-4 opacity-0"
// Exit to left
className="-translate-x-4 opacity-0"
// Duration: quick (200ms), Easing: out-quart
Drill Forward / Back
Spatial message: "This is INSIDE that"
Navigating deeper into or back up the information hierarchy. Like drilling into a folder structure.
When to use Drill Forward
- List item to detail view
- Parent to child navigation
- Breadcrumb drilling down
- Folder to contents
When to use Drill Back
- Detail view back to list
- Back button pressed
- Breadcrumb clicking parent
Key indicators
- Drill Forward: breadcrumbs would ADD a level, URL path gets longer
- Drill Back: breadcrumbs would REMOVE a level, URL path gets shorter
Implementation
// Drill Forward — new content from right
enterClass="translate-x-full opacity-0"
exitClass="-translate-x-1/3 opacity-50"
// Drill Back — parent returns from left
enterClass="-translate-x-1/3 opacity-50"
exitClass="translate-x-full opacity-0"
// Duration: normal (300ms), Easing: out-expo
Layer
Spatial message: "This is ON TOP of that"
Content appears above existing content. The underlying content remains visible (often dimmed) to maintain context.
When to use
- Modal dialogs
- Dropdown menus
- Tooltips and popovers
- Command palette (Cmd+K)
- Bottom sheets
- Context menus
Key characteristics
- Backdrop / scrim present
- Dismissible by clicking outside
- Escape key closes it
- Does NOT change URL
- Focus should be trapped inside
When to avoid
- Full page navigation (use Drill)
- Content replacement (use Fade)
Implementation
// Enter: scale up and fade in
className="scale-95 opacity-0"
// Active: full size and visible
className="scale-100 opacity-100"
// Duration: quick (200ms), Easing: out-quart
Fade
Spatial message: "This REPLACES that"
Content crossfades in place with no spatial movement. Used when there's no meaningful spatial relationship.
When to use
- Loading state to content
- Skeleton to real data
- Image swap
- Toast notifications
- State changes in place
- Error to success state
When to avoid
- Navigation that implies direction (use Drill or Shared Axis)
- When spatial relationship matters
Implementation
// Enter and exit are just opacity
enterClass="opacity-0"
exitClass="opacity-100"
// Duration: quick (200ms), Easing: out-quart
// Keep it subtle — fade should feel almost instant
Common scenarios
| Scenario | Pattern | Notes |
|---|---|---|
| Open modal from button | Layer | Standard overlay |
| Open modal from card | Container Transform | If card morphs into modal |
| Switch tabs | Shared Axis | Horizontal slide |
| List item → detail | Drill Forward | Push from right |
| Back button pressed | Drill Back | Return from left |
| Skeleton → content | Fade | In-place replacement |
| Show dropdown | Layer | Overlay near trigger |
| Carousel next | Shared Axis | Slide left |
| Toast appear | Fade | No spatial origin |
Accessibility
Always respect prefers-reduced-motion:
@media (prefers-reduced-motion: reduce) {
* {
transition-duration: 0.01ms !important;
}
}
For essential animations that convey meaning (like drill direction), consider showing them but making them instant rather than removing them entirely.
FAQ
How do I choose between Container Transform and Drill?
- Container Transform: a specific element (thumbnail, avatar, card) morphs into the destination
- Drill: the whole view transitions, no specific element continuity
If you can point to "this element becomes that element," use Container Transform. If it's general navigation, use Drill.
Should dropdowns use Layer or Fade?
Layer. Dropdowns are overlays that appear on top of content. Fade is for in-place content replacement where there's no "on top of" relationship.
What duration should I use?
- Quick (200ms): most UI feedback (dropdowns, tooltips, tabs)
- Normal (300ms): significant transitions (modals, page navigation)
Use the motion tokens: duration-quick, duration-normal.
Can I combine patterns?
Generally no. Each transition should use one pattern. The pattern choice communicates spatial meaning; mixing patterns confuses users about the relationship between states.
The exception is Container Transform, which may incorporate scaling/opacity similar to other patterns, but the differentiator is the shared element morph.