What is HTMX, and why is it important?
In 2013, Carson Gross created an alternative frontend library intercooler.js, with the tagline “Ajax With Attributes” to simplify the complexity of frontend web development. A new version of intercooler.js reached version 2.0 and became htmx described as a library that enables you to access Ajax, WebSockets, CSS transition, and Server-Sent Events directly inside HTML.
- Why should only
<form>be able to make HTTP requests?
- Why should only
submitevents trigger them?
- Why should only
POSTmethods be available?
- Why should you only be able to replace the
“By removing the arbitrary constraints, htmx completes HTML as a hypertext,” he concludes.
Setting up HTMX
To setup HTMX, you can seemingly load it via a CDN and add it to your head tag like this below:
<script src="https://firstname.lastname@example.org" integrity="sha384-EzBXYPt0/T6gxNp0nuPtLkmRpmDBbjg6WmCUZRLXBBwYYmwAUxzlSGej0ARHX0Bo" crossorigin="anonymous"></script
Another way is to download the htmx.min.js source file and add it to the appropriate directory in your project, then insert it where necessary with a script tag like this :
You can also install HTMX via
npm like this below:
npm install htmx.org
Sending Ajax Requests using HTMX
HTMX offers a set of attributes that enable you to make AJAX requests directly from HTML.
hx-post- issues a POST request to the given URL.
hx-get- issues a GET request to the given URL.
hx-put- issues a PUT request to the given URL.
hx-patch- issues a PATCH request to the given URL.
hx-delete- issues a DELETE request to the given URL.
Each of these attributes above accepts a URL to send an AJAX request to. So whenever the element is triggered, it sends the specified type of request to the given URL. Consider the example below:
<script src="https://email@example.com"></script> <div hx-get="https://v2.jokeapi.dev/joke/Any?format=txt&safe-mode" >Load Jokes</div>
The demo above instructs the browser that when a user clicks the
Load Jokes element, it should send a
GET request (
hx-get) to the jokeapi endpoint URL (https://v2.jokeapi.dev/joke/Any?format=txt&safe-mode) and load the response into the div element. We used a demo Joke API here, a REST API that serves uniformly and well-formatted jokes.
Next, we will examine how to load the response into another HTML element.
Triggering Requests with HTMX
An element’s “natural” event initiates Ajax requests automatically by default. For example,
onchange event triggers
select. While the
onsubmit event triggers
click event triggers every other request. HTMX offers a unique ‘hx-trigger’ if you need to specify which event will trigger the request.
<script src="https://firstname.lastname@example.org"></script> <div class= "jokes" hx-get="https://v2.jokeapi.dev/joke/Any?format=txt&safe-mode" hx-trigger="mouseenter” > Load Jokes </div>
When the mouse hovers over the div element in the code above, it sends a GET request to the provided URL endpoint and retrieves the Jokes.
Triggering Modifiers with HTMX
As mentioned in the previous section, it is possible to modify the hx-trigger attribute to change its behavior. For instance, if you only want a request to occur once, you can use the
once modifier for the trigger.
<div class= "jokes" hx-get="https://v2.jokeapi.dev/joke/Any?format=txt&safe-mode" hx-trigger="mouseenter once” > Load Jokes </div>
Below are the lists of available modifiers:
changed- send a request if the element value has changed.
display:<time interval>- wait for a given amount of time(e.g
delay-1s) before sending the request.
throttle: <time interval>- wait the given amount of time (e.g
delay-1s) before sending the request. Unlike delay, if a new event occurs before it reaches the time limit, the event will discard, which means it triggers a request at the end of the time.
<css selector>- listen for event on a different element. You can use this for things like keyboard shortcuts.
You can use all these attributes above for implementing some common UX patterns like the Active Search Box pattern. With this example here, you can see these attributes above in action.
Polling with the
Using the HTMX trigger attribute, we can also specify that the element polls the given URL every
n seconds instead of waiting for an event to occur.
<script src="https://email@example.com"></script> <div class= "jokes" hx-get="https://v2.jokeapi.dev/joke/Any?format=txt&safe-mode" hx-trigger="every 3s"> Load Jokes </div>
Here, the HTMX instructs the browser to send a GET request to the
/V2.jokeapi URL every 3s and display the response in the div element.
Because the browser provides no feedback, it is helpful to notify users that something is happening. You can do this with HTMX by using the ‘htmx-indicator’ class.
<div class= "jokes" hx-get="https://v2.jokeapi.dev/joke/Any?format=txt&safe-mode" > <button>Load Jokes</button> <img class="htmx-indicator" src="https://i.imgur.com/8THYvPQ.gif"> </div>
The ‘htmx-indicator’ class would set the opacity of any element with this class to
0 by default, making it hidden but present in the DOM. When you click the ‘load jokes’ button, it adds the ‘htmx-request’ class, which displays the loader indicator.
As stated before, HTMX loads the response to an AJAX request into the element that initiated the request. The ‘hx-target’ attribute allows you to load the response in a different element than the one that initiated the request. The ‘hx-target’ will accept a CSS selector and will automatically load the AJAX response into the target element:
<button class="btn" hx-get="https://v2.jokeapi.dev/joke/Any?format=txt&safe-mode" hx-target="#result" > Load Jokes </button> <div class= "jokes" id="result"></div>
In the demo above, when you click on the
load jokes button, it will automatically load the response into the
div element below it.
hx-target in the previous section, HTMX offers a different way to determine how to load the response returned by Ajax within the Dom. You can do so by setting the ‘hx-swap’ attribute with any of the values listed below:
innerHTML: This is the default value; it inserts the content into the target element sending the request.
outerHTML: It replaces the entire target element with the returned content.
afterbegin: It prepends the response before the first child inside the target element.
beforebegin: prepends the response as a parent element of the actual element triggering the request.
beforeend: It appends the response after the last child of the element sending the request.
afterend: like the
beforeend, this appends response after the element sending request.
none: this option doesn’t append or prepend a response from an AJAX request.
Here is an example of a scrolling progress bar using some of the attributes mentioned above (https://htmx.org/examples/progress-bar).
Synchronizing Request with HTMX
Sometimes, you will need to synchronize requests between two elements. Suppose you want a request from one element to override another element’s requests, or you want to wait until the other element’s requests are complete. You can do this by using the
hx-sync attribute. Consider the code below:
<form hx-post="/article"> <input id="title" name="title" type="text" hx-post="/validate" hx-trigger="change" > <button type="submit">Submit</button> </form>
In the example above, we have a form submission and an individual
input validation request. Without using
hx-sync, when you fill out the form and submit it, it triggers two parallel requests to
/validate simultaneously. According to the documentation, using
hx-sync=" closest form:abort" on the input will watch for requests on the
form and halt the input requests if a form request is present or start while the input request is in flight:
<form hx-post="/article"> <input id="title" name="title" type="text" hx-post="/validate" hx-trigger="change" hx-sync="closest form:abort" > <button type="submit">Submit</button> </form>
Using this approach, we can fix the synchronization issue between the two elements declaratively. You can read more on
hx-sync attribute here.
Open Source Session Replay
OpenReplay is an open-source, session replay suite that lets you see what users do on your web app, helping you troubleshoot issues faster. OpenReplay is self-hosted for full control over your data.
Start enjoying your debugging experience - start using OpenReplay for free.
File Upload with HTMX
With HTMX, you can create a file upload form that will be submitted via Ajax to your backend for processing. You can effortlessly send files like videos, images, and documents. You can implement this with HTMX by directly embedding the
hx-encoding attributes with the value
multipart/form-data into the parent element sending the request:
<form hx-encoding='multipart/form-data' hx-post='/registration' _='on htmx:xhr:progress(loaded, total) set #progress.value to (loaded/total)*100'> <input type='file' name='userFile'> <button> Upload File </button> </form>
Input Validation with HTMX
Htmx incorporates natively with the HTML 5 Validation API, so if a validatable input is invalid, it will not send a request. This feature applies to both AJAX requests and WebSockets sends. Also, HTMX fires events around validation that you can use to hook in custom validation and error handling. The following events are currently available:
- `htmx:validation: validate – used for adding custom validation logic.
htmx:validation:failed` – this event fires when an element validation return false, e.g., indicating an invalid input.
htmx:validation: halted: It calls this event when you a request is not issued due to validation errors. You can find specific errors in the
Consider an input that uses the
htmx:validate:validate event to ensure that the input has the value
David using hyperscript:
<form hx-post="/validate"> <input _="on htmx:validation:validate if my.value != 'David' call me.setCustomValidity('Please enter the value David') else call me.setCustomValidity('')" name="username" > </form>
It is important to note that all client-side validation must occur on the server, as it can always be bypassed.
CSS animations with HTMX
class-tools which allows you to define CSS classes that swap onto or off the element using the
You can use the extension by assigning to the
classes attribute to an element. The
classes attribute value consist of “runs” separated by an & character. In a run, it will apply class operations sequentially with the specified delay. These class operations are
toggle accompanied by a CSS class name and optionally by a colon: and time delay.
<div classes= “add sample-demo: 1s”></div>
Once the browser contents load, HTMX will automatically add a new class of
sample-demo to the div after 1 second. Let’s take a look at this demo example below:
<div hx-ext="class-tools"> <div class="demo" classes="toggle faded:1s">See me Fading Away </div> </div>
HTMX seamlessly integrates with different server-side frameworks, although some frameworks may have alternatives for installing HTMX. Check out this link to explore how you can integrate HTMX with different server-side frameworks.
Check this link to explore some sets of UX patterns demo implemented with HTMX that you can edit and integrate with your projects.
The following link (https://htmx.org/examples/) contains some sets of UX pattern demos that you can edit and integrate into your projects.