View Transition API
If you are reading this on any browser besides Firefox (Firefox is my browser of choice) then you may be surprised there isn't any JS handling page transitions. If you click on my name at the top of this article you'll see this page slide out to the left and the homepage slide in behind it. You just navigated to a new page. Not like in the SPA way, well like in the SPA way, but only visually.
This site uses the view transition API to
animate page loads. Using CSS you can define a transition out and a transition in animation for any element on
the page. I have two. One is in my styles.css file that enables view transitions
and
handles the slide left of the articles on navigation.
/* Enables view transitions on this page */
/* Must also nbe included on the navigating page */
@view-transition {
navigation: auto;
}
/* Removes transitions for those that prefer reduced motion */
@media (prefers-reduced-motion: reduce) {
@view-transition {
navigation: none;
}
}
@keyframes slideOutLeft {
from {
transform: translateX(0%);
}
to {
transform: translateX(-100%);
}
}
@keyframes slideInLeft {
from {
transform: translateX(100%);
}
to {
transform: translateX(0%);
}
}
::view-transition-group(root) {
animation-duration: .25s;
animation-timing-function: ease-in-out;
}
::view-transition-old(root) {
animation-name: slideOutLeft;
}
::view-transition-new(root) {
animation-name: slideInLeft;
}
The styles.css file is loaded on every page and contains the base level element
styles. So every page will slide left on navigation unless overridden. If you navigate back to an article
you'll notice that they slide up instead of left. This is because articles contain an additional file, article-animation.css that overrides the base slide left animation with a slide up
animation.
@keyframes slideOutUp {
from {
transform: translateY(0%);
}
to {
transform: translateY(-100%);
}
}
@keyframes slideInUp {
from {
transform: translateY(100%);
}
to {
transform: translateY(0%);
}
}
::view-transition-old(root) {
animation-name: slideOutUp;
}
::view-transition-new(root) {
animation-name: slideInUp;
}
On this page we override the slide left animations with the slide up animations yet if I click a link back to the homepage the article slides left. This, to me, is the trickiest part of the view transition API.
The view transition API works by taking a snapshop of the animated element and keeping that element rendered
on the DOM when the new page loads. In both of our examples the element we reference is root which refers to the entire DOM. So when you navigate back to the homepage the
article DOM remains rendered, but the only view transition CSS code remaining is the slide left one.
The suffixes -old and -new refer to the old and new
DOMs. Or specifically in this case, ::view-transition-old(root) in styles.css refers to the article DOM that is still rendered when the homepage loads.
The article DOM and the homepage then animate at the same time giving the appearance that the new page is
sliding in.
In reality you just followed a link like you would on any website. MDN (ironically) has some great docs on multipage app view transitions if you are interested in learning more.