HTMX fait beaucoup parler de lui, souvent réduit à « le truc qui évite React ». C'est passer à côté de l'essentiel. Revenons à l'origine, à l'idée, à ce qu'il change vraiment — et à ce que prépare la v4.
D'où vient HTMX
HTMX est le successeur direct d'intercooler.js, une bibliothèque née au début des années 2010 qui ajoutait déjà de l'AJAX déclaratif au HTML — mais qui dépendait de jQuery. Réécrit de zéro, sans aucune dépendance, il est devenu htmx. Le projet est porté par Big Sky Software (Carson Gross et son équipe), fièrement « made in Montana ».
Le résultat tient en une ligne de script : environ 10 ko minifiés et compressés, zéro dépendance. On l'ajoute à une page existante sans build, sans bundler, sans écosystème à apprendre.
Le pourquoi : et si le HTML en faisait plus ?
HTMX part de quatre questions très simples sur les limites du HTML natif : pourquoi seuls <a> et <form> peuvent-ils émettre une requête ? Pourquoi seulement sur un clic ou une soumission ? Pourquoi uniquement en GET ou POST ? Et pourquoi devoir remplacer la page entière ?
En levant ces quatre contraintes, htmx « complète » le HTML en tant qu'hypertexte : n'importe quel élément peut déclencher une requête, sur n'importe quel événement, avec n'importe quelle méthode HTTP, et ne remplacer qu'un fragment de la page.
Ce que HTMX apporte
Concrètement, htmx ajoute quelques attributs : hx-get/hx-post (la requête), hx-trigger (l'événement), hx-target (où injecter) et hx-swap (comment injecter).
<button hx-post="/clicked" hx-swap="outerHTML">
Clique-moi
</button>Au clic, le bouton envoie un POST vers /clicked et se fait remplacer par la réponse. Pas une ligne de JavaScript. Surtout : le serveur renvoie du HTML, pas du JSON. Aucune sérialisation, aucune logique d'affichage à dupliquer entre le back et le front.
Sa place : les applications hypermedia
HTMX n'est pas qu'une astuce : c'est une façon de penser, l'application pilotée par l'hypermedia (HDA). Le serveur reste la source de vérité et renvoie des fragments de HTML ; le client se contente de les afficher. Pour le micro-interactif purement local (toggles, dropdowns), on saupoudre un peu de JS — Alpine.js se marie parfaitement avec. L'ouvrage de référence, Hypermedia Systems, détaille cette approche (gratuit en ligne).
HTMX ne remplace pas tout. Pour une application très stateful côté client (éditeur temps réel, canvas, jeu), un framework JS garde du sens. Mais pour un site de contenu, un back-office, un dashboard ou un CRUD — l'immense majorité du web — la question mérite d'être posée.
HTMX 2 vs HTMX 4 : ce qui change
La v4 est en chantier (sur four.htmx.org). Ce n'est pas un lifting de surface : elle modernise le moteur et durcit plusieurs comportements par défaut. Vue d'ensemble :
| Sujet | HTMX 2 | HTMX 4 |
|---|---|---|
| Transport HTTP | XMLHttpRequest | fetch() natif |
| Héritage d'attributs | implicite par défaut | explicite via :inherited |
| Réponses 4xx / 5xx | non swappées | swappées par défaut |
| Stratégies de swap | standard | + innerMorph / outerMorph, textContent, delete |
| Multi-cibles | <...> hx-swap-oob | + <hx-partial> |
| Par code HTTP | config globale | hx-status par code |
| Transitions de vue | via extension | natif (opt-in) |
| Timeout par défaut | aucun | 60 s |
| Événements | htmx:afterSwap… | htmx:after:swap (phase:action) |
| Extensions | attribut hx-ext | script inclus directement |
Quelques points méritent ton attention. Le passage à fetch() est définitif (impossible à rétablir). L'héritage d'attributs devient explicite : il faut désormais ajouter :inherited pour qu'un attribut descende dans l'arbre DOM. Et surtout, les réponses 4xx/5xx sont désormais swappées : si ton serveur renvoie du HTML avec un 422 ou un 500, ce HTML est inséré dans la cible. À toi de concevoir tes pages d'erreur en conséquence, ou d'utiliser le nouvel attribut hx-status.
<form hx-post="/save"
hx-status:422="swap:innerHTML target:#errors"
hx-status:5xx="swap:none">
<!-- champs -->
</form>La v4 apporte aussi des swaps morph (algorithme idiomorph : innerMorph/outerMorph) qui préservent l'état du DOM, l'élément <hx-partial> pour cibler plusieurs zones depuis une seule réponse, les transitions de vue natives (opt-in), et un timeout de 60 s par défaut. Les événements sont renommés selon un schéma cohérent htmx:phase:action (par ex. htmx:afterSwap devient htmx:after:swap).
Bonne nouvelle pour la migration : deux lignes de config — ou l'extension htmx-2-compat — restaurent le comportement de la v2, et un outil en ligne de commande (upgrade-check) scanne tes templates pour lister ce qui doit changer.
<script>
htmx.config.implicitInheritance = true;
htmx.config.noSwap = [204, 304, '4xx', '5xx'];
</script>Que faire avec HTMX ?
Les cas d'usage les plus naturels : la recherche live, la pagination / le défilement infini, les formulaires validés côté serveur, les dashboards rafraîchis sans rechargement, l'édition inline (CRUD), le chargement paresseux de fragments et les modales. Exemple d'une recherche instantanée :
<input type="search" name="q"
hx-get="/recherche"
hx-trigger="input changed delay:300ms"
hx-target="#resultats">
<div id="resultats"></div>Chez nous, sur Punky Tools (CodeIgniter 4), htmx est la colonne vertébrale de l'admin et des interfaces statistiques : on renvoie des fragments Blade, htmx les insère, Alpine gère le micro-interactif. Zéro rechargement, zéro state client à maintenir — et du code qu'on relit sans transpirer.
Le meilleur framework JavaScript, c'est parfois celui qu'on n'a pas à écrire.