Dynamic Web Apps without JavaScript - HTMX Showcase at DjangoCon and Devoxx

Dynamic Web Apps without JavaScript - HTMX Showcase at DjangoCon and Devoxx


By: Bruno Couriol

From InfQ.com: October 21. 2022.

DjangoCon and Devoxx Belgium recently reported examples of interactive web applications developed without JavaScript developers. The showcased htmx HTML-first framework seems to target those applications that mainly propose a friendly interface to CRUD operations over remote resources. In one case, the team was able to remove the JavaScript developer.

At DjangoCon 2022, David Guillot reported reimplementing his company’s SaaS product with HTML-first framework htmx in two months with the following results:

Guillot gladly mentioned that 15,000 lines of JavaScript code disappeared from the codebase; performance improved (as measured by time to interactive and memory usage); the only JavaScript developer in the team left and back-end developers turned to full stack developers.

The htmx team however warns that such spectacular results were achieved because this particular SaaS application was a good fit for htmx’s HTML-first approach:

These are eye-popping numbers, and they reflect the fact that the Contexte application is extremely amenable to hypermedia: it is a content-focused application that shows lots of text and images. We would not expect every web application to see these sorts of numbers.

However, we would expect many applications to see dramatic improvements by adopting the hypermedia/htmx approach, at least for part of their system.

At Devoxx Belgium 2022, Wim Deblauwe showcased the kind of interactivity that htmx can implement without any JavaScript: search-as-you-type input field, update of the user interface as some remote resource is affected by CRUD operations, regularly refresh the user interface with server-sent data, and more.

The htmx team considers an application a good fit for the framework if the UI is mostly text and images; the UI mostly interfaces CRUD operations; and HTML updates mostly take place within well-defined blocks. Conversely, applications with many, dynamic interdependencies, that require offline functionality, or update state extremely frequently would not be a good first for htmx’s hypermedia approach.

In an htmx application, the server returns pages or fragments of pages.

<button hx-post="/clicked"




    Click Me!


The previous HTML excerpt encodes that when a user clicks on the button, htmx issues an HTTP POST request to the /clicked endpoint. Htmx uses the content from the posterior response to replace the element with the id parent-div in the DOM. With htmx, any element (i.e., not just anchors and forms), any event can trigger an HTTP request. The HTML response from the server only updates the relevant part of the UI. For the full overview of htmx capabilities, developers may refer to the documentation.

Interestingly, htmx is often showcased by back-end developers who belong to non-JavaScript ecosystems (e.g., Python/Django/Flask, PHP/Laravel, Ruby/Ruby on Rails). As Guillot mentioned, with htmx, back-end developers extend their scope to the entire stack without having to learn JavaScript, npm, Webpack, React, CSS-in-JS, and many more. Matt Layman, in his You don’t need JavaScript talk summarizes:

"It’s just this constant churn in the [JavaScript] ecosystem and adding a lot of complexity onto a flow when you’re trying to deliver a web application. You want to just get an experience out there that actually works for people. But then you end up fighting with [the toolchain].

At a certain amount of scale, JavaScript can be a fantastic thing to build into your applications. But for an average person or a small team, it’s a ton of extra complexity so my recommendation is: just don’t. We have other options."

htmx is an open-source project under the BSD-2-clause license.

htmx claims to provide AJAX, CSS Transitions, WebSockets, and Server-Sent Events directly in HTML, using attributes, so developers can build user interfaces with the simplicity and power of hypertext.


  • Roy Fielding, Architectural Styles and the Design of Network-based Software Architectures


More references here

Let’s look at the first feature of htmx: the ability of any web page element to issue HTTP requests. This is the core functionality provided by htmx, and it consists of five attributes that can be used to issue the five different developer-facing types of HTTP requests:


Issues an HTTP GET request.


Issues an HTTP POST request.


Issues an HTTP PUT request.


Issues an HTTP PATCH request.


Issues an HTTP DELETE request.


Relative Positional Expressions in Htmx.
  • next - Scan forward in the DOM for the next matching element, e.g., next .error
  • previousScan backwards in the DOM for the closest previous matching element, e.g., previous .alert
  • closest - Scan the parents of this element for the matching element, e.g., the closest table.
  • find - Scan the children of this element for matching element, e.g., find the span.
  • this - the current element is the target (default)


The hx-swap attribute supports the following values:

  • innerHTML - The default, replace the inner html of the target element.
  • outerHTML - Replace the entire target element with the response.
  • beforebegin - Insert the response before the target element.
  • afterbegin - Insert the response before the first child of the target element.
  • beforeend - Insert the response after the last child of the target element.
  • afterend - Insert the response after the target element.
  • delete - Deletes the target element regardless of the response.
  • none - No swap will be performed.

  • settle -Like swap, this allows you to apply a specific delay between when the content has been swapped into the DOM and when its attributes are “settled”, that is, updated from their old values (if any) to their new values. This can give you fine-grained control over CSS transitions.

  • show - Allows you to specify an element that should be shown — that is, scrolled into the viewport of the browser if necessary — when a request is completed.
  • scroll - Allows you to specify a scrollable element (that is, an element with scrollbars), that should be scrolled to the top or bottom when a request is completed.
  • focus-scroll - Allows you to specify that htmx should scroll to the focused element when a request completes. The default for this modifier is “false.”




“Pushes” the request URL (or some other value) into the navigation bar.


Causes a client-side redirection to a new location


Preserves a bit of the DOM between requests; the original content will be kept, regardless of what is returned.


Synchronized requests between two or more elements.


Disables htmx behavior on this element and any children. We will come back to this when we discuss the topic of security.




Let the user know that a search is in progress.

HTTP Request

When placed on an element, each attribute tells the htmx library: “When a user clicks (or whatever) this element, issue an HTTP request of the specified type.”


This will be the string “true” if the request is made via an element using hx-boost.


This will be the browser's current URL.


This will be the string “true” if the request is for history restoration after a miss in the local history cache.


This will contain the user response to an hx-prompt.


This value is always “true” for htmx-based requests.


This value will be the id of the target element if it exists.


If it exists, this value will be the name of the triggered element.


If it exists, this value will be the ID of the triggered element.
once. The given event will only trigger a request once.
  • delay - Allows you to specify a delay to wait before a request is issued. If the event occurs again, the first event is discarded and the timer resets. This allows you to “debounce” requests.

  • changed - Allows you to specify that a request should only be issued when the value property of the given element has changed.

  • throttle - Allows you to throttle events, only issuing them once every certain interval. This is different than delay in that the first event will trigger immediately, but any following events will not trigger until the throttle time period has elapsed.
  • from - A CSS selector that allows you to pick another element to listen for events on. We will see an example of this used later in the chapter.
  • target - A CSS selector that allows you to filter events to only those that occur directly on a given element. In the DOM, events “bubble” to their parent elements, so a click event on a button will also trigger a click event on a parent div, all the way up to the body element. Sometimes you want to specify an event directly on a given element, and this attribute allows you to do that.
  • consume - If this option is set to true, the triggering event will be cancelled and not propagate to parent elements.
  • queue - This option allows you to specify how events are queued in htmx. By default, when htmx receives a triggering event, it will issue a request and start an event queue. If the request is still in flight when another event is received, it will queue the event and, when the request finishes, trigger a new request. By default, it only keeps the last event it receives, but you can modify that behavior using this option: for example, you can set it to none and ignore all triggering events that occur during a request.

No comments:

Post a Comment