Tutorial - Extend with View Transitions
View transitions are a way to control what happens when visitors navigate between pages on your site. Astro’s View Transitions API allows you to add optional navigation features including smooth page transitions and animations, controlling the browser’s history stack of visited pages, and preventing full-page refreshes in order to persist some page elements and state while updating the content displayed.
Get ready to…
- Import and add the
<ViewTransitions />router to a common
- Add event listeners during the navigation process to trigger
<script>s when needed
- Add page transition animations using transition directives
- Opt out of client-side routing for an individual page link
You will need an existing Astro project with a common base layout or
<Head /> component.
This tutorial uses the Build a Blog tutorial’s finished project to demonstrate adding view transitions (client-side routing) to an existing Astro project. You can fork and use that codebase locally, or complete the tutorial in the browser by editing the blog tutorial’s code in StackBlitz.
You can instead follow these steps with your own Astro project, but you will need to adjust the instructions for your codebase.
We recommend using our sample project to complete this short tutorial first. Then, you can use what you have learned to create view transitions in your own project.
Build a Blog Tutorial Code
In the Build a Blog introductory tutorial, you learned about Astro’s built-in file-based routing: any
.mdx file anywhere within the
src/pages/ folder automatically became a new page on your site.
To navigate between these pages, you used the standard HTML
<a> element. For example, to create a link to your About page, you added
<a href="/about/">About</a> to your page header. When a visitor to your site clicked that link, the browser refreshed and loaded a new page with entirely new content.
Full-page navigation vs client-side routing (SPA mode)
When a browser refreshes and loads a new page, there is no continuity between the old page and the new page. During client-side routing, a new page is displayed without a full-page browser refresh
Because each new page does not require a full browser refresh, client-side routing allows you to control page transitions in several ways. Persistent elements, such as a common page header, do not have to be entirely rerendered on the screen. The transition from one page to another can appear much smoother. And, state can be preserved, allowing you to transfer values from one page to the next, or even keep a video playing as your visitors navigate pages!
There are times when you will want or need a full-page browser refresh. For example, when a link takes a visitor to a
Read more about Astro’s view transitions in our guide, or get started with the instructions below to convert a basic blog from
Test your knowledge
Adding view transitions to my astro site…
Which is not a benefit of Astro’s view transitions?
The view transitions router…
Extending the blog tutorial with view transitions
The steps below show you how to extend the final product of the Build a Blog tutorial by adding client-side routing to enhance page transitions.
Upgrade to the latest version of Astro, and upgrade all integrations to their latest versions by running the following commands in your terminal:
<ViewTransitions /> router
Import and add the
<ViewTransitions />component to the
<head>of your page layout.
In the Blog tutorial example, the
<head>element is found in
ViewTransitionsrouter must be first imported into the component’s frontmatter. Then, add the routing component inside the
No other configuration is necessary to enable Astro’s default client-side navigation! Astro will create default page animations based on the similarities between the old and new page, and will also provide fallback behavior for unsupported browsers.
Navigate between pages in your site preview
View your site preview at a large screen size, such as desktop mode. As you move between pages on your site, notice that the old page content appears to fade out as the new page content fades in. Use the view transitions guide to add custom behavior if you are not satisfied with the defaults.
View your site preview at a smaller screen size, and try to use the hamburger menu to navigate between pages. Notice that your menu will no longer work after the first page load.
With view transitions, some scripts may no longer re-run after page navigation like they do with full-page browser refreshes. There are two events during client-side routing that you can listen for, and fire events when they occur:
Make the script controlling the
<Hamburger />mobile menu component available after navigating to a new page.
To make your mobile menu interactive after navigating to a new page, add the following code that listens for the
astro:page-loadevent which runs at the end of page navigation, and in response, runs the existing script to make the hamburger menu function when clicked:
Make the script controlling the theme toggle available after page navigation.
<script>that controls the light/dark theme toggle is located in the
<ThemeIcon />component. For the theme toggle to continue to function on every page, remove the
is:inlineattribute from the script and add the same event listener as in the previous example so that
astro:page-loadevent can trigger your existing function.
Update the existing script tag so that your function runs in response to the
astro:page-loadevent, making your theme toggle interactive after the new page is fully loaded and visible to the user:
Now, the theme toggle is interactive on every page when using the
<ViewTransitions />router, after the page has finished loading.
Check for theme earlier to prevent flashing in dark mode.
The theme toggle works on every page, but its script is loaded at the end of the navigation process, after the new page has fully loaded in the browser. There may be a flash of the light theme version of the site before this theme toggle script runs and checks which theme it should use on the page.
To check for, and if necessary set, dark mode earlier in the navigation process, create a function that will run in response to the
astro:after-swapevent. The following function to check the browser’s
localStoragefor dark theme will run immediately after the new page has replaced the old page, before the DOM elements are painted to the screen.
Add this new script to the
<ThemeIcon />component, in addition to the script that controls the theme toggle.
Now, every page change that uses the
<ViewTransitions />router for client-side navigation (and therefore access to the
astro:after-swapevent) will be able to detect
theme: darkfrom the browser’s
localStorageand update the current page accordingly before the page is rendered for the viewer.
Test your knowledge
Which is the correct order of events after a visitor clicks a link to go to a new page during client-side navigation?
Customize Transition animations
Change the default
fadeanimation to a
slidefor the page title.
With view transitions enabled, you currently have a small fade in and out set for all page transition animations. Astro also provides a built-in
slideanimation. To change the type of animation for a single element, add the
For example, to make the page titles slide in instead of fade in, add
<h1>element in the BaseLayout:
In your browser preview, you will now see the page titles slide on to the screen, while other elements such as the body text continues to fade in and out.
Try it yourself - Make the navigation links slide in
Add an animation directive to make the
Navigation.astrocontaining all the header links slide in on page navigation, following the same steps as above.
Show me the code.
Check your browser preview and now both the page title and the header links will slide in on every page navigation.
Add a longer fade-in on your blog post descriptions.
You can also customize Astro’s built-in animations by importing them, then providing any CSS animation properties.
For example, to make the description fade in slowly when you navigate to a blog post, import the
fadeanimation in your layout for Markdown blog posts. Then, add the transition directive for Astro’s
fadewith a duration of
Navigate to any blog post in your browser preview, and you will see the description fade in slower than the rest of the text.
Force a full browser reload for some links
Prevent client-side routing and instead require the browser to reload when navigating to your About page.
Sometimes you will want a full browser reload when visitors click a certain link. For example, you may be linking to a page that does not also use the
<ViewTransitions />router, or to a file directly such as a
To make it so that your browser refreshes every time you click the navigation link to go to your About page, add the
data-astro-reloadattribute to the
<a>tag in your
<Navigation/>component. This will override the
<ViewTransitions />router entirely, and any of the view transition animations, for this one link.
Now, when you click the navigation link to your About page, no animations will occur. The page links and title will not slide in, and the page content will not fade in when you navigate to your About page using this link.
Add a link to your About page from your author name in your Markdown layout for blog posts
data-astro-reloadonly triggers a full browser refresh when going to a new page from the link it is added to. It does not control all instances of navigating to your About page.
<MarkdownPostLayout />component, add a link to your About page on your author name:
If you visit any blog post in your browser preview, and then click on the linked author name to be taken to the About page, what does the page navigation look like?
When a visitor clicks a link to the About page from an individual blog post, the page title and header navigation links because
There is still so much more to explore! See our full View Transitions Guide for more things you can do with view transitions.
For the full example of the blog tutorial using view transitions, see the View Transitions branch of the tutorial repo.Learn