Animation
A guide to animating Base UI components.
Base UI components can be animated using CSS transitions, CSS animations, or JavaScript animation libraries. Each component provides a number of data attributes to target its states, as well as a few attributes specifically for animation.
CSS transitions
Use the following Base UI attributes for creating transitions when a component becomes visible or hidden:
[data-starting-style]corresponds to the initial style to transition from.[data-ending-style]corresponds to the final style to transition to.
Transitions are recommended over CSS animations, because a transition can be smoothly cancelled midway. For example, if the user closes a popup before it finishes opening, with CSS transitions it will smoothly animate to its closed state without any abrupt changes.
CSS animations
Use the following Base UI attributes for creating CSS animations when a component becomes visible or hidden:
[data-open]corresponds to the style applied when a component becomes visible.[data-closed]corresponds to the style applied before a component becomes hidden.
JavaScript animations
JavaScript animation libraries such as Motion need the popup to stay rendered while its exit animation plays, and Base UI to know when that animation is over.
When a popup closes, open becomes false right away, but the popup stays rendered in a closing phase until its closing animation finishes.
Base UI detects animations on the popup element. CSS animations are always detected, and so are Motion animations that include opacity.
Once the animation ends, the popup is removed from the DOM, or hidden if the <Portal> has keepMounted, and onOpenChangeComplete(false) fires.
This leaves two choices:
- Where does the popup go when closed? Removed from the DOM with
<AnimatePresence>, or kept in the DOM withkeepMounted. - Who ends the closing phase? Base UI, when it can detect the animation, or you, with manual unmounting.
The examples below animate opacity, so Base UI ends the closing phase on its own.
Animating components unmounted from DOM when closed with Motion
Most popup components like Popover, Dialog, Tooltip, and Menu are removed from the DOM when they are closed by default. To animate them with Motion:
- Make the component controlled with the
openprop so<AnimatePresence>can see the state as a child - Specify
keepMountedon the<Portal>part so Base UI doesn’t remove it before the exit animation has played - Use the
renderprop to compose the<Popup>withmotion.div
Animating components kept in DOM when closed with Motion
Components that specify keepMounted remain rendered in the DOM when they are closed. These elements need a different approach to be animated with Motion:
- Use the
renderprop to compose the<Popup>withmotion.div - Animate the properties based on the
openstate, avoiding<AnimatePresence>
Animating Select component with Motion
The Select component is removed from the DOM until its first interaction and stays in the DOM after that. To animate it with Motion, a mix of the two previous approaches is needed.
Manual unmounting
Use this when Base UI can’t detect your closing animation, for example when it doesn’t animate opacity, or when the popup should stay in its closing phase until something other than an animation completes.
Call eventDetails.preventUnmountOnClose() in onOpenChange when the component closes, then call unmount() on the actionsRef passed to the <Root> once the animation finishes.
This ends the closing phase, and onOpenChangeComplete(false) fires. Whether the popup leaves the DOM is still decided by keepMounted.