We’ve found this makes us super productive when building out pages. Like everything else, our conventions stay the same project to project so you can be sure that when you see some Figma styles set on text there will be corresponding classes. In this case “Heading Jumbo” is hd-jb
, “Heading Extra Large” is hd-xl
, “Heading Large” is hd-lg
, etc.
One of the great things about plugins is their portability. We have curated a collection of Tailwind plugins that we consistently use in our TailwindCSS
Plugins repo. You might also notice the rem()
function I’ve used above. The rem()
helper and other handy helpers are also explained further in that same repo.
Prevent premature abstractions, bloat, and inconsistency
We build out HTML pages and only think about abstracting a component if it’s clear we’ll need to re-use it. The clearest examples of things that shouldn’t be abstracted are site headers or footers. These don’t need their own CSS file or their own reusable component file, they are one-offs. Premature abstractions tend to cause bloat and inconsistencies over time.
Any system you use for CSS should try to prevent bloat and make it hard for inconsistencies to happen, Tailwind makes it easy by minimizing what we have to write. A typical project will have very little CSS written by us. In the past, CSS has been the place where we observe bloat accumulating over time after sites go into support mode.
Inconsistencies can be avoided in many ways, but the use of a tailwind.config.js
file is one of the best ways. The act of configuring makes us take a holistic look at the design and identify inconsistencies. This doesn’t mean we are totally inflexible, what I mean is this helps us identify unintended inconsistencies in the system, the type that ends up causing bloat and confusion when coming back to a project a year later.
With the introduction of JIT compiling for tailwind we can further constrain our configuration file ensuring that those rare one-off values are contained within very specific components and don’t pollute the overall design system.
No project knowledge required
The problem with systems we’ve tried before and other systems we’ve considered is that there’s a certain amount of ramp up time to understand what is going on with the CSS. Naming is never consistent from person to person or project to project. Tailwind cuts through all this with its utility-first approach. When it comes to supporting projects this is game-changing.
When faced with a ticket to change something, we don’t have to track down a CSS file and ask ourselves what else this CSS file affects. Without any familiarity with the project you can immediately be productive and modify the HTML right in front of you, or write a whole new component using nothing but utility classes. All my best experiences with support work have happened in projects that use Tailwind. More and more people on our team are having similar experiences.
How we think about the downsides and criticisms of Tailwind
Most of the criticism of Tailwind we read appears to come from people who haven’t used it—or don’t tailor it to their projects. That’s fine, that’s how I criticize CSS-in-JS, so I get it. We also question our approach often. It’s not perfect and, like everything else we do, we are always trying to find a better way—or trying to optimize how we work.
Before getting into our concerns, I want to address the arguments I don’t think have merit:
- It’s just inline styles (Sarah Dayan explains how that is not true),
- It violates separation of concerns (Adam Wathan does a great breakdown of why that is ok), and
- it adds like a megabyte of CSS. (This one is just a complete misunderstanding of Tailwind, it has PurgeCSS built-in so you usually end up with less CSS than you would otherwise)
While we don’t think any of the above are a real concern, there are two downsides that do concern us at Viget. First, we aren’t writing CSS and that means junior FEDs might not have opportunities to learn CSS fundamentals. Secondly, Tailwind might go in a direction we eventually disagree with, and then what do we do?
Not learning CSS
To use Tailwind you still need to know CSS, there’s no getting around that. Especially in the way we use it where we are often writing plugins and modifying the configuration to our needs. Having a layer of abstraction on top of CSS does make it hard for a less experienced FED to be exposed to what is going on at the CSS level. That’s a huge problem not just for us but for them.
Not every project will use Tailwind so we need everyone to be able to toggle back and forth between using Tailwind and using other CSS techniques. More importantly, if a junior FED wants to move on from Viget we’ve done them a disservice in not properly teaching them CSS if all they ever see is Tailwind code.
What if Tailwind betrays us?
We like Tailwind a lot and think Adam Wathan does a great job of coming up with new features and growing the project in a good direction. Having said that, at some point one of two things could happen:
- Nightmare scenario one: Tailwind decides that they want to focus a lot more on the pre-configured version and they do things that make the experience for people who like to use the full config untenable somehow.
- Nightmare scenario two: Tailwind stops asking themselves whether they should do something and just start adding things because they can do it, and that introduces problems for us.
We aren’t anywhere close to running into these problems but we don’t have any control over Tailwind. In theory we could freeze what version of Tailwind we use but that doesn’t seem like a great solution if the rest of the tooling keeps moving with Tailwind.
We’ll keep evolving
Not that long ago I wrote How does Viget JavaScript?, and while broadly it’s still accurate three large projects currently in development are using Hotwire in the way I describe in Should I use Hotwire with Craft?. Whenever there is a reason to change, we do, and that will be the same with our approach to CSS.
Using Tailwind as our CSS solution has solved big problems for us and has turned out to be a great decision for our team. Even people on the team who hated Tailwind have changed their minds once they started using it in our projects. Still, we are always open to new ideas, and I imagine at some point someone on the team will find a way to improve on our current setup.