HTMx Swap and Settle Classes for Cool Transitions
You may have noticed a subtle fade-out and fade-in effect when navigating between pages on this website. This is achieved by leveraging HTMx's swap and settle classes.
How It's Done
HTMx automatically applies and removes a couple of classes to the target element when responding to a trigger. When these classes are applied, you can use CSS to create smooth transitions in response.
The HTMx Request/Response documentation explains:
- When an element is triggered and a response is detected, HTMx will add the
htmx-swappingclass to the target element. - HTMx will then optionally wait a specified amount of time before actually performing the DOM swap.
- After swapping the content, HTMx removes the
htmx-swappingclass and adds thehtmx-settlingclass to the target element. - HTMx waits an optional amount of time and the DOM is settled.
- Finally, HTMx removes the
htmx-settlingclass from the target element.
I could draw it something like this:
***** triggered (e.g. a link is clicked)
(wait for a response)
(response received)
----> htmx-swapping
(wait optional time)
(DOM is swapped)
<---- htmx-swapping
----> htmx-settling
(wait optional time)
(DOM is settled)
<---- htmx-settling
So, this opens up the possibility of using the addition and removal of these classes to trigger CSS transitions.
All we need to do is: add some CSS to our project that responds to these classes and configure these optional wait times (above) when we configure the events that respond to the triggers.
The CSS
Here's an example of how I do it on this website:
/* HTMx Transition Styles */
.htmx-swapping {
opacity: 0.25;
transition: opacity 0.25s ease-in;
}
.htmx-settling {
opacity: 1;
transition: opacity 0.5s ease-out;
}
When the htmx-swapping class is added, the opacity of the target element is set to 25% with a transition time of a quarter of a second and an easing of ease-in. This creates a fade-out effect.
When the htmx-settling class is added, the opacity of the target element is set back to 100% with a transition time of half a second and an easing of ease-out. This creates a slightly longer fade-in effect. I found that a .25 second fade-in appeared too quickly for my taste.
The HTMx Configuration
Now, all we have to do is configure the trigger and swap behavior. The key is to add a long enough delay or wait time to allow the CSS transitions to complete before HTMx removes the classes.
Let's say I was configuring a link to initiate this kind of swap. I would use the hx-swap family of directices to create the critical delays:
<a href="/partial/"
hx-get="partial"
hx-target="#the-target"
hx-swap="innerHTML swap:0.25s settle:0.5s">My Partial</a>
See how we specify some details in the hx-swap attribute?
In particular, we set the swap delay to 0.25 seconds and the settle delay to 0.5 seconds. This allows the fade-out transition to complete before the content is swapped in, and the fade-in transition to complete after the new content is settled.
View Transitions API
Just a little note: There's also support for the new CSS View Transitions API in HTMx. See here. With more browser support, this option would be the way forward but, until then, we'll stick with the straight-forward class-based transition mechanism.
Conclusion
Anyway, I think the transition looks nice and yet shows a little restraint.
The whole point of HTMx is to provide the responsiveness of a local application or SPA, so this transition effect may not always be appropriate. But, you're free to imagine your own transitions or dispense with them altogether.
In this case, where I'm swapping in text, I think it all works. I think the fading provides a more gentle cognitive transition for the user over the more jarring instantaneous swap that is the default.