Htmx is a JavaScript library for performing AJAX requests, triggering CSS transitions, and invoking WebSocket and server-sent events directly from HTML elements. Htmx lets you build modern and powerful user interfaces with simple markups.
This library weighs ~10KB (min.gz’d), it is dependency-free (i.e., it does not require any other JavaScript package to run), and it’s also compatible with IE11.
In this tutorial, we will be exploring the powerful features of htmx while covering the following sections:
You can get started with htmx by downloading the htmx source file or including its CDN directly in your markup, like below:
<script src="https://unpkg.com/[email protected]"></script>
The script above loads the current stable version of htmx, which as of writing this is version 1.3.3, on your webpage. Once that’s done, you can implement htmx features on your webpage.
Htmx provides a set of attributes that allows you to send AJAX requests directly from an HTML element. Available attributes include:
hx-get
— send GET
request to the provided URLhx-post
— send POST
request to the provided URLhx-put
— send PUT
request to the provided URLhx-patch
— send PATCH
request to the provided URLhx-delete
— send DELETE
request to the provided URL<button hx-get="http://localhost/todos">Load Todos</button>
The code example above tells the browser that when the user clicks the button, it sends a GET
request (hx-get
) to the provided URL, which in this case is http://localhost/todos
.
By default, the response returned from any htmx request will be loaded in the current element that is sending the request. In the In the Targeting elements for AJAX requests section, we will be exploring how to load the response in another HTML element.
Targeting elements for AJAX requests section, we will be exploring how to load the response in another HTML element.
You should note that AJAX requests in htmx are triggered by the natural event of the element. For example, input
, select,
and textarea
are triggered by the onchange
event, and form
is triggered by the onsubmit
event, and every other thing is triggered by the onclick
event.
In a situation where you want to modify the event that triggers the request, htmx provides a special hx-trigger
attribute for this:
<div hx-get="http://localhost/todos" hx-trigger="mouseenter"> Mouse over me! </div>
In the example above, the GET
request will be sent to the provided URL if and only if the user’s mouse hovers on the div.
The hx-trigger
attribute mentioned in the previous section accepts an additional modifier to change the behavior of the trigger. Available trigger modifiers include:
once
— ensures a request will only happen oncechanged
— issues a request if the value of the HTML element has changeddelay:<time interval>
— waits for the given amount of time before issuing the request (e.g., delay-1s
). If the event triggers again, the countdown is resetthrottle:<time interval>
— waits the given amount of time before sending the request (e.g., throttle:1s
). But unlike delay, if a new event occurs before the time limit is reached, the event will be in a queue so that it will trigger at the end of the previous eventfrom:<CSS Selector>
— listens for the event on a different element<input type="text" hx-get="http://localhost/search" hx-trigger="keyup changed delay:500ms" />
In the code sample provided above, once the user performs a keyup
event on the input element (i.e., the user types any text in the input box) and its previous value changes, the browser will automatically send a GET
request to http://localhost/search
after 500ms.
htmx-trigger
attributeIn the htmx-trigger attribute, you can also specify every n seconds rather than waiting for an event that triggers the request. With this option, you can send a request to a particular URL every n seconds:
<div hx-get="/history" hx-trigger="every 2s"> </div>
The code sample above tells the browser to issue a GET request to /history
endpoint every 2s and load the response into the div.
In previous sections, we’d mentioned that the response from an AJAX request in htmx will be loaded into the element making the request. If you need the response to be loaded into a different element, you can use the hx-target
attribute to do this. This attribute accepts a CSS selector and automatically injects the AJAX response into an HTML element with the specified selector.
We can modify our to-dos sample to suit this case:
<button hx-get="http://localhost/todos" hx-target="#result"> Load Todos </button> <div id="result"></div>
Unlike the previous example, this new code sample sends a request to http://localhost/todos
and loads the response in our div with id=result
.
Similar to hx-target
, the hx-swap
attribute is used to define how the returned AJAX response will be loaded in the DOM. Supported values include:
innerHTML
— default value, this option will load the AJAX response inside the current element sending the requestouterHTML
— this option replaces the entire element sending the request with the returned responseafterbegin
— loads the response as a first child of the element sending the requestbeforebegin
— loads the response as a parent element of the actual element triggering the requestbeforeend
— loads and appends the AJAX response after the last child of the element sending the requestafterend
— unlike the previous, this appends the AJAX response after the element sending the requestnone
— this option will not append or prepend the response from an AJAX requestWhen sending an AJAX request, it is often good practice to let the user know that something is happening in the background since the browser won’t do this automatically by default. You can easily accomplish this in htmx with the htmx-indicator
class.
Consider the code sample below:
<div hx-get="http://path/to/api"> <button>Click Me!</button> <img class="htmx-indicator" src="path/to/spinner.gif" /> </div>
The opacity of any HTML element defined with the htmx-indicator
class is set to 0 by default, therefore making the element invisible but present in the DOM.
And, when you issue an AJAX request, htmx will automatically add a new htmx-request
class to the element sending the request. This new htmx-request
class will cause a child element with the htmx-indicator
class on it to transition to an opacity of 1, therefore showing the indicator.
If your AJAX request was triggered by a form or an input element, by default htmx will automatically include the value of all the input field(s) in your request.
But in a case where you want to include the values of other elements, you can use the hx-include
attribute with a CSS selector of all the elements whose values you want to include in the request.
<div> <button hx-post="http://path/to/api/register" hx-include="[name=username]"> Register! </button> Enter Username: <input name="username" type="text"/> </div>
Like in the code sample above, when you issue a request to the /register endpoint, your AJAX request will automatically include the email field in its body.
Htmx also provides another htmx-params
attribute with which you can filter out the only parameters that will be submitted when an AJAX request is sent.
<div hx-get="http://path/to/api/example" hx-params="*"> Send Request </div>
The code sample above will include all input elements on your page as your request parameters.
All possible values include:
*
— will include all parameters present in your webpage and send it along in your AJAX requestnone
— won’t include any parameters in your requestnot <param-list>
— includes all other parameters and excludes the comma-separated list of parameter names<param-list>
— will only include all the comma-separated parameter names in your listWith htmx you can easily send files such as images, videos, PDFs, etc. to your backend for processing by adding the hx-encoding
attribute with value multipart/form-data
to the parent element of the actual element sending the request:
<form hx-encoding="multipart/form-data"> Select File: <input type="file" name="myFile" /> <button hx-post="http://path/to/api/register" hx-include="[name='myFile']" > Upload File! </button> </form>
Htmx is integrated with the HTML5 validation API by default, and will not issue a request if a validatable input is invalid. This feature works for both AJAX requests and WebSocket events.
In addition to this, htmx also fires events around validation, which can be pretty useful in custom input validation and error handling.
Available validation events include:
htmx:validation:validate
— this event is useful in adding custom validation login, as it is called before an element is validatedhtmx:validation:failed
— this event is fired when an element validation returns false, i.e., indicating an invalid inputhtmx:validation:halted
— this event is called when an element was unable to issue a request due to input validation errorsHtmx provides a way to easily attach smooth CSS transitions to AJAX events and also in your webpage generally.
class-tool
htmx class-tool
is an extension that you can easily use to toggle, add, or remove a particular class name from an HTML element without writing any JavaScript code.
You can utilize this extension by adding the classes
attribute to your element and then specifying the action, followed by the class name you want to add or remove:
<div classes="add sample-class:1s"></div>
Like in the code sample above, once the browser content is loaded, htmx will automatically add a new class (sample-class
) to the div after 1s.
Also note that you can create an action queue by separating each action with a comma (,
), or make multiple actions run simultaneously by separating them with an ampersand (&
):
<!-- class tool queue --> <div classes="add sample-class:1s, remove another-class:2s, toggle 3rd-class:1s"></div> <!-- simultaneous actions --> <div classes="add sample-class:1s & remove another-class:2s & toggle 3rd-class:1s"></div>
Below is an example that toggles the visibility of an element:
<style> .demo.faded { opacity: 0.3; } .demo { opacity: 1; transition: opacity ease-in 900ms; } </style> <div class="demo" classes="toggle faded:1s">I'm Fading! âš¡</div>
In this article, we’ve explored the htmx installation process, how to send AJAX requests, form validation, and also triggering CSS animation without writing any JavaScript code.
Htmx offers experimental support for WebSocket and server-sent events, which were not covered in this article because they are still under development. You can learn more about WebSocket and SSE support from htmx documentation.
Install LogRocket via npm or script tag. LogRocket.init()
must be called client-side, not
server-side
$ npm i --save logrocket // Code: import LogRocket from 'logrocket'; LogRocket.init('app/id');
// Add to your HTML: <script src="https://cdn.lr-ingest.com/LogRocket.min.js"></script> <script>window.LogRocket && window.LogRocket.init('app/id');</script>
Leptos is an amazing Rust web frontend framework that makes it easier to build scalable, performant apps with beautiful, declarative UIs.
Learn more about the 5 best JavaScript libraries for dealing with multidimensional arrays, such as ndarray, math.js, and NumJs.
We spoke with Dom about his approach to balancing innovation with handling tech debt and to learn how he stays current with technology.
Vite is a versatile, fast, lightweight build tool with an exceptional DX. Let’s explore when and why you should adopt Vite in your projects.