Dave's htmx Live Reference

Created: 2021-11-27 Updated: 2022-01-18
This page is a draft and may be incomplete, incorrect, or just a stub or outline. I've decided to allow myself to put draft pages on my website as an experiment. I'm hoping they will:
  • Help me address my backlog of article ideas.
  • Serve as a "living" TODO list of things to work on.
  • Be useful to myself or others in their incomplete forms.
As always, I'm happy to accept feedback on anything I publish including draft content.
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.

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"):

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:

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. TODO: link to the attribute as soon as I have an example. :-)

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!

More coming on a regular basis...
Check the Updated date at the top of this page to see how I'm doing.
rather overdone htmx letters as a negative image of a living mass of vines

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