Switching from "standard" CSS to Tailwind
Created //
TL;DR // It looks ugly and you'll hate it at first. But you'll soon appreciate not needing to create names for CSS classes or organize CSS files.
I've been using "standard" CSS for the past 20 years. That means writing and organizing classes andrules in a way that tries to be maintainable.
It's hard. But I've always decided that the solution was the need to have a "planning" phase. And that makes sense. If it becomes messy, it's because we're veering away from a consistent system.
Very recently I threw all that away and started using Tailwind CSS. Let's take a look.
Tailwind is a "utility class" CSS framework
Pretend I have a button that I want to style. Without Tailwind, I might write something like this:
HTML
<button class="btn btn-primary">Click me</button>
CSS
.btn {
padding: 0.5rem 1rem;
border-radius: 0.25rem;
font-size: 1rem;
font-weight: bold;
border: 1px solid #0c4a6e;
}
.btn.primary {
background-color: #0c4a6e;
color: white;
}
We can talk about whether it'd make sense to use BEM, SMACSS, OOCSS or some other approach but that doesn't really change our intention here.
With Tailwind, we'd do something like this:
HTML
<button
class="py-2 px-4 border-sky-900 rounded font-bold text-base text-white bg-sky-900"
>Click me</button>
And... no CSS required.
But it looks ugly and unmaintainable, right? What's the practical difference that makes this worth it?
The problem with "standard" CSS
(Both of these problems are initially going to sound silly and ridiculous and heck, maybe even like whining.)
- You need at least 2 files open at the same time (HTML and CSS)
- You need to constantly name things (your CSS classes)
So why are those problems?
It's not that they are problems per se, but they are annoyances. And with Tailwind, they go away.
Naming things is the part I think is most important. It's the one I experienced the benefit of immediately.
As for needing multiple files open at the same time, that's not actually the annoyance. The annoyance is having to constantly switch between my 'markup' file and then my 'style' file. (Some frameworks try to solve this by putting the CSS in the same file as the HTML. That's a solution for sure. But you'll still need to name the styles you put in that file. And maybe even make sure you're not overwriting named in other files, if the CSS isn't scoped.)
What do we mean by utility CSS classes?
Utility CSS classes are effectively one CSS class for one CSS rule.
This was the horror I encountered when I was brought into an existing project around 2015:
CSS
.lowercase{text-transform: lowercase; }
.no-text-transform { text-transform: inherit !important;}
.no-border {border: none !important;}
.margin-top-minus-30px{margin-top: -30px; }
.margin-top-minus-40px{margin-top: -40px !important; }
.margin-top-minus-60px{margin-top: -60px; }
.margin-top-none{margin-top: 0px !important; }
.margin-top-10px{margin-top: 10px; }
.margin-top-15px{margin-top: 15px; }
.margin-top-15px-important{margin-top: 15px !important; }
.margin-top-20px{margin-top: 20px; }
.margin-top-20px-important{margin-top: 20px !important; }
.margin-top-25px{margin-top: 25px; }
.margin-top-30px{margin-top: 30px; }
.margin-bottom-10px{margin-bottom: 10px; }
.margin-bottom-20px{margin-bottom: 20px; }
.margin-bottom-20px-important{margin-bottom: 20px !important; }
.margin-bottom-30px{margin-bottom: 30px; }
.margin-bottom-30px-important{margin-bottom: 30px !important; }
.margin-bottom-50px{margin-bottom: 50px; }
.padding-right-50px{padding-right: 50px; }
.padding-top-0px{padding-top: 0px !important; }
.padding-bottom-5px{padding-bottom: 5px !important; }
.padding-bottom-300px{padding-bottom: 300px !important; }
.padding-top-20px{padding-top: 20px !important; }
.padding-top-30px{padding-top: 30px !important; }
Effectively, that's an old example of the concept. It scared me at the time because it was different from what I was used to. And, at first glance it seemed so wasteful to have all these classes, which were effectively the same idea as inline style attributes. There were hundreds and hundreds of these.
This was how a dev team coped with a project that had no real design system, and the layout was seemingly arbitrary.
Tailwind is a modern take on this idea. Now that web components (real or React-like) are common, and we have simple preprocessors to only include the relevant CSS, it's a much more practical approach.
I'll be transparent here though -- not everyone sees the benefit with Tailwind. To that end, here's an article by someone who isn't a fan:
What does the styling process look like with Tailwind?
- I look at the design and the HTML
- I add classnames to the HTML to match the design
That's it! It's immediate. No naming, no jumping between files. It's all in one place.
Let's remember what it's like with 'normal' CSS:
- I look at the design and the HTML
- I decide what classes I need to create
- I think of names for the classes (and hopefully don't clobber any existing class names)
- I decide which file the classes should go in, or create a new file
- I add the class name to the CSS file
- I write the rules for that class
- I repeat for any other classes I need to create
- I add the class names to the HTML file
Let's be honest: the steps aren't hard at all. But when you're doing it hundreds and hundreds of times, it gets tedious.
Why do I prefer Tailwind now?
I no longer have to manage CSS files.
I don't have to name things.
It's a more direct line from the design to the HTML and it's all in one place.
Let's repeat the two immediate advantages:
- Not having to name things is HUGE.
- Not having to keep both the correct CSS file(s) open and HTML file, and constantly switching back and forth is HUGE. It doesn't seem like it would be, but it is.
What are the downsides?
There's one giant caveat:
- All reusable elements should be implemented as components (or partials)
You only want to implement a style once. If a button style is used on many different pages, you don't want to reimplement that style on every page. And you don't want the design of a common element to change between pages.
I mean, that's the problem CSS classes solved right? So the correct approach is to extract that element into its own component or a partial file. Implement the styling once in the component (or partial), and then you're done.
But let's be honest, that's how we should be constructing pages anyways.
The Tailwind CSS goes to great lengths to talk about the right ways to reuse styles.
There's a second smaller caveat:
- You'll need to learn the names for Tailwind classes
You're going to have to remember a set of CSS class names that Tailwind uses for each corresponding CSS rule. Your first day of using Tailwind is going to be spent jumping back and forth between your project and the Tailwind classes documentation.
But here's the thing... you're going to learn them. And you're going to learn them quickly. And you're going to learn them because you're going to be using them all the time.
And they're going to be the same on every project. The days of each project having a different set of unique CSS class names will go away.
What else do I need to be aware of?
You're going to run into common problems of setting global values for things. Like, a common set of padding values, colour values, font sizes, etc.
In Tailwind, you define these global design settings in a tailwind.config.js
file. That's beyond the scope of this article but once you start building bigger projects that need to adhere to a design system, that's your solution.
And finally, yes you can implement standard rules to offset the CSS reset that Tailwind implements. I'll just mention the @apply
directive and you can go from there.
One more bonus: performance
With traditional CSS, we create lots of named classes. As a project evolves over time, we tend to end up with many CSS rules where we're not entirely sure if we still need the rule, or what the consequence of removing it will be.
That leads to bloat.
With Tailwind, we only have utility classes, and the preprocessor will only include the classes that are actually used in the project. That means that over time, the size of the CSS will not tend to grow.
Wrapping it up...
I've always thought that if we were "just more careful and planned more" then we can have maintainable CSS. But in practice, that's not what happens. And at large agencies where projects will be touched by many people over years, there's little chance of success.
Tailwind eliminates a whole set of problems that occur with traditional CSS. The learning curve is actually very short. In a day or two you should start to feel comfortable with the utility classes and their implementation.
Naming things sucks, and that problem is gone with Tailwind.
Having to remember where you put things also sucks (which CSS files do I need to change for this design change?), and that problem is gone with Tailwind.
I was highly skeptical at first. I thought it looked ugly and unmaintainable. But I was wrong. It's a better way to build websites. Give it an honest try for a day or two and you'll see!
// ka