htmx is a small, lightweight library that shifts the focus of web front-end development away from JavaScript and large single-page applications back to the origins of the web. In this article, we’ll take a look at the features and uses of htmx.
With their component-oriented architecture, major SPA frameworks like Angular, React, and Vue are committed to a declarative approach. However, the origins of this type of development lie in HTML. With HTML, you follow a semantic structure of your documents. You describe the structure of the website that users receive with a defined set of elements, each with a specific meaning. htmx takes on this idea and extends the possibilities of HTML.
The htmx website provides a nice overview of the library’s core:
In summary, this means you can keep your familiar HTML structure and extend it selectively. The focus of htmx is on server communication and state transition animations. You can also implement the standard use case of an SPA, a simple CRUD application, with these. They are significantly more lightweight in the process.
You can install and integrate htmx in a variety of ways. These range from loading via a CDN, downloading the source code and delivering it statically via a web server, to using a package manager and a bundler like webpack, Rollup, or Vite.
The easiest way to get started with htmx is to use a CDN. You can include it with an ordinary script tag and refer to unpkg.com. Listing 1 contains a simple example that clearly shows how htmx works.
Listing 1: Hello World in htmx
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
<script src="https://unpkg.com/htmx.org@1.9.4"></script>
</head>
<body>
<output></output>
<button
hx-get="/hello"
hx-trigger="click"
hx-target="output"
hx-swap="innerHTML"
>
say hello
</button>
</body>
</html>
This code example shows how to integrate htmx into an HTML document header using a CDN. The core of the example is the button element. The four attributes beginning with hx- tell htmx to send an HTTP request when the button is clicked and insert the response into the document.
Individual attributes in the example include:
For the example to work, you need a web server that delivers the source code and responds to a GET request to the URL /hello with an HTML structure.
htmx works with the standard elements of HTML and relies on special attributes. For this, the library searches the DOM structure for the attributes and evaluates them. For the attributes, htmx registers handler functions that are activated once the events are triggered.
Although this example illustrates the principles of htmx well, it’s a long way from a realistic application. But this will change in the next step.
One of the most important features of a typical CRUD application is displaying an overview list. You can render a list on the server side and deliver it to the browser as static HTML. However, you can also use htmx and first display the frame application and load the actual list dynamically. In our example, we will implement an application for managing books, starting with a list of data records. You will need a web server that delivers the base document and renders a series of table rows when the /books path is requested.
Listing 2: List rendering with htmx
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
<script src="https://unpkg.com/htmx.org@1.9.4"></script>
</head>
<body>
<table hx-trigger="load" hx-get="/books" hx-target="tbody">
<thead>
<tr>
<th>Titel</th>
<th>Autor</th>
<th>Veröffentlichungsjahr</th>
<th>Seiten</th>
<th>Sprache</th>
</tr>
</thead>
<tbody>
<tr>
<td colspan="5">Lade Daten</td>
</tr>
</tbody>
</table>
</body>
</html>
In this example, you take advantage of the fact that every element can trigger a request, even for any event. In this case, the table element is responsible for displaying the book list. The event is the load event and the target is the contained tbody element in the table. When the table is loaded, the browser sends a request to the server and loads the actual content. In the meantime, the browser displays information that the data is being loaded. Once the response from the server is available, htmx replaces content from the tbody element with the response from the server.
If everything goes according to plan, you’ll briefly see the loading information and after just a few moments, the finished table with the data records. But what happens if an error happens on the server side? What if, for instance, the server does not respond with a status code 200 and the desired content, but with an internal server error? In this case, you also want to replace the load information with an error message after receiving the response. htmx focuses on the success case, which is why it’s conveniently implemented. For error handling, you can fall back on several approaches, two of which I’d like to present: handling the htmx error event and an extension for dealing with errors.
htmx can trigger a whole range of events during an application’s runtime. These range...