Premise
Since version 8, Turbo has built in support for the View Transitions API. Once you get used to their semantics, you can use them to drive powerful animations that give your application that native touch.
In this exercise we will use them to create a swiper-like look and feel when paging through an image gallery.
Starting Point
First, a caveat: It seems like Stackblitz’s sandbox is interfering with the loading of JavaScript via Importmaps. That’s why you might see some odd behavior when implementing this, such as view transitions intermittently not working. I can assure you that I’ve put this to practice in a production application without these flaws.
Let’s look at what we have, though. There are four simple HTML pages, each containing an image from https://picsum.photos along with “previous” and “next” links for navigation through the collection:
https://stackblitz.com/edit/turbo-drive-swiper?file=index.html,page2.html,page3.html,page4.html
For the card containing the image and caption, we have configured a custom view transition named swiper
:
https://stackblitz.com/edit/turbo-drive-swiper?file=view-transitions.css%3AL2
Furthermore, from line 32 on, we have defined four custom animations for swiping the old card out to the left or right, and swiping the new one in from the left or right:
https://stackblitz.com/edit/turbo-drive-swiper?file=view-transitions.css%3AL32
The core of the CSS logic is when we apply those animations to the ::view-transition-old
and ::view-transition-new
snapshots. Depending on a data-direction
attribute (either prev
or next
) that’s attached to the html
root element, we utilize animations to the left or right:
https://stackblitz.com/edit/turbo-drive-swiper?file=view-transitions.css%3AL7
Challenge
You might have noticed that the navigation links have an aria-label
of either Previous
or Next
.
Use a render interception to detect which link was clicked and add the respective data-direction
attribute to the html
root:
Here’s a sneak peek at the result again:
Caveat
Because the turbo:before-render
event unsurprisingly contains no reference to the link being clicked, you have to store this initiator element in a temporary variable in the turbo:click
event. Just make sure you clean up before resuming rendering!
Use the turbo:load
event to remove the data-direction
attribute from <html>
again, so you don’t end up caching it inadvertently.