How I style HTMX apps with Tailwind CSS
Date: 2024-06-07 | create | tech | htmx | tailwind | web-apps |
HTMX is changing the way we build web apps - essentially unlocking SPA-like user experiences with the simplicity of MPAs. It's certainly changed the way I build web apps, freeing me to move away from frontend frameworks like SvelteKit and towards fullstack moduliths in my favorite language F#.
Tailwind is a popular tool for styling apps with CSS in a composable, ergonomic way. I personally like building with Tailwind because it makes styling less of a chore - it's easy to tweak styles here and there with just a few class changes, without digging through nested CSS classes. I often couple it with Daisy UI to get a balance of ready-to-use components and easy customizability (that's what's styling this site right now).
HTMX is still growing in popularity and I see a lot of confusion in how to do common things with it so in this post we'll explore how to use Tailwind in HTMX apps.
Want to support HTMX / get some swag? Check out the official HTMX Swag store. (not sponsored I just like HTMX and want to support creator).
HTMX apps are MPAs
A lot of the confusion around HTMX I think originates from a core misunderstanding of what HTMX is and what that means for building web apps. Here's my take:
- HTMX is a library you load on a web page
- HTMX allows the webpage to ask the server for HTML partials (as opposed to MPAs which usually ask for full HTML pages)
- The server supports HTMX by adding / modifying endpoints so they can return HTML partials (as opposed to full HTML pages like MPAs)
Put simply - most HTMX apps are really just MPAs with a bit of extra server endpoints / logic to enable sending HTML partials instead of the full HTML page.
This means that we can use the same techniques for styling MPAs with CSS to style HTMX apps with CSS.
Styling MPAs with Tailwind
Okay so we've established that HTMX apps are basically just MPAs which means we can style HTMX apps with Tailwind in the same way we style MPAs with Tailwind. So now let's look at how we can style MPAs with Tailwind.
Tailwind is a bit more complicated than simply including a CSS file in your webpage. You do use Tailwind by simply including a CSS file in your webpage but typically you don't want to do this with vanilla Tailwind as the payloads are too large (order of megabytes). Instead it's recommended to use a Tailwind build step so that it prunes itself of all the unused styles to get the small (low kilobyte) payload it's famous for.
Exactly how you setup this Tailwind build step largely depends on what technology you're using to build your app. One of the big unlocks of HTMX (really Hypermedia) is that it is backend agnostic - you can build it with basically any language you want. But this does mean that there are many different ways to use Tailwind and thus that the specifics will be different for each.
That said using Tailwind outside of the JS ecosystem generally follows a common pattern:
- Create a Tailwind project in your repo
- Setup a build step that runs Tailwind CLI, pointing it at your source code files that may contain HTML/X (and thus see the Tailwind classes you're using)
- Configure the output to be placed in a static resource folder your app will serve
- Setup your webpages to reference the output Tailwind file
This allows your Tailwind CSS to update based on the styles you're using every time you build the app. It outputs these styles in a usable location which your app can then pull into its webpage when it needs it.
How I use Tailwind CSS to style HTMX
The above steps are a bit vague because specifics largely depend on your tech stack of choice. Here I wanted to give a more concrete example of how I do this with my tech stack of choice - SSR HTML/X served with F# / Giraffe (ASP.NET).
For a more detailed guide on how I do this (including source code) checkout: Building ASP.NET apps with Tailwind CSS
Project Setup:
- F# app - Includes my frontend and backend code (I use an HTML DSL (Giraffe.ViewEngine) to create HTML in a type-safe manner)
- Tailwind CLI - A node project with all my configurations for styles and included dependencies (I often use DaisyUI and Tailwind Typography)
I like to build my apps with containers because I find containers to be a 3S for building and deploying apps anywhere. It makes it very easy to get ~deterministic builds locally and remotely and also has nice features for doing build-time configuration as we'll leverage here.
Building:
- Tailwind step - Parses F# code to find Tailwind classes, outputs its pruned CSS
- F# step - Builds my F# app
- Output step - Copies the Tailwind output into the F# static folder and runs the app
This is a lot of steps but I want to be clear that it is the same amount of steps for HTMX as it is MPA. There is no extra thing needed for HTMX as HTMX is simply HTML so it plays the same way.
Next
This is basically how I'm building / styling all my apps these days. I've found it's brought the joy back to building web apps - I don't have to learn the latest framework / feature, I can just build using technologies and techniques I like and am used to.
Q: How are you styling your HTMX apps?
If you liked this post you might also like:
Want more like this?
The best / easiest way to support my work is by subscribing for future updates and sharing with your network.