HTMX
About
-
A JavaScript library.
-
Embraces hypermedia controls.
-
Is it client-side or server-side? :
-
HTMX waits for a server response before updating the DOM.
-
It does not pre-render or simulate changes locally. Every interaction that uses
hx-get,hx-post, etc. involves a network round trip. The latency depends on server and network speed. -
Every interaction still depends on the server. Complex client logic still requires JS.
-
-
When to use it :
-
The HTMX’s purpose is to make hypermedia applications dynamic without a SPA stack .
-
Consider when:
-
You want progressive enhancement.
-
You want to scale from static HTML to interactive components gradually.
-
You prefer server-side rendering and logic centralization.
-
-
Static sites gain almost nothing from HTMX.
-
HTMX is meant for server-rendered web apps that need partial interactivity but don’t justify a client framework.
-
Examples:
-
Inline CRUD operations in admin dashboards.
-
Updating a comment section after submission.
-
Live search results or pagination without full reloads.
-
-
-
"Technical advantages of HTMX over JS" :
-
None.
-
JavaScript can do everything HTMX does.
-
HTMX does partial DOM replacement automatically via
hx-target. -
Vanilla JS can absolutely do the same thing; you just have to write the code yourself.
-
HTMX is syntactic and architectural sugar . It does not reduce network trips or make DOM updates faster.
-
It’s syntax sugar over JavaScript and
fetch(). -
Bandwidth and latency are identical; performance differences are minimal (tiny parsing/initialization cost of HTMX).
-
-
"Structural advantages of HTMX over JS" :
-
Architecturally, it enforces a different model.
-
It restores hypermedia-driven design — the server defines behavior through HTML responses.
-
It minimizes client-side logic and state, which cuts maintenance cost.
-
It integrates naturally with traditional SSR backends, avoiding SPA complexity.
-
HTMX’s value is that you write and organize far less of it, staying in HTML and server templates instead of managing JS code and build tooling.
-
-
What HTMX actually SOLVES :
-
Caio:
-
HTMX gives ergonomics over a very specific part of working with JS, but it doesn't seem like the part where HTMX helps is actually the part where sites suffer. I mean, I imagine that the real struggles of a site are handling responsiveness through client-side rendering, etc. My point is that I don't see a reason to spend time learning this new framework, which doesn't solve the important problems; it doesn't really solve anything....
-
-
Your conclusion is accurate.
-
HTMX solves a narrow problem: boilerplate around sending AJAX requests and swapping HTML.
-
It does not :
-
Improve responsiveness or reduce latency.
-
Solve client-side state management.
-
Reduce complexity in dynamic UIs with heavy interactivity.
-
Replace SPA frameworks for apps with complex rendering logic.
-
-
Its value is ergonomic and architectural, not technical performance
-
But in practice, for most modern web apps:
-
Real difficulties come from client-side rendering, state synchronization, and interactivity.
-
HTMX does not address these.
-
-
Characteristics
-
AJAX:
-
Declarative AJAX via
hx-get,hx-post, etc.
-
-
"HTMX writes JavaScript, so you don't have to".
-
Server-driven rendering; server returns HTML fragments
-
HTMX works by adding behavior through HTML attributes (
hx-get,hx-post,hx-target, etc.) inside normal markup. -
The HTML stays the primary language; the logic (interactivity, data fetching) is embedded declaratively within it.
-
It’s closer in spirit to Hugo, Jinja, or PHP templates, than to JSX or Svelte.
-
Enables HTML to trigger AJAX (Asynchronous JavaScript and XML), WebSocket, or SSE without writing JS
-
Runs directly in the browser.
-
Framework-agnostic, enhances plain HTML.
Comparisons
Without HTMX
-
Each interaction reloads the full page.
-
Developers must choose between full reloads or building a client app (React/Vue/etc.).
-
Ex1 :
button.addEventListener("click", async () => { const res = await fetch("/data"); document.querySelector("#result").innerHTML = await res.text(); }); -
Ex2 :
<button id="loadBtn">Load Items</button> <div id="result"></div>document.getElementById("loadBtn").addEventListener("click", async () => { const res = await fetch("/items"); // 1. Send AJAX request const html = await res.text(); // 2. Wait for server response document.getElementById("result").innerHTML = html; // 3. Update DOM });-
The code :
-
fetch-
A modern browser API to make HTTP requests (GET, POST, etc.).
-
By default, it sends a GET request to the URL.
-
Returns a Promise that resolves when the server responds.
-
awaitpauses the async function until the response arrives.
-
-
res.text()-
Reads the response body as plain text (HTML in this case).
-
Also returns a Promise, so
awaitis needed.
-
-
document.getElementById("result").innerHTML = html;-
Replaces the contents of the
#resultdiv with the HTML received. -
Only the contents of
#resultare replaced, just like in HTMX.
-
-
-
Step-by-step mechanics:
-
User clicks the button.
-
JS event listener fires.
-
JS issues a network request to
/items. -
Server responds with HTML.
-
JS inserts HTML into
#result.
-
-
Performance/Responsiveness:
-
One network round-trip per click.
-
DOM update is instant once response arrives.
-
Minimal CPU usage; modern browsers handle it efficiently.
-
Bandwidth = server response size only.
-
-
Pros:
-
Fully controlled in JS.
-
Flexible for complex logic before/after request.
-
-
Cons:
-
Boilerplate JS code for every button/form.
-
Requires attaching event listeners.
-
Harder to maintain at scale for multiple similar elements.
-
-
With HTMX
-
You keep a server-rendered architecture.
-
You get partial updates via HTML fragments instead of full reloads.
-
You avoid writing or maintaining JavaScript frameworks, build steps, or client-side state logic.
-
Ex1 :
<button hx-get="/data" hx-target="#result">Load</button> <div id="result"></div> -
Ex2 :
<button hx-get="/items" hx-target="#result">Load Items</button> <div id="result"></div>-
Step-by-step mechanics:
-
User clicks the button.
-
HTMX intercepts the click via its internal event delegation.
-
HTMX issues an AJAX GET to
/items. -
Server responds with HTML.
-
HTMX inserts the response into
#resultusinginnerHTMLby default.
-
-
Performance/Responsiveness:
-
Network round-trip identical to vanilla JS.
-
DOM update is comparable in speed.
-
Slight extra CPU overhead for HTMX event delegation (~1–2 KB script parsing, negligible for modern browsers).
-
Bandwidth identical (HTML fragment only).
-
-
Pros:
-
No JS boilerplate; behavior is entirely declarative.
-
Easily reusable: any button with
hx-*works automatically. -
Integrates cleanly with server-rendered templates.
-
Supports advanced behaviors (
hx-swap,hx-trigger,hx-vals,hx-indicator) without extra JS.
-
-
Cons:
-
Every interaction still requires a server round-trip (not instant).
-
Limited flexibility for complex logic compared to vanilla JS (requires
hx-onor external JS hooks). -
Adds a small client-side dependency.
-
-
Attributes
Get (
hx-get
)
-
By default, an HTMX response is put inside as a child of the element that made the request.
-
It replaces the content that was inside that element.
Swap (
hx-swap
)
-
It defines the placement strategy.
-
innerHTML-
Replaces the content inside the element.
-
The default value.
-
-
outerHTML-
Replaces the element itself, not the inside of the HTML element.
-
-
beforeend-
Inject right before the end of the target; before the closing tag.
-
-
afterend-
Inject right after the end of the target; after the closing tag.
-
Target (
hx-target
)
-
Uses a CSS selector to specify where the content should be placed.
-
It defines the place where it should be placed.
Events (
hx-on
)
-
You write JS inside, as a response to the event.
-
Embeds JavaScript inline to handle events directly in HTML.
-
How often is this used :
-
Most developers use
hx-*attributes for declarative behavior and attach broader JS logic via event listeners in separate scripts. -
hx-onappears mainly in:-
Small demos or prototypes.
-
Inline UI tweaks that don’t merit full scripts.
-
Cases where deployment constraints forbid custom JS files.
-
-
Production code usually avoids inline JS for readability, security (CSP issues), and maintainability.
-
So: common in examples, uncommon in real systems.
-