~
🌟 This post is about View Transitions. If you are not familiar with the basics of it, check out this 30-min talk of mine to get up to speed.
~
When using View Transitions you’ll notice the page becomes unresponsive to clicks while a View Transition is running.
Take the following example that allows you to manipulate a list of cards. The addition and removal of cards is animated using View Transitions. What you will notice, is that you can’t rage click the +
button to add a lot of cards: the button does not respond to clicks while there is an ongoing View Transition:
See the Pen
Add/Remove Cards with View Transitions (using view-transition-class ) by Bramus (@bramus)
on CodePen.
This happens because of the ::view-transition
pseudo element – the one that contains all animated snapshots – gets overlayed on top of the document and captures all the clicks.
::view-transition /* 👈 Captures all the clicks! */
└─ ::view-transition-group(root)
└─ ::view-transition-image-pair(root)
├─ ::view-transition-old(root)
└─ ::view-transition-new(root)
To make clicks fall through to the document underneath, you need to disable pointer events on the pseudo. In CSS it’s as easy as including the following rule:
::view-transition {
pointer-events: none;
}
The embed below has the snippet included. As you see, you can rapidly click the +
button multiple times in succession:
See the Pen
Add/Remove Cards with View Transitions (using view-transition-class ) by Bramus (@bramus)
on CodePen.
~
One thing I didn’t mention with the demo above is that there’s an extra thing that I did: I prevented the :root
element from being captured as part of the View Transition.
:root {
view-transition-name: none;
}
The reason for doing so is because snapshots that are being animated do not respond to hit testing, as per spec:
Elements participating in a transition need to skip painting in their DOM location because their image is painted in the corresponding ::view-transition-new() pseudo-element instead. Similarly, hit-testing is skipped because the element’s DOM location does not correspond to where its contents are rendered.
By not capturing the :root
, we leave room for click-interactivity, as clicks then can fall through to the document – as long as you don’t click any of the other snapshots.
And oh, in case you are wondering why you can’t undo this unresponsiveness on the groups, it is for very good reasons:
- While being animated, the location on screen might not match the actual element’s location.
- What should be done when two different elements are transitioning from the one to the other: you could see the old element screen but then clicks would have to go to the new one?
~
🔥 Like what you see? Want to stay in the loop? Here's how:
Bramus, is there any reason why `pointer-events: none;` was not the default styling for View Transitions from the get-go? It seems like this would be the more desirable approach, but maybe I’m missing something. 🤷🏻♂️
Those discussions predate my time on the feature, so I don’t really know. I’m sure Jake Archibald is the right person to ask this.