HTMX Loading Patterns
HTMX has an in-built way to display loading content the moment a user submits a request. The term they use for this is hx-indicator
. You can read more about it here.
There are several scenarios where a user can trigger a request: Clicking a Link, Clicking a Button, or Submitting a Form.
Scenario 1: Clicking A Link
The most common way to handle this is to replace your main content container with something that indicates content is loading.
Add two divs inside your htmx target div (in this case
#main-content
).Wrap your main content in a
.hidden-while-loading
div, and...Add your loading content in a
.shown-while-loading
div.
<div id="main-content">
<div class="shown-while-loading">
<div class="shimmer p-5">
<div class="rect"></div>
<div class="rect width-.75"></div>
<div class="rect width-.5"></div>
<div class="rect width-.25"></div>
</div>
</div>
<div class="hidden-while-loading">
<%= yield %>
</div>
</div>
Make sure your htmx request specifies an hx-indicator
<body hx-boost="true" hx-target="#main-content" hx-indicator="#main-content">
That's it. Provided you've loaded the CSS below and the Shimmer CSS, and added your shimmer content, this should work out of the box.
Scenario 2: Clicking A Button
In scenarios where the content of the whole page won't change on click, a full replacement of the main div with a shimmer is overkill. In this case a cleaner UX is to simply show the user a loading spinner inside the button they clicked. This is as simple as
Add
hx-indicator="this"
to the button itself. This will override thehx-indicator
on any outer elements.Add a loading spinner inside the link or button, wrapped in a
.shown-while-loading
span.If there's already another icon on the button, it will look bad alongside the loading spinner. So hide it by wrapping it in
.hidden-while-loading
<a hx-indicator="this" href="/foo" class="flex items-center">
Send Notification
<span class="hidden-while-loading">
<svg class="w-4 h-4"></svg>
</span>
<span class="shown-while-loading">
<svg class="w-4 h-4"></svg>
</span>
</a>
Scenario 3: Submitting A Form
When a user submits a form the cleanest UX we've found is to...
Show a loading spinner on the submit button to indicate the form is saving.
Communicate that the form is in an interim state and should not be modified.
This can be achieved by doing the following:
Add
hx-indicator="this"
to the form.Add the
.faded-while-loading
class to the form.Add loading spinner icons inside the submit button.
<form hx-indicator="this" class="faded-while-loading">
<button type="submit">
Save
<span class="hidden-while-loading">
<svg class="w-4 h-4"></svg>
</span>
<span class="shown-while-loading">
<svg class="w-4 h-4"></svg>
</span>
</button>
</form>
The SVG
<svg viewBox="0 0 50 50" class=" htmx-indicator">
<path fill="currentColor" d="M43.935,25.146c0-10.355-8.396-18.75-18.75-18.75c-10.355,0-18.75,8.396-18.75,18.75h4.068 c0-8.115,6.567-14.682,14.682-14.682s14.682,6.567,14.682,14.682H43.935z">
<animateTransform attributeType="xml" attributeName="transform" type="rotate" from="0 25 25" to="360 25 25" dur="1s" repeatCount="indefinite"></animateTransform>
</path>
</svg>
The CSS
.htmx-request .shown-while-loading { display: block; }
.htmx-request .hidden-while-loading { display: none; }
.shown-while-loading { display: none; }
.htmx-request.faded-while-loading, .htmx-request .faded-while-loading { opacity: 0.6 }
Last updated