--- title: version: experimental --- **This API is experimental and is not available in a stable version of React yet.** You can try it by upgrading React packages to the most recent experimental version: - `react@experimental` - `react-dom@experimental` - `eslint-plugin-react-hooks@experimental` Experimental versions of React may contain bugs. Don't use them in production. `` lets you animate elements that update inside a Transition. ```js import {unstable_ViewTransition as ViewTransition} from 'react';
...
```
--- ## Reference {/*reference*/} ### `` {/*viewtransition*/} Wrap elements in `` to animate them when they update inside a [Transition](/reference/react/useTransition). React uses the following heuristics to determine if a View Transition activates for an animation: - `enter`: If a `ViewTransition` itself gets inserted in this Transition, then this will activate. - `exit`: If a `ViewTransition` itself gets deleted in this Transition, then this will activate. - `update`: If a `ViewTransition` has any DOM mutations inside it that React is doing (such as a prop changing) or if the `ViewTransition` boundary itself changes size or position due to an immediate sibling. If there are nested` ViewTransition` then the mutation applies to them and not the parent. - `share`: If a named `ViewTransition` is inside a deleted subtree and another named `ViewTransition` with the same name is part of an inserted subtree in the same Transition, they form a Shared Element Transition, and it animates from the deleted one to the inserted one. By default, `` animates with a smooth cross-fade (the browser default view transition). You can customize the animation by providing a [View Transition Class](#view-transition-class) to the `` component. You can customize animations for each kind of trigger (see [Styling View Transitions](#styling-view-transitions)). #### How does `` work? {/*how-does-viewtransition-work*/} Under the hood, React applies `view-transition-name` to inline styles of the nearest DOM node nested inside the `` component. If there are multiple sibling DOM nodes like `
` then React adds a suffix to the name to make each unique but conceptually they're part of the same one. React doesn't apply these eagerly but only at the time that boundary should participate in an animation. React automatically calls `startViewTransition` itself behind the scenes so you should never do that yourself. In fact, if you have something else on the page running a ViewTransition React will interrupt it. So it's recommended that you use React itself to coordinate these. If you had other ways of trigger ViewTransitions in the past, we recommend that you migrate to the built-in way. If there are other React ViewTransitions already running then React will wait for them to finish before starting the next one. However, importantly if there are multiple updates happening while the first one is running, those will all be batched into one. If you start A->B. Then in the meantime you get an update to go to C and then D. When the first A->B animation finishes the next one will animate from B->D. The `getSnapshotBeforeUpdate` life-cycle will be called before `startViewTransition` and some `view-transition-name` will update at the same time. Then React calls `startViewTransition`. Inside the `updateCallback`, React will: - Apply its mutations to the DOM and invoke useInsertionEffects. - Wait for fonts to load. - Call componentDidMount, componentDidUpdate, useLayoutEffect and refs. - Wait for any pending Navigation to finish. - Then React will measure any changes to the layout to see which boundaries will need to animate. After the ready Promise of the `startViewTransition` is resolved, React will then revert the `view-transition-name`. Then React will invoke the `onEnter`, `onExit`, `onUpdate` and `onShare` callbacks to allow for manual programmatic control over the Animations. This will be after the built-in default ones have already been computed. If a `flushSync` happens to get in the middle of this sequence, then React will skip the Transition since it relies on being able to complete synchronously. After the finished Promise of the `startViewTransition` is resolved, React will then invoke `useEffect`. This prevents those from interfering with the performance of the Animation. However, this is not a guarantee because if another `setState` happens while the Animation is running it'll still have to invoke the `useEffect` earlier to preserve the sequential guarantees. #### Props {/*props*/} By default, `` animates with a smooth cross-fade. You can customize the animation, or specify a shared element transition, with these props: * **optional** `enter`: A string or object. The [View Transition Class](#view-transition-class) to apply when enter is activated. * **optional** `exit`: A string or object. The [View Transition Class](#view-transition-class) to apply when exit is activated. * **optional** `update`: A string or object. The [View Transition Class](#view-transition-class) to apply when an update is activated. * **optional** `share`: A string or object. The [View Transition Class](#view-transition-class) to apply when a shared element is activated. * **optional** `default`: A string or object. The [View Transition Class](#view-transition-class) used when no other matching activation prop is found. * **optional** `name`: A string or object. The name of the View Transition used for shared element transitions. If not provided, React will use a unique name for each View Transition to prevent unexpected animations. #### Callback {/*events*/} These callbacks allow you to adjust the animation imperatively using the [animate](https://developer.mozilla.org/en-US/docs/Web/API/Element/animate) APIs: * **optional** `onEnter`: A function. React calls `onEnter` after an "enter" animation. * **optional** `onExit`: A function. React calls `onExit` after an "exit" animation. * **optional** `onShare`: A function. React calls `onShare` after a "share" animation. * **optional** `onUpdate`: A function. React calls `onUpdate` after an "update" animation. Each callback receives as arguments: - `element`: The DOM element that was animated. - `types`: The [Transition Types](/reference/react/addTransitionType) included in the animation. ### View Transition Class {/*view-transition-class*/} The View Transition Class is the CSS class name(s) applied by React during the transition when the ViewTransition activates. It can be a string or an object. - `string`: the `class` added on the child elements when activated. If `'none'` is provided, no class will be added. - `object`: the class added on the child elements will be the key matching View Transition type added with `addTransitionType`. The object can also specify a `default` to use if no matching type is found. The value `'none'` can be used to prevent a View Transition from activating for a specific trigger. ### Styling View Transitions {/*styling-view-transitions*/} In many early examples of View Transitions around the web, you'll have seen using a [`view-transition-name`](https://developer.mozilla.org/en-US/docs/Web/CSS/view-transition-name) and then style it using `::view-transition-...(my-name)` selectors. We don't recommend that for styling. Instead, we normally recommend using a View Transition Class instead. To customize the animation for a `` you can provide a View Transition Class to one of the activation props. The View Transition Class is a CSS class name that React applies to the child elements when the ViewTransition activates. For example, to customize an "enter" animation, provide a class name to the `enter` prop: ```js ``` When the `` activates an "enter" animation, React will add the class name `slide-in`. Then you can refer to this class using [view transition pseudo selectors](https://developer.mozilla.org/en-US/docs/Web/API/View_Transition_API#pseudo-elements) to build reusable animations: ```css ::view-transition-group(.slide-in) { } ::view-transition-old(.slide-in) { } ::view-transition-new(.slide-in) { } ``` In the future, CSS libraries may add built-in animations using View Transition Classes to make this easier to use. #### Caveats {/*caveats*/} - By default, `setState` updates immediately and does not activate ``, only updates wrapped in a [Transition](/reference/react/useTransition). You can also use [``](/reference/react/Suspense) to opt-in to a Transition to [reveal content](/reference/react/Suspense#revealing-content-together-at-once). - `` creates an image that can be moved around, scaled and cross-faded. Unlike Layout Animations you may have seen in React Native or Motion, this means that not every individual Element inside of it animates its position. This can lead to better performance and a more continuous feeling, smooth animation compared to animating every individual piece. However, it can also lose continuity in things that should be moving by themselves. So you might have to add more `` boundaries manually as a result. - Many users may prefer not having animations on the page. React doesn't automatically disable animations for this case. We recommend that using the `@media (prefers-reduced-motion)` media query to disable animations or tone them down based on user preference. In the future, CSS libraries may have this built-in to their presets. - Currently, `` only works in the DOM. We're working on adding support for React Native and other platforms. --- ## Usage {/*usage*/} ### Animating an element on enter/exit {/*animating-an-element-on-enter*/} Enter/Exit Transitions trigger when a `` is added or removed by a component in a transition: ```js function Child() { return Hi } function Parent() { const [show, setShow] = useState(); if (show) { return ; } return null; } ``` When `setShow` is called, `show` switches to `true` and the `Child` component is rendered. When `setShow` is called inside `startTransition`, and `Child` renders a `ViewTransition` before any other DOM nodes, an `enter` animation is triggered. When `show` switches back to `false`, an `exit` animation is triggered. ```js src/Video.js hidden function Thumbnail({ video, children }) { return (