Drawer
Slides in from its edge over a fading backdrop.
Live demo
The preset here changes the whole site. Slow motion and reduced motion change this stage only.
Frame by frame
Every frame of the movement, on top of each other. Wide gaps are fast. Ghosts past the dashed outline are overshoot. It updates with the preset.
When to use
Side panels, filter sheets, and mobile navigation: a panel that comes in from an edge of the screen. The backdrop fades and the panel slides in from its edge on spring.default. The exit slides it back out with a fast tween, so closing never feels slow.
Slide from the edge the panel lives on. On a bouncy preset the panel overshoots its resting place, so let it run past the screen edge (or put a strip of its color there). Otherwise the overshoot opens a gap. Move focus into the panel at once, and keep it there until the panel closes. This site's mobile menu uses this recipe.
Recipe
Side panels and mobile navigation. The backdrop fades in. The panel slides in from its edge. Exit slides it back out, faster.
| State | Property | Token | Now |
|---|---|---|---|
| initial | opacity | literal | 0 |
| slide | literal | 0 | |
| animate | opacity | literal | 1 |
| slide | literal | 1 | |
| exit | opacity | literal | 0 |
| slide | literal | 0 | |
| transition | Movement (spring) | {spring.default} | stiffness 511 · damping 40 |
| transition | Fade duration | {duration.base} | 188ms |
| transition | Fade easing | {easing.enter} | cubic-bezier(0, 0, 0, 1) |
| transition | Exit duration | {duration.fast} | 132ms |
| transition | Exit easing | {easing.exit} | cubic-bezier(0.3, 0, 1, 1) |
Tokens used
spring.default stiffness 511 · damping 40duration.base 188mseasing.enter cubic-bezier(0, 0, 0, 1)duration.fast 132mseasing.exit cubic-bezier(0.3, 0, 1, 1)
Code
/* drawer: Side panels and mobile navigation. The backdrop fades in. The panel slides in from its edge. Exit slides it back out, faster.
Use: .motif-drawer-backdrop and .motif-drawer-panel (right edge; add data-side="left" for the left edge).
They enter when mounted. To exit, set data-state="closed" and unmount after the transition.
Bouncy presets overshoot: let the panel run past its edge, so the overshoot never opens a gap. */
.motif-drawer-backdrop {
transition: opacity var(--motif-duration-base) var(--motif-ease-enter);
}
.motif-drawer-panel {
transition: transform var(--motif-spring-default-duration) var(--motif-spring-default);
}
@starting-style {
.motif-drawer-backdrop {
opacity: 0;
}
}
@starting-style {
.motif-drawer-panel {
transform: translateX(100%);
}
}
@starting-style {
.motif-drawer-panel[data-side="left"] {
transform: translateX(-100%);
}
}
.motif-drawer-backdrop[data-state="closed"] {
opacity: 0;
transition: opacity var(--motif-duration-fast) var(--motif-ease-exit);
}
.motif-drawer-panel[data-state="closed"] {
transform: translateX(100%);
transition: transform var(--motif-duration-fast) var(--motif-ease-exit);
}
.motif-drawer-panel[data-side="left"][data-state="closed"] {
transform: translateX(-100%);
}
@media (prefers-reduced-motion: reduce) {
/* drawer: the panel does not slide. It appears in place and fades. */
.motif-drawer-panel,
.motif-drawer-panel[data-state],
.motif-drawer-panel[data-side][data-state] {
transform: none;
transition: opacity var(--motif-duration-fast) var(--motif-ease-standard);
}
@starting-style {
.motif-drawer-panel {
opacity: 0;
}
}
.motif-drawer-panel[data-state="closed"] {
opacity: 0;
}
}
Reduced motion
- No slide. The panel appears in place and fades with the backdrop. Focus still moves into the drawer at once.
- Fades take 132ms (
duration.fast), so the state change stays visible. - Turn on the Reduced motion box under the demo to preview it, or set your system to reduce motion.