Page Transitions with the View Transition API: Part 2
In part 1 I set up the transitions between article pages but adding more animations brought up some challenges that I will address here.
Challenges
Route specific animation
I wanted a different animation from the list of articles to the article page; specifically morphing the article title from the list page to its new position on the details page. I added a view-transition-name
to both pages. This had the side effect of removing the article title from the animation between article pages. Its seems without completely taking over the entire render process there is no simple way to define an animation for a specific route only.
.article-title {
width: fit-content;
.article-list &:has(a:focus), .article &:not(.has-view-transition-disabled) {
view-transition-name: --article-title;
}
}
::view-transition-new(--article), ::view-transition-new(--article-title):only-child {
animation-name: fade-in, slide-from-right;
}
I settled on a compromise using JS to add a class .has-view-transition-disabled
to the article title on the article page using the Navigation API. This essentially makes the article title transition an only child when navigating between article pages. I can then add the same animation as the articles themselves.
if (toPath !== '/blog/') {
document.querySelector(`.page--article .article-title`).classList.add('has-view-transition-disabled');
}
View transition names must be unique
The view-transition-name
need to be unique but this is a problem for list pages which have many article titles. My solution was to target the article title that has a link in focus, thereby making it unique.
Animation scaling
Since the article titles are different scales on the different pages adding width: fit-content;
gets the title to scale properly.
Stacking context
The final challenge concerned the sticky header, the view transitions were animating on top of it. After some research I found the view transitions change the stacking order while animating. You need to add view transitions to these elements outside of the document flow even if you don’t need them to animate.
.header {
view-transition-name: --header;
}
::view-transition-group(--header) {
animation: none;
z-index: 100000;
}
References
- Smooth and simple transitions with the View Transitions API by Jake Archibald
- Getting started with View Transitions on multi-page apps by Dave Rupert
- View transitions and stacking context by Nic Chan
- The View Transitions API And Delightful UI Animations (Part 2) by Adrian Bece