Pure
Structure

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