Web Components Work Great with htmx
People interested in htmx often ask us about component libraries. React and other JavaScript frameworks have great ecosystems of pre-built components that can be imported into your project; htmx doesn’t really have anything similar.
The first and most important thing to understand is that htmx doesn’t preclude you from using anything. Because htmx-based websites are often multi-page apps (https://unplannedobsolescence.com/blog/less-htmx-is-more/), each page is a blank canvas on which you can import as much or as little JavaScript as you like. If your app is largely hypermedia, but you want an interactive, React-based calendar for one page, just import it on that one page with a script tag.
We sometimes call this pattern “Islands of Interactivity”—it’s referenced in our explainers here (https://htmx.org/essays/10-tips-for-ssr-hda-apps/#tip-8-when-necessary-create-islands-of-interactivity), here (https://htmx.org/essays/hypermedia-friendly-scripting/#islands), and here (https://htmx.org/essays/you-cant/#myth-5-with-htmx-or-mpas-every-user-action-must-happen-on-the-server). Unlike JS frameworks, which are largely incompatible with each other, using islands with htmx won’t lock you into any specific paradigm.
But there’s a second way that you can re-use complex frontend functionality with htmx, and it’s Web Components (https://developer.mozilla.org/en-US/docs/Web/API/Web_components)!
Practical Example (https://htmx.org/essays/webcomponents-work-great/#practical-example) Let’s say that you have a table that says what carnival rides everyone is signed up for:
Name
Carousel
Roller Coaster
Alex
Yes
No
Sophia
Yes
Yes
Alex is willing to go on the carousel but not the roller coaster, because he is scared; Sophia is not scared of either.
I built this as a regular HTML table (closing tags are omitted (https://developer.mozilla.org/en-US/docs/Web/HTML/Element/td#technical_summary) for clarity):
| Name | Carousel | Roller Coaster |
|---|---|---|
| Alex | Yes | No |
| Sophia | Yes | Yes |
Now imagine we want to make those rows editable. This is a classic situation in which people reach for frameworks, but can we do it with hypermedia? Sure! Here’s a naive idea:
That will give us this table:
Name
Carousel
Roller Coaster
Alex
Sophia
Save That’s not too bad! The save button will submit all the data in the table, and the server will respond with a new table that reflects the updated state. We can also use CSS to make the
Let’s remove all that redundancy with a web component!
We still have an entirely declarative HATEOAS (https://htmx.org/essays/hateoas/) interface—both current state (the value attribute) and possible actions on that state (the