Introduction
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:
- Installing htmx
- Sending AJAX requests with htmx
- Custom htmx input validation
- Triggering CSS animation with htmx
Installing htmx
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.
Sending AJAX requests with htmx
Htmx provides a set of attributes that allows you to send AJAX requests directly from an HTML element. Available attributes include:
hx-get
— sendGET
request to the provided URLhx-post
— sendPOST
request to the provided URLhx-put
— sendPUT
request to the provided URLhx-patch
— sendPATCH
request to the provided URLhx-delete
— sendDELETE
request to the provided URL
Code sample
<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.
Trigger requests
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.
Trigger modifiers
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
Code sample
<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.
Polling with the htmx-trigger
attribute
In 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.
Targeting elements for AJAX requests
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
.
Swapping the HTML returned into the DOM
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 request
Request indicators
When 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.
Requesting data
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.
Code sample
<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.
Filtering out parameters
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 list
Uploading files
With 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>
Custom htmx input validation
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 errors
Triggering CSS animation with htmx
Htmx provides a way to easily attach smooth CSS transitions to AJAX events and also in your webpage generally.
Using 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>
Summary
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.
Get set up with LogRocket's modern error tracking in minutes:
- Visit https://logrocket.com/signup/ to get an app ID
- Install LogRocket via npm or script tag.
LogRocket.init()
must be called client-side, not server-side - (Optional) Install plugins for deeper integrations with your stack:
- Redux middleware
- NgRx middleware
- Vuex plugin
$ 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>