|
| 1 | +--- |
| 2 | +description: Animate page navigations with the View Transitions API |
| 3 | +--- |
| 4 | + |
| 5 | +Fresh integrates the browser's native |
| 6 | +[View Transitions API](https://developer.mozilla.org/en-US/docs/Web/API/View_Transition_API) |
| 7 | +into its [partials](/docs/advanced/partials) system. When enabled, DOM updates |
| 8 | +during client-side navigation are wrapped in `document.startViewTransition()`, |
| 9 | +giving you smooth animated transitions between pages with zero JavaScript |
| 10 | +animation code. |
| 11 | + |
| 12 | +This is progressive enhancement -- if the browser doesn't support the View |
| 13 | +Transitions API, partials work exactly as before with no animation. |
| 14 | + |
| 15 | +## Enabling view transitions |
| 16 | + |
| 17 | +Add the `f-view-transition` attribute alongside `f-client-nav`: |
| 18 | + |
| 19 | +```tsx routes/_app.tsx |
| 20 | +export default function App({ Component }: PageProps) { |
| 21 | + return ( |
| 22 | + <html lang="en"> |
| 23 | + <head> |
| 24 | + <meta charset="utf-8" /> |
| 25 | + </head> |
| 26 | + <body f-client-nav f-view-transition> |
| 27 | + <Component /> |
| 28 | + </body> |
| 29 | + </html> |
| 30 | + ); |
| 31 | +} |
| 32 | +``` |
| 33 | + |
| 34 | +All partial navigations (link clicks, form submissions, back/forward) will now |
| 35 | +be animated. |
| 36 | + |
| 37 | +## Customizing animations |
| 38 | + |
| 39 | +The default view transition is a cross-fade. Customize it with standard CSS |
| 40 | +using the `::view-transition-old` and `::view-transition-new` pseudo-elements: |
| 41 | + |
| 42 | +```css static/styles.css |
| 43 | +::view-transition-old(root) { |
| 44 | + animation: fade-out 0.2s ease-in; |
| 45 | +} |
| 46 | +::view-transition-new(root) { |
| 47 | + animation: fade-in 0.2s ease-out; |
| 48 | +} |
| 49 | +``` |
| 50 | + |
| 51 | +### Per-element transitions |
| 52 | + |
| 53 | +Assign a `view-transition-name` in CSS to animate specific elements |
| 54 | +independently from the rest of the page: |
| 55 | + |
| 56 | +```css static/styles.css |
| 57 | +.sidebar { |
| 58 | + view-transition-name: sidebar; |
| 59 | +} |
| 60 | +.main-content { |
| 61 | + view-transition-name: content; |
| 62 | +} |
| 63 | +``` |
| 64 | + |
| 65 | +Then target those named transitions: |
| 66 | + |
| 67 | +```css static/styles.css |
| 68 | +/* Sidebar stays in place */ |
| 69 | +::view-transition-old(sidebar), |
| 70 | +::view-transition-new(sidebar) { |
| 71 | + animation: none; |
| 72 | +} |
| 73 | + |
| 74 | +/* Content slides */ |
| 75 | +::view-transition-old(content) { |
| 76 | + animation: slide-out-left 0.3s ease-in; |
| 77 | +} |
| 78 | +::view-transition-new(content) { |
| 79 | + animation: slide-in-right 0.3s ease-out; |
| 80 | +} |
| 81 | +``` |
| 82 | + |
| 83 | +This is useful for keeping persistent UI (navigation bars, sidebars) stable |
| 84 | +while animating the main content area. |
| 85 | + |
| 86 | +### Direction-aware animations |
| 87 | + |
| 88 | +Since Fresh tracks navigation history, you can use CSS custom properties or |
| 89 | +classes to apply different animations for forward vs. backward navigation. The |
| 90 | +View Transitions API captures the old and new states automatically -- combine |
| 91 | +this with `::view-transition-group` to create directional slide effects. |
| 92 | + |
| 93 | +## Disabling view transitions |
| 94 | + |
| 95 | +Disable view transitions on a subtree by setting `f-view-transition={false}`: |
| 96 | + |
| 97 | +```tsx |
| 98 | +<body f-client-nav f-view-transition={false}> |
| 99 | +``` |
| 100 | + |
| 101 | +## Browser support |
| 102 | + |
| 103 | +View Transitions are supported in Chrome 111+, Edge 111+, and Safari 18+. |
| 104 | +Firefox support is in development. On unsupported browsers, navigations work |
| 105 | +normally without animation -- no polyfill needed. |
0 commit comments