The Awesome Things You Can Do With HTMX

The Awesome Things You Can Do With HTMX

Imagine a framework that gives you all the benefits of a modern UI framework such as React or Vue.js, as well as the simplicity of HTML.

Yes, such a framework exists, and its name is HTMX.

The HTMX framework enhances HTML by giving you the ability to access AJAX requests, transitions, WebSockets, and Server Sent Events right from your markup.

Learn about the advantages of using HTMX and how you can integrate it into your web application. By the end of this article, you might consider replacing HTMX with whatever UI framework you're using; who knows?

Sidenote: If you’re new to learning web development, and you’re looking for the best resource to help with that, I strongly recommend HTML to React: The Ultimate Guide.

What is HTMX?

HTMX allows you to create highly interactive sites with just HTML. It provides special attributes for adding dynamic behavior to your web page without using JavaScript. This makes it easier to build interactive user interfaces.

Consider the following anchor tag, for example:

<a href="/blog">Blog</a>

When you click on this link, the browser issues an HTTP request to /blog and renders the HTML page corresponding to that route.

The only other time you can make an HTTP request in HTML is when you click on the submit button inside a form.

With HTMX, however, you can make an HTTP request from any element on your page. For example, consider the following button element which has been enhanced with HTMX attributes:

<button hx-post="/get-data"
    hx-trigger="click"
    hx-target="#parent-div"
    hx-swap="outerHTML"
>
    Click Me!
</button>

When you click this button, the browser makes an HTTP POST request to /get-data, gets the content from the response, and uses it to replace the element with an ID of "parent-div" in the DOM.

This essentially makes HTMX an extension of HTML that allows you to:

  • Issue an HTTP request from any element, not just anchor links and forms

  • Trigger requests with any event, not just clicks or form submissions

  • Use any HTTP verb, not just GET or POST

  • Target any element in the DOM and update it using the response content

Advantages of using HTMX

Here are four benefits of using HTMX on your website:

  1. Easy to use and learn: If you're familiar with HTML, then you can easily learn HTMX. The library is perfect for developers who are not familiar with JavaScript, or those who want to create dynamic and interactive websites as quickly as possible.

  2. Better performance: HTMX renders components from the server. Therefore, it offers better performance by taking work away from the client-side to the server-side. This results in faster page load speed and an overall better user experience.

  3. Greater accessibility: Because HTMX was created with user accessibility in mind, it's great for building websites that are accessible to everyone (especially those with disabilities).

  4. Cutting-edge SEO: From the use of semantic HTML to clean URLs, HTMX includes all the essential features that'll make your website rank well in search results.

Next, let's see how to use HTMX in a real-life project.

Getting Started With HTMX

To install HTMX, import it in a <script> tag from the head of the HTML document like so:

<!DOCTTYPE html>
<html lang="en">
<head>
   <script src="https://unpkg.com/htmx.org@1.9.2"></script>
</head>
<body>

</body>

Now you can use HTMX attributes on HTML elements within the <body> tag in your document.

To handle the API requests, you need to create a server in your favorite programming language that returns HTML text as a response.

For this tutorial, we'll go with an express server. You'll need to have Node.js installed on your local machine to follow along.

  1. Create an empty folder

  2. Launch your command prompt

  3. cd to the directory you just created

  4. Run the following command to create a Node project:

npm init -y

Next, install express:

npm i express

NOTE: I have a full-stack web development course that'll teach you how to build an application from scratch. You can get it here.

Now that the set-up is complete, let's dive deep into the meat of things.

Issuing an API GET request with HTMX

You make an HTTP GET request in HTML with the hx-get attribute. The value of this attribute should be the API endpoint you want to access:

<button 
  hx-get="http://localhost:5000/say-hello"
  hx-swap="outerHTML"
>
  Click me!
</button>

In this case, you're replacing this particular element (the button) with the content of the API response.

Alternatively, you can replace a different element by including the hx-target attribute. This attribute should point to the element you want to replace the API response with on the page:

<button 
  hx-get="http://localhost:5000/say-hello"   
  hx-target="#responseDiv"
  hx-swap="outerHTML"
  >
  Click me!
</button>

<div id="responseDiv">

</div>

This is going to replace the entire <div> element with the content of the API response. If you want to instead replace the inner HTML, then you need to pass the "innerHTML" value to hx-swap.

The following image is an illustration of the different values supported by hx-swap and the part of the UI they replace:

Now to set up the server and API endpoint, create a server.js file and include the following code:

const express = require('express')

const app = express()

app.get('/say-hello', (req, res)=> {
    res.send("Hello!")
})

app.listen(5000, ()=> {
    console.log("Server is active")
})

Start the server by executing the following command:

node server.js

When you click the button, it'll make a GET request to the server, take the response and use it to replace the target element asynchronously.

Some notes:

  1. You can also make a post, put, and delete request by appending the HTTP verb to "hx-" on the element (i.e. hx-post, hx-put, etc).

  2. The hx-target attribute allows you to find that element with a CSS selector, but it has additional syntax like next and closest (allows you to easily find the right element without a bunch of custom ids):

<button 
  hx-get="..."   
  hx-target="next #responseDiv"
  hx-swap="..."
  >
  Click me!
</button>

<div id="responseDiv">
</div>

Let's move on to events.

Setting a custom event as the trigger in HTMX

The hx-trigger attribute allows you to customize the event on which the API request is triggered. You can also use modifiers like delay and throttle to control the way the request is sent:

<button 
  hx-get="..." 
  hx-target="..."
  hx-trigger="keyup changed delay:1s"
>
  Key up

  <img class="htmx-indicator" src="spin.gif" />
</button>

In this case, the HTTP GET request is issued when you trigger the keyup event on the button.

While the request is still being processed, we use .htmx-indicator to show a loading spinner and write a CSS transition animation for the incoming element:

.htmx-indicator {
  opacity: 0;
  transition: opacity 500ms ease-in;
}

.htmx-request .htmx-indicator {
  opacity: 1
}

.htmx-request.htmx-indicator. {
  opacity: 1
}

The best part is that you did all of this without writing a single line of JavaScript code.

Using the client-side router

The HTMX library also has a client-side router called boost, that can make any traditional web application feel like a faster single-page application:

<div hx-boost="true">
  <a href="/home">Home</a>
  <a href="/about">About</a>
</div>

Basically, it swaps the different pages into the <body> tag. This is the same behavior you'd get with SPA frameworks like React and Vue.js.

<body>
  <!-- Dynamically inserts the current page here -->
</body>

The library also provides extensions for more advanced features like web sockets and integrations with other HTML frameworks like Alpine.

List of HTMX extensions

Event System

HTMX has a large event system that you can leverage by listening to the custom event with JavaScript. The following code will run just before you're about to swap an element. It checks if the status code is 404 and responds with a "Page not found" alert (if that's true):

document.body.addEventListener('htmx:beforeswap', (ev) => {
  if(ev.detail.xhr.status === 404) {
    alert("Page not found!")
  }
})

The hx-on attribute allows you to bind a JavaScript function to any element in case you want to execute your own client-side JavaScript:

<button hx-on:'click: alert('clicked!')'>
  Click me!
</button>

If it's a function, just ensure that you define the function within the <script> tags and you're good to go.

Final thoughts

I hope you learned something new from this article. Furthermore, I would encourage you to get my full-stack web development course if you're looking to build an awesome project from scratch.