htmx Tutorial · User Feedback · Lesson 15 of 30
Animations and Transitions
Fade new content in and old content out with the CSS classes htmx adds during swaps, and use View Transitions.
The classes htmx adds
| Class | When |
|---|---|
htmx-request |
on the requesting element during the request |
htmx-swapping |
on the target before the swap (lasts for the swap: delay) |
htmx-added |
on new content before it settles |
htmx-settling |
on the target during the settle phase |
Combined with CSS transitions, they give smooth animations with no JavaScript.
Fade out, then remove
hx-swap="outerHTML swap:500ms" waits 500 ms before swapping. During that time the element has htmx-swapping, so a
CSS transition can fade it out:
<style>.row { transition: opacity 500ms; } .row.htmx-swapping { opacity: 0; }</style>
<div class="row">Notification 1 <button hx-delete="/n/1" hx-target="closest .row" hx-swap="outerHTML swap:500ms">Dismiss</button></div>
<div class="row">Notification 2 <button hx-delete="/n/2" hx-target="closest .row" hx-swap="outerHTML swap:500ms">Dismiss</button></div>
<!-- The pretend server: on a real site this part is your backend (Python, PHP, Node, Go...) -->
<script>
server.delete("/n/:id", () => "");
</script>
Smooth changes between versions
htmx keeps the id of elements between the old and new content and copies the old attributes first, then applies the
new ones after a short settle delay. So if the new element has the same id and a different class or style, a CSS
transition runs between them:
<style>#bar { height: 18px; background: #0ea5e9; transition: width 600ms ease; }</style>
<div style="border:1px solid #ccc;width:300px"><div id="bar" style="width:10%"></div></div>
<button hx-get="/progress" hx-target="#bar" hx-swap="outerHTML">Make progress</button>
<!-- The pretend server: on a real site this part is your backend (Python, PHP, Node, Go...) -->
<script>
let pct = 10;
server.get("/progress", () => {
pct = pct >= 100 ? 10 : pct + 30;
return `<div id="bar" style="width:${Math.min(pct, 100)}%"></div>`;
});
</script>
View Transitions
hx-swap="innerHTML transition:true" uses the browser's View Transitions API, which cross-fades the old and new
content (in supporting browsers, with a normal swap elsewhere).
Test yourself
What does hx-swap="outerHTML swap:500ms" give you time to do?
Run a CSS fade-out while the element has the htmx-swapping classCancel the requestLoad a second responseRetry a failed request
Show answer
Answer: Run a CSS fade-out while the element has the htmx-swapping class
The swap delay keeps the old element in place with htmx-swapping, so a transition can play.