I’ll be honest and say that the View Transition API intimidates me more than a smidge. There are plenty of tutorials with the most impressive demos showing how we can animate the transition between two pages, and they usually start with the simplest of all examples.
@view-transition {
navigation: auto;
}
That’s usually where the simplicity ends and the tutorials venture deep into JavaScript territory. There’s nothing wrong with that, of course, except that it’s a mental leap for someone like me who learns by building up rather than leaping through. So, I was darned inspired when I saw Uncle Dave and Jim Neilsen trading tips on a super practical transition: post titles.
You can see how it works on Jim’s site:
This is the perfect sort of toe-dipping experiment I like for trying new things. And it starts with the same little @view-transition
snippet which is used to opt both pages into the View Transitions API: the page we’re on and the page we’re navigating to. From here on out, we can think of those as the “new” page and the “old” page, respectively.
I was able to get the same effect going on my personal blog:
Perfect little exercise for a blog, right? It starts by setting the view-transition-name
on the elements we want to participate in the transition which, in this case, is the post title on the “old” page and the post title on the “new” page.
So, if this is our markup:
<h1 class="post-title">Notes</h1>
<a class="post-link" href="/link-to-post"></a>
…we can give them the same view-transition-name
in CSS:
.post-title { view-transition-name: post-title; }
.post-link { view-transition-name: post-title; }
Dave is quick to point out that we can make sure we respect users who prefer reduced motion and only apply this if their system preferences allow for motion:
@media not (prefers-reduced-motion: reduce) {
.post-title { view-transition-name: post-title; }
.post-link { view-transition-name: post-title; }
}
If those were the only two elements on the page, then this would work fine. But what we have is a list of post links and all of them have to have their own unique view-transition-name
. This is where Jim got a little stuck in his work because how in the heck do you accomplish that when new blog posts are published all the time? Do you have to edit your CSS and come up with a new transition name each and every time you want to post new content? Nah, there’s got to be a better way.
And there is. Or, at least there will be. It’s just not standard yet. Bramus, in fact, wrote about it very recently when discussing Chrome’s work on the attr()
function which will be able to generate a series of unique identifiers in a single declaration. Check out this CSS from the future:
<style>
.card[id] {
view-transition-name: attr(id type(<custom-ident>), none); /* card-1, card-2, card-3, … */
view-transition-class: card;
}
</style>
<div class="cards">
<div class="card" id="card-1"></div>
<div class="card" id="card-2"></div>
<div class="card" id="card-3"></div>
<div class="card" id="card-4"></div>
</div>
Daaaaa-aaaang that is going to be handy! I want it now, darn it! Gotta have to wait not only for Chrome to develop it, but for other browsers to adopt and implement it as well, so who knows when we’ll actually get it. For now, the best bet is to use a little programmatic logic directly in the template. My site runs on WordPress, so I’ve got access to PHP and can generate an inline style that sets the view-transition-name
on both elements.
The post title is in the template for my individual blog posts. That’s the single.php
file in WordPress parlance.
<?php the_title(
'<h1 class="post-single__title" style="view-transition-name: post-' . get_the_id() . '">', '</h1>'
); ?>
The post links are in the template for post archives. That’s typically archive.php
in WordPress:
<?php the_title(
'<h2 class="post-link><a href="' . esc_url( get_permalink() ) .'" rel="bookmark" style="view-transition-name: post-' . get_the_id() . '">', '</a></h2>'
); ?>
See what’s happening there? The view-transition-name
property is set on both transition elements directly inline, using PHP to generate the name based on the post’s assigned ID in WordPress. Another way to do it is to drop a <style>
tag in the template and plop the logic in there. Both are equally icky compared to what attr()
will be able to do in the future, so pick your poison.
The important thing is that now both elements share the same view-transition-name
and that we also have already opted into @view-transition
. With those two ingredients in place, the transition works! We don’t even need to define @keyframes
(but you totally could) because the default transition does all the heavy lifting.
In the same toe-dipping spirit, I caught the latest issue of Modern Web Weekly and love this little sprinkle of view transition on radio inputs:
Notice the JavaScript that is needed to prevent the radio’s default clicking behavior in order to allow the transition to run before the input is checked.
Toe Dipping Into View Transitions originally published on CSS-Tricks, which is part of the DigitalOcean family. You should get the newsletter.