About two months ago I hopped on the Tailwind.css train. I've written websites for many years. Mostly for enterprise or internal tooling, a few public websites as well. I can say for sure this is going to be the pattern I'm going to use for a long time. It just gets it right. Let me trying to explain why.
First, learn CSS
Look you can't really escape it, if you want to use tailwind.css, knowing vanilla CSS is a prerequisite. You have to understand the box model, and the basic CSS properties that you need to get a basic website layout going. For me I learned that by trial and error over the beginning of my career. It's worth while, get down to the metal. I assure you it's much easier to learn today than it was 10 years ago. There are way better primitives now (🙏 thank god for flexbox).
Second, learn to hate CSS
Once you get decent at CSS you'll start to get creative. That's when things start to fall apart. You'll spend your time trying to refactor your CSS into the most logical classes so that you can by DRY. This is normal. I don't care whether you write Python, R, CSS or C++, everyone does it. You'll quickly realize you are spending 80% of your time obsessing over an abstraction before you have all the requirements rendering your beautiful class structure useless.
CSS is particularly dangerous in this regard because everything is global by default. Changing one attribute in your beautiful class structure can have wide ranging effects in your UI. Your abstraction ends up having the opposite effect it was designed for. It makes the codebase unapproachable to new developers on your project. To stay safe, they end up just creating a new class for what they want to do. Your beautiful garden is tainted, and within 6 months you'll have 4MB of CSS shipped to the browser on page load.
Everyone hits this point and they try to do two things.
- Use some fancy toolchain to purge unused CSS, or inline the above the fold or critical CSS.
- You'll ditch the entire thing for a CSS Component Framework
Both will be a waste of time.
Fancy CSS Toolchains
The community has gotten pretty fancy with these. To be honest, some of them are pretty clever. Facebook for instance did some real fancy shit with their latest website redesign. They have some toolchain that goes through their site and refactors into utility classes and modifies the HTML to use utility classes that minimize the amount of CSS that they have to ship. It's clever but it makes your production markup really hard to debug when there are visual errors. You can solve that by getting into CSS sourcemaps, but at that point are you really solving the problem?
On the surface this doesn't seem like a bad option. Millions of websites were built with bootstrap right? But hey, you're a modern web developer, you don't build with raw HTML, you're using React. Okay great, time to pull the React version of the component library.
Everything is going great until you realize some of the components maintain their own margin and now the components that looked beautiful on their own look super janky next to eachother. The minute you want to do anything custom you find yourself ejecting yourself from the framework then wrestling against it writing a bunch of custom CSS anyways. It won't take long.
Years of misery ensue
This was the state of CSS for years. On one side you had the purists that would insist you build the semantic web and write custom CSS for everything. On the other side you had the latest CSS framework released by company X with it's bloat, it's own unique set of primitives and naming scheme.
We were stuck in this pattern for years.
Adam hits the scene
That's when this clever fucker decided he had enough. He had looked at the problems:
- CSS has global variables everywhere, global variables are bad
- I don't want to learn yet another set of components
We're all writing React, Vue, or w/e anyways. Components have taken over web development, why are we inventing parallel component systems that we're going to wrap with react anyways? At the end of the day we all end up falling back to CSS anyways.
Stop wrestling with mutliple component systems, keep it simple
Let's go back to basics.
- Don't abstract before you need to
- Things that change together should be together
- We already have components
Tailwind.css, embrace the utility class
That when Adam introduced tailwind.css. The premise is simple. There are a finite number of CSS properties that we actually use. Make a CSS class for each one, then string them together in HTML.
ml-4, that it. Just a bunch of terse CSS classes that are named exactly after the CSS properties they represent.
Thomas, this is disgusting, your HTML offends me
Every person cringes when I show them tailwind for the first time. The reactions are all same:
- This makes the HTML so ugly
- You're repeating yourself all over the place, have you heard of DRY?
- This defeats the purpose of CSS
Hell, I had the same reaction. But there's a beauty to it. Not only that, the boon to productivity is insane.
First let's concede one basic fact. Often when you are building a website you have to jump back and forth between HTML and CSS to get your layout correct. Maybe you're working off a design and you have enough experience that you're going to need to wrap the piece of text in a span so you can get the vertical alignment correct, but the reality that CSS is weird and often you need to jump back to the HTML to add an extra div to get things working the way you want. If you aren't working from a design, then good luck. You'll be jumping between CSS and HTML all the time. Here's where the first benefit comes in.
You don't have to switch files to get your UI correct. It's so simple. You edit the structure of the HTML and the styles of the nodes side by side.
Things that change together should be together
"But Thomas you're repeating yourself all over the place", you'll say. Am I though? It's 2020, i'm using react. I hope you're using at least some kind of component library. If you're writing a list of things, a
.map function takes care of the reptition for you. If you are truely using the same HTML and style in multiple places (you're probably not) then you can refactor it into a react component. Problem solved. If not, just copy the JSX and modify the styles to customize it to that page's specific use case.
Most developers abstract prematurely. Chances are you shouldn't be writing that component in the first place. Write once, write a second time, only on the third time should you consider refactoring. That's what Jeremy Karn taught me that dude is pretty smart.
If you really need to, you already have react. Don't create parallel component systems.
And finally let's talk about bundle size. This one was a bit of a surprise to me. When I first starting considering tailwind I figured it was just going to be like any other CSS framework, bloated and big. After all they were creating a class for every property. Surely that's going to be a lot of CSS.
By default you'd be right. The raw CSS for tailwind is
348kb raw. But here's the thing. Remember those fancy toolchains we were talking about earlier. Well it turns out purging unused is a much simpler problem then trying to refactor css into the optimal set of utility classes (kudos Facebook for actually doing that).
Tailwind.css supports purging unused CSS at build time as part of the framework. Doing this with Next.js is super simple. For a site like https://billclintonswag.com/ I end up only using about
9.4kb raw of CSS and it's completely extensible.
Compare that to those using custom CSS classes for each node in the HTML graph and you'll find yourself using at least 10x fewer bytes for your CSS.
Take the dive, it's worth it
I'm telling you it's worth it. I've been writing websites for a long time. I can turn a full page mockup into code in ~30-45 minutes. The CSS is small and it's really easy to fix visual bugs.
If you want to learn more, I highly suggest watching a few of Adam Wathan's YouTube videos. He walks through building tons of example sites using tailwind. There are so many little tips and tricks in these videos that will make you incredbily productive about building beautiful websites.