I just finished migrating this website from CSS Modules to Tailwind. Overall it was a straightforward, but long process. The transition has proven to be worth it, and I'll explain my thoughts on the outcome below.
🧬 better defaults
If nothing else, Tailwind starts you off with a better set of defaults. They accomplish this with a CSS reset pulled in with the
@tailwind base directive. The Tailwind reset goes above and beyond, and really sets you up with a proper blank page without the need to constantly override default browser styles.
Tailwind also provides you with a stellar set of design tokens out of the box. Everything from colors, to box shadows, to spacing have all been excellently designed for you to utilize.
If you opt into some of Tailwind's official plugins, they offer great additional features. For example, the typography plugin provided much better styling for my
markdown content than I had created myself.
✍🏼 authoring experience
While the authoring experience of Tailwind is its number one criticism, I didn't find it to be that bad. I really love the fact that I'm able to write my styles directly next to the elements that they affect rather than off in another file.
I also don't have to spend any time thinking about class naming, with the exception of a few Tailwind classes that confuse me every time! Specifically the grid placement classes. Sometimes you have to be specific about the placement direction, like
align, other times you have to be specific about the thing you're placing, like
items, and sometimes it's a mix of both.
Luckily, Tailwind has an awesome vscode extension that not only autocompletes class names for you, but also shows the associated CSS output! This plugin is super helpful on all properties with only a few exceptions. For example, I found that when it autocompletes
border, it places all of the different
border-spacing values at the top of the list, forcing me to scroll way down to reach more relevant classes like
💯 incredibly maintainable
The biggest benefit that Tailwind offers is its long term maintainability. While making this transition, I was able to remove the majority of a
global.css file. Modifying those styles was incredibly difficult because I didn't know which parts of the website would be affected. With Tailwind, all styles are declared right on the elements they modify, which means no scoping issues. Despite being pretty verbose, I actually removed code during the migration.
But that doesn't mean Tailwind is not reusable. You can still leverage the cascade with Tailwind's class based styling. Instead of declaring a
font-family on every element, you can place the class high up in the DOM and the styles will apply to all children.
If you ever need to break free from Tailwind's out of the box classes, you can use arbitrary values, or customize your configuration. While I did a fair bit of customization, my configuration was only 59 lines of code.
🏎️ performance improvements
Most importantly, Tailwind brought performance improvements to my website. Primarily this was through reducing the amount of HTTP requests. It turns out that Next.js preloads CSS Modules for client side routing to adjacent pages, which caused seven extra requests on my home page. Given that I'm moving to Remix soon, I won't have much use for client side routing.
This reduction in HTTP requests ultimately lead to faster load times on my website by about
200ms and a reduced page weight of around
🙌🏼 framework integrations
While Tailwind does integrate well with Next.js through create-next-app, that only supports new projects. As I mentioned before I'll be moving to Remix, which is getting first class Tailwind support very soon.
🧶 wrap up
Overall I'm very happy with my migration to Tailwind. It took longer than expected, and rewriting everything from scratch would have probably been quicker, but I liked perspective it gave me. Tailwind has a great developer experience, it improved performance on my site, and gives me a great base to start styling with.