I am a software developer and reluctant travel enthusiast. I love clean code, lean process, and constant learning.

A "Jalapeno Business" Production

Subscribe for updates straight to your inbox. Free. No spam. Early Access.

jamie@example.com
nickrogers.blog

What is HTMX?

What is HTMX?
/imagine giant whiteboard with a diagram, clear details, box diagrams, outline, plan, arrows title at top says "Migration to HTMX" --ar 16:9
🤯
HTMX is a javascript library that lets you build dynamic web pages without using JavaScript (unless you want to).

What this covers:

  • Introduction
  • Installation and Basic Usage with Examples
  • Community and Ecosystem
  • Security Considerations

When I first learned HTML and started building simple websites it was liberating. It felt empowering to build something and put it on the internet. Back then the business logic and presentation would generally all happen on the server. User interaction was limited to forms sent from browsers, that would return as brand new web pages, happily rendered by their patiently waiting recipients. Servers sent HTML and browsers rendered it. We call these hypermedia APIs.

Modern Web Development

Over time AJAX and frameworks like React and Angular enabled the kind of user interaction that early web pioneers could only dream of. But they have introduced a lot of complexity, and generally require some duplication of data models from backend systems which are likely returning JSON objects.

HTMX aims to enable rich user interactivity with only html attributes. It is a tiny javascript library that shifts some front end work to the domain of the server by extending the functionality of basic HTML. It enables some seriously cool patterns, and there are UI examples for most modern web tropes. (click to edit, dialogs, lazy loading, animations, active search, etc).

Installation

HTMX is dependency free, so to "install" htmx you simply add a <script> tag to any html document. You can use the free content delivery network (CDN) or cache your own copy if you are the nervous type (npm install htmx.org). The official htmx account jokingly offered a "create-htmx-app" script in this post on X that would create one html file with the following:

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8">
    <title><!-- enter title here --></title>
    <script src="https://unpkg.com/htmx.org@1.9.2"></script>
  </head>
  <body>
    <!-- enter page content here -->
  </body>
</html>

The most minimal htmx app. 1.9.2 = current version at time of writing. Start with the newest.

💡
Try saving the code above into index.html and opening it inside a web browser. You have officially created your first HTMX app!

Usage - Custom Attributes

HTMX adds superpowers to the html in our document. The docs give lots of useful details, but the core idea is that any element can issue an HTTP request, and any element can be updated with the result of that request. The most important new functionality we get is hx-get and hx-post (both transform HTML elements into fully fledged AJAX request machines) but there are several other new attributes that will let us build amazing, responsive apps with no javascript on the front end.

Attribute Description
hx-request Issues an http request (eg request = "get") to the given URL
hx-trigger describes when to trigger (default = 'click')
hx-target replace any element on screen (transclusion)
hx-swap specify how to swap content into the dom
hx-swap-oob used for out of bounds swaps (advanced)
hx-indicator show an indicator during the AJAX request
hx-include include with request via a css-selector (e.g. "[name='email']")
hx-disable disables the element if set
hx-headers JSON object to be passed as headers with request
hx-encoding changes the request encoding from "application/x-www-form-urlended"
hx-request request level parameters (e.g. '"timeout":100')
hx-vals JSON submitted with the ajax request (e.g. hx-vals='{"key":"val"}')
hx-push-url controls url pushed to browser, defaults to false
hx-sync synchronize AJAX requests between multiple elements (eg - "replace")
hx-ws connects element with a websocket
hx-sse used for consuming server sent events via websocket
hx-preserve allows you to specify an element to remain unchanged

The three most important to learn initially are hx-<request>, hx-target, hx-swap. These will tell the browser what rest action to perform, where and how to place the results.

Any element can issue an HTTP request, and any element can be updated with the result of that request.

hx-<request>

The core of htmx are the attributes that allow you to send AJAX requests from any element. We have access to all of the traditional REST verbs: post, put, delete, and even patch and you can substitute any one of these for <request>.

In particular, we can add hx-get to any element, and when it is clicked, it will execute a GET request to the address we provide:

<button hx-get="https://nickrogers.blog/about" hx-swap="outerHTML">
  Click Me
</button>

The default value for hx-swap is "innerHTML", which would replace only the text "Click Me" and would result in a giant button filled with the contents of this site

hx-swap

This attribute defines what to do with the response of our get call.

  • "outerHTML" will replace the element entirely
  • "innerHTML" will replace anything nested inside of it. (this is the default)
  • can take a settle:<time> where time is a time value such as "1s" or "500ms" to put a delay on the swap.

hx-target

We can also add hx-target to any element that has an hx-get attached to specify exactly where htmx should put the result of the request.

<button hx-get="/disclaimer" hx-target="disclaimer">
  Click Me
</button>

<div id="disclaimer"></div>

When the button is clicked, the hx-target value tells the browser to place the response inside the div below with id equal to "disclaimer"

hx-boost

Boosting any element will cause links inside of it to do a great impression of a single page app. It essentially transforms any links into get requests with a target of the entire body of the document. Boosted anchor (<a>) links will replace the entire body of the HTML document. Boost can be applied at the parent level.

Partial Updates with hx-select

The hx-select attribute allows you to specify which part of the server's response should be used to update the DOM.

<div>
    <button hx-get="/user-data" hx-select="#address" hx-swap="outerHTML">
        Get Address!
    </button>
</div>

This button will issue a GET to /user-data and then select the element with the id address, which will replace the entire button in the DOM.

Request Indicators

Of course modern web sites need loading spinners. Set the attribute hx-indicator to a css selector that specifies an element that should become visible while loading and go away after.

<button hx-get="/data" hx-indicator="#loadingSpinner">
    Fetch Data
</button>
<div id="loadingSpinner" style="display:none;">Loading...</div>

The loading spinner becomes visible while fetching and then reverts back afterwards.

Lazy Loading

By setting the attribute hx-trigger to revealed, we can gate requests until objects scroll into view. Simply put a div like this at the bottom of your data and new elements will get fetched when a user scrolls to the end.

<div hx-get="/lazy-load" hx-trigger="revealed">
  <!-- Content will be loaded when this element comes into view -->
</div>

There's a lot more you can do with this little library. I have built a handful of apps and I'm excited to share everything I have learned with you.

Community and Ecosystem

The community and ecosystem is growing in popularity (there are extensions available). You can inject them using the hx-ext attribute and apply them to specific elements. HTMX is young, but will naturally grow over time. It has received a lot of attention lately and was even

🚀
HTMX has been accepted into the first class of the GitHub Open Source Accelerator for 2023!

The documentation is very straightforward, and can be a fantastic resource when you are getting started.

Security

Since elements are rendered server side, you can take advantage of this model to handle data validation before returning any content to a user. In theory, htmx can be very secure. Your templates and html partials are going to get delivered to front end users though, so you should be cautious.

  • Serve your front end and back end from the same place (Only make requests against routes that you control).
  • Use an auto-escaping template engine (eg - jinja, handlebars, blade)
  • Authentication cookies should be set with SecureHttpOnly, and SameSite=Lax
  • Only serve user defined content in html. Don't use any user defined values in <script> tags. Don't ever use user defined attribues.

For a full consideration of web security as it relates to htmx, check out the official advice.

Latest post