This content originally appeared on Bram.us and was authored by Bramus!
Instead of duplicating an animation on the ::view-transition-group pseudo, you can also rely on CSS transitions on the original element … if you’ve set it up correctly.
~
🌟 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.
~
# The animation approach
In https://brm.us/view-transitions-border-radius I shared how you can nicely animate things like a border-radius with View Transitions. To recap, View Transitions animate snapshots and because of that things like a changing border won’t nicely animate but they will fade from the old to the new snapshot.
To work around that I suggested to replicate the border animation and put it onto the ::view-transition-group pseudo. For example, if the border-radius of your #card element changes from 0.25rem to 3rem, you’d create such an animation and apply it to the ::view-transition-group as follows:
@keyframes adjust-group {
from {
border-radius: 0.25rem;
}
to {
border-radius: 3rem;
}
}
::view-transition-group(card) {
box-sizing: border-box;
border: 2px solid black;
animation-name: -ua-view-transition-group-anim-card, adjust-group;
}
:active-view-transition-type(shrink)::view-transition-group(card) {
animation-direction: normal, reverse;
}
::view-transition-image-pair(card) {
display: none;
}
Live demo (that animates more than only the border-radius):
See the Pen
View Transitions with a Border Radius (2/3 – Workaround, with random text + border) by Bramus (@bramus)
on CodePen.
A key aspect to making this actually work, is that you have to individually capture the background part of the #card and the content/foreground part of it. It’s only the background part that you animate.
#card {
view-transition-name: card;
}
#card > #card-content {
view-transition-name: card-content;
}
Check out the following visualization which, upon hovering, shows the two layers that get captured. It’s the background layer that gets animated:
See the Pen
Untitled by Bramus (@bramus)
on CodePen.
~
# A simpler approach
On BlueSky, Martin Trap – from “The Bag of Tricks for View Transitions” – let me know that there is a simpler approach.
When such things get too complicated for me, I usually drop the old image along with the new one’s entry animation and rely on the fact that the new image is a live representation of the original element.
That way, I can simply use CSS transitions on the original element during the #ViewTransitions morph and be done with it.
So instead of creating an animation on the ::view-transition-group pseudo, Martin’s approach is to show only the new state of the box – through the ::view-transition-new pseudo – and rely on CSS transitions to have it transition the border with a duration that is set to the same duration + timing-function as the View Transition. Nice!
In code, it becomes this:
#card {
view-transition-name: card;
transition: all 2s ease; /* Same duration and easing as the View Transition */
}
#card > #card-content {
view-transition-name: card-content;
}
::view-transition-group(card) {
animation-duration: 2s;
animation-timing-function: ease;
}
::view-transition-old(card) {
display: none;
}
::view-transition-new(card) {
animation: none;
width: 100%;
height: 100%;
}
Here’s the demo that Martin shared:
See the Pen
View Transitions with a Border Radius (original by Bramus) by Martin Trapp (@martrapp)
on CodePen.
This approach too requires you to decompose the element into a background (which you animate) and a foreground layer. What you can drop from the animation-based approach is the extra logic to determine the type for the View Transition + the CSS to reverse the animation that goes along with it.
One (minor) nit with Martin’s code is that instead of transitioning all, I’d transition only the properties that need to transition. The downside is that it can result in quite a big list, such as for this demo:
#card {
transition-property: border, background-color, border-radius, aspect-ratio, font-size; /* Yeah, that’s a lot of properties … */
transition-duration: 2s;
transition-timing-function: ease;
}
Thanks for sharing your ideas, Martin!
~
🔥 Like what you see? Want to stay in the loop? Here's how:
I can also be found on 𝕏 Twitter and 🐘 Mastodon but only post there sporadically.
This content originally appeared on Bram.us and was authored by Bramus!
Bramus! | Sciencx (2025-05-15T19:46:32+00:00) View Transitions Applied: Smoothly animating a border-radius with a View Transition, revisited. Retrieved from https://www.scien.cx/2025/05/15/view-transitions-applied-smoothly-animating-a-border-radius-with-a-view-transition-revisited/
Please log in to upload a file.
There are no updates yet.
Click the Upload button above to add an update.