Dave's htmx Live Reference

Page created: 2021-11-27 , updated: 2023-08-27
rather overdone htmx letters in a living mass of vines

This live reference is LIVE! Everything actually works and actually submits to a real API. View this page's source to see the living, breathing client-side markup. Use your browser's developer tools (the F12 key) to view the network traffic.

Incomplete Page

I still like HTMX just as much as I did when I first discovered it. But I was using it in a project that has ended and I have not been keeping up with it. After some soul-searching, I've decided not to finish this page.

Hopefully what is here will remain useful and I'm happy to make small fixes if anyone finds any. -Dave

Currently presented in the exact same order as the reference documentation: https://htmx.org/reference/


htmx enhances HTML using attributes prefixed with hx-. Because you aren’t writing JavaScript directly, nothing bad will happen if the htmx library is not present or JavaScript is disabled. Your page won’t halt due to syntax errors. For this reason, htmx is a perfect companion for progressively enhancing HTML interfaces.


boost bear boosts anchor tag

Causes <a> and <form> tags to make htmx requests, replacing the whole page <body> contents (innerHTML) by default.

Here’s a "regular" anchor link to another page and a "boosted" one. When you click on the boosted link, the contents of the "Foo" page will be requested and will replace this one. htmx will even discover the <title> and set it for us. The address bar will also reflect the new URL. Only super savvy users will even realize there’s a difference.

It is much more obvious that we’ve done something different when we change the swap target to an element other than the whole page body (hx-target="#boost-target"):

Click me! (boosted, loads below)
Foo will load here!

But notice that the address bar is now pointing to the Foo page. If you refresh now, your browser will take you to the Foo page. You should design boosted links so that they make sense even if the user has JavaScript disabled.

Like most htmx attributes, boost is inherited from parent elements. Here, the container <div> contains the hx-boost attribute, so all of the anchors (<a>) are boosted:

Foo 1 (boosted)
Foo 2 (boosted)
Foo 3 (boosted)

I think hx-boost is one of the most convenient ways htmx helps support progressive enhancement. Make your site/application work 100% without any JavaScript at all, then figure out how scripting the page can make it even better.


confirmation fox asks if you are sure

Pops up the standard browser confirm dialog before performing the HTTP request (whatever it may be).

This example has a <form> that submits a pilot (via POST) to the API’s /danger/zone. It has an hx-confirm attribute that will first prompt to ask you if you wish to do this.

Response will display here!


This is what’s super-cool about htmx: it extends HTML to remove arbitrary limitations. Why can the native HTML elements only issue GET or POST requests? We can fix that.

Adding hx-delete="/foo" to an element causes it to send an HTTP DELETE request to the URL /foo.

As with boosting, the element fires the request on the "natural" event (buttons and anchors on click, forms on submit). You can change this with hx-trigger.

Response will display here!


the disable bear cannot interact

Putting hx-disable on an element prevents htmx from doing anything with that element and any of its child elements. Use this any time you need to shut off htmx processing at an element level for any reason.

The hx-get on the following example button doesn’t do anything because the parent <div> has hx-disable:

(won't do anything)


encoding owl prefers multipart form data

By default, HTML form requests are POSTed with application/x-www-form-urlencoded encoding:


This is the correct type for most typical form data (text fields, checkboxes, etc.) but there’s a much more appropriate type for uploading forms that include complex data such as file uploads.

The multipart/form-data content type (see RFC 7578) which "which can be used by a wide variety of applications and transported by a wide variety of protocols as a way of returning a set of values as the result of a user filling out a form."

In fact, when uploading files from HTML forms, encoding with multipart/form-data is the only way to send files. Otherwise you’ll just send the selected filename!

Let’s see what that looks like:

Content-Disposition: form-data; name="name"

Owls Encoding Spells
Content-Disposition: form-data; name="genre"

Melodic Forest Metal

As you can see, a multipart form is extreme overkill for transfering regular text form fields like this!

Since I’ve set a limit of 10Kb for uploads to my API, I’ve provided a sample file in the form of a story in a .txt document. By weird coincidence, the story is also about multipart form encoding.

Both forms below use hx-boost so that htmx makes the request. The encoding type is set in the second one to use multipart/form-data with hx-encoding so you can see the difference. (Normally you’d set this with the enctype attribute in a <form> tag (and that’s what I recommend), but having the ability to add this to any tag with htmx rounds out its ability to address edge cases and fully enhance HTML.

Sample file to upload:

encoding-owl.txt Encoding Owl Saves the Day

Form with default encoding type:

(10Kb limit!)
(Response will show up in box below the second form.)

Same form, but with multipart encoding:

(10Kb limit!)
Response(s) will display here!

(This example also uses the inheritance feature of htmx: the hx-boost and hx-target properties for both forms are set in the parent div.)


extension bear admires his new extended arm

You can define extensions to htmx with htmx.defineExtension('foo', …​). Use them with the hx-ext="foo, bar" attribute (note that multiple extensions can be used by separating them with commas in the attribute value). There are also twelve (as I write this) "official" extensions that are part of the htmx repo and published in separate .js files - they expose additional interesting functionality for DOM elements. Check them out.

The API surface for htmx extensions is really small (just five callback functions available). See the documentation for the details. Also see the events documentation for the htmx events you can handle.

Here we have created an extension called "foo", registered it with htmx, and activated it on this container div. Any element with a foo attribute will pop up an alert box with the element's inner text.

(no "foo" attribute on this one)


get moose gets

The hx-boost directive (top of this page) tells htmx to make the request on behalf of an element which would normally do a GET or POST request (anchor and form tags). With hx-get, we can cause any element to make a GET HTTP request.

Response(s) will display here!


header squirrel is...eating header values?

This shows how much control htmx gives us over all aspects of HTTP requests in our HTML attributes. The format of the value of this attribute is interesting: it’s a JSON object containing key-value pairs, each of which will be sent as header properties in the request.

Response(s) will display here!
bear says, what is that supposed to be? fox says, a squirrel? owl says, yeah i don't get it

Hey! I don’t need any commentary. The squirrel volunteered to do headers. Nobody else wanted to be the header animal. I didn’t see any of you jumping to demonstrate HTTP headers.

squirrel explains: I store things in my head!

See? There you have it.


The hx-history-elt or "history element" attribute tells htmx to use only the scope of the current element for history snapshots (which preserve browser navigation history).

To demonstrate this, we’ll need a whole new page!

Click here to visit the History Owl and see this attribute in action.

(And also read the incredible Forest Blog!)

forest blog logo


form fox has a little backpack

The hx-include attribute tells htmx to include the value from another element (or elements) on the page in the HTTP request.

In the example below, the Publisher input field is outside of the <form> tag, but it is included in the request by way of hx-include. Try it out and you’ll see that the publisher field (and whatever you typed in it) is part of the request body.


Book Form
Book Title:
Page Count:
Response will display here!

It’s a little difficult to imagine obvious use cases for this and it at first appears to have been included to handle weird edge cases. But actually, I suspect there might be all kind of handy uses for this because it allows you to declaratively tie together data from disparate parts of the HTML document without having to restructure or compromise the "physical" layout of the document to do so.

In this example, an anchor link submits the form by including the form element, which causes child input elements to be included.

My Favorites Form

Click here to submit the form!

Response will display here!

But note that including fields like this is probably going to break whatever fancy thing you had planned if JavaScript isn’t enabled. So this attribute is probably not part of a valid progressive enhancement strategy.


tortoise is slow

A very common UI need is some sort of spinner or other "waiting" indicator to let the user know that their call is very important to you request has been submitted to The Cloud.

Thankfully, htmx has this common usage covered with hx-indicator.

It works by letting you target any element on the page with a CSS selector (typically by ID or class) or you can also use magic like closest div or closest img. While a request is "in flight", a htmx-request class is added to the targeted element.

In the example below, I have three <div> tags with IDs (one for each button). They all have the tortoise-indicator class so that they don’t display until they are needed. As explained above, the htmx-request class will be added, so that’s how I make them display as needed. Here’s the CSS:

.tortoise-indicator { display: none; }
.htmx-request.tortoise-indicator { display: inline; }
Fetching... fast tortoise animated gif
Fetching... fast tortoise animated gif
Fetching... fast tortoise animated gif
Response will display here!

Side note: I made the little tortoise animated GIF featured in the example above in Krita. Using just the official tutorial, I was able to go from knowing nothing to a completed animation in a single evening. Krita is an amazingly polished FOSS application!


a backpack full of foxes

You can use hx-params to either exclude (filter) certain parameters from a request.

Or you can use it to include values from nearby form elements as parameters for a method which wouldn’t normally do so such as GET:

By default hx-get does not include any parameters. You can use the hx-params attribute to change this — hx-get reference

I couldn’t actually get the include-in-a-GET to work outside of a <form> until a reader emailed me and pointed out the magic combo (thanks!). See the relevant part of this Stack Overflow answer.

The following examples show how you can use the filtering aspect of hx-params.

You can use wildcards or list fields by name to include:

This form has
hx-params="fox1, fox2"
and will only submit those fields.
Response will display here!

Or you can exclude specific fields:

This form has
hx-params="not fox1"
and will submit all but that field.
Response will display here!


this is a drawing of patch. behold.

An HTTP PATH request is for updating or changing parts of a document. This is in contrast with PUT, which is for completely replacing a document with a new one.

Response will display here!


drawing of posty the post

Makes the element perform an HTTP POST request when it’s action is triggered (usually a click). This is just like the GET (hx-get) we saw above, but it’s a POST instead!

(Posty the Post would like it very much if you would send a POST request with the example below. Thank you.)

Response will display here!


2022-04-28: I’m changing how I continue this! I was creating the technical examples, drawing animals, and writing the creative text all at once. I’ve always found it hard to "shift gears" like this. So I’m going to continue (as of hx-preserve) in more of a phased approach: do all of the technical work (example code) first, then write the creative text, then make a final pass to create the art (probably improving what’s currently there to make it all more consistent).

Put this attribute (and an id attribute!) on an element. When htmx would normally replace it with new content, it will instead be preserved (its replacement must have the same ID).

In the example below, the HTML contenteditable property has been set on two div elements. But only the top one has the hx-preserve property (and an id). Try editing the text in both elements and then use the Request Fruit Preserve to get a fresh set of preserves and see what happens.

Response will display here!


This example is minus the creative stuff. But it does work. This is the last thing I completed.

Response will display here!


This is the last working example.

Here’s the page we’ll be loading below. This is just a regular link: push1.

After clicking this button, look at your browser's URL bar.

Response will display here!







Wondering how the "Show Source" links work? Click the one in this box to find out!