Skip to content

Search pages

Jump to any page on the site.

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.

24 frames383 ms · drawn 4.0×
24 frames at 60 fps. Settles in 383 ms, overshoots 0.3%.

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.

States of the switch recipe
StatePropertyTokenNow
initialopacityliteral0
x{distance.sm}5
animateopacityliteral1
xliteral0
exitopacityliteral0
x{distance.sm}5
indicatorprogressliteral1
transitionMovement (spring){spring.default}stiffness 511 · damping 40
transitionFade duration{duration.fast}132ms
transitionFade easing{easing.enter}cubic-bezier(0, 0, 0, 1)
transitionExit duration{duration.fast}132ms
transitionExit easing{easing.exit}cubic-bezier(0.3, 0, 1, 1)

Tokens used

  • spring.default stiffness 511 · damping 40
  • duration.fast 132ms
  • easing.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.