Switch
The active indicator slides. Panel content crossfades.
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
Tabs and segmented controls: one active option out of several. The indicator slides to the new tab on spring.default. The panel content crossfades with a small distance.sm shift in the direction of travel.
Keep aria-selected on the active tab.
Recipe
Tabs and segmented controls. The active indicator slides. Panel content crossfades with a distance.sm shift.
| State | Property | Token | Now |
|---|---|---|---|
| initial | opacity | literal | 0 |
| x | {distance.sm} | 5 | |
| animate | opacity | literal | 1 |
| x | literal | 0 | |
| exit | opacity | literal | 0 |
| x | {distance.sm} | 5 | |
| indicator | progress | literal | 1 |
| transition | Movement (spring) | {spring.default} | stiffness 511 · damping 40 |
| transition | Fade duration | {duration.fast} | 132ms |
| 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.fast 132mseasing.enter cubic-bezier(0, 0, 0, 1)easing.exit cubic-bezier(0.3, 0, 1, 1)distance.sm 5px
Code
/* switch: Tabs and segmented controls. The active indicator slides. Panel content crossfades with a distance.sm shift.
Use: .motif-switch-indicator (set its transform and width to the active tab from JS),
.motif-switch-panel on the panel content (re-mount it on tab change). */
.motif-switch-indicator {
transition:
transform var(--motif-spring-default-duration) var(--motif-spring-default),
width var(--motif-spring-default-duration) var(--motif-spring-default);
}
.motif-switch-panel {
transition:
opacity var(--motif-duration-fast) var(--motif-ease-enter),
transform var(--motif-spring-default-duration) var(--motif-spring-default);
}
@starting-style {
.motif-switch-panel {
opacity: 0;
transform: translateX(var(--motif-distance-sm));
}
}
/* Reduced motion: the variable overrides at the end of motif.css set
travel to 0, scale to 1, and blur to 0, so this recipe needs no extra rule. */
Reduced motion
- The indicator jumps to the active tab. The panel crossfades with no shift.
- 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.