Cam Scott

Tailwind CSS Appreciation Post

Tailwind will help developers become more efficient and better organized, which makes for happy developers and happy businesses.

This is a Tailwind appreciation post. There are many like it, but this one is mine.

Tailwind is a utility-first CSS framework, originally created by Adam Wathan, Steve Schoger, Jonathan Reinink, and David Hemphill (though the team has grown by several folks in the last year.) Tailwind did not originate the concept of utility-first CSS, but built a framework on top of that foundation that is eminently approachable, configurable, and powerful.

Adam has written extensively about how the team arrived at this approach: as with many of the best ideas, it was created to solve an existing pain-point. For folks interested in the entrepreneurial process, or in an answer to the eternal question of where ideas come from, Adam's writing is gold.

Tailwind has—perhaps more so than anything else—had a dramatic impact on my development life over the last 18 months. This year alone, I've used it in Laravel apps, WordPress and Statamic themes, React/Gatsby projects, and static sites. In fact, I've yet to encounter a context where I can't plug it in and immediately enjoy the benefit.

I've also (maybe more interestingly) migrated a number of existing projects to Tailwind. In the course of so doing, I've had several conversations with project stakeholders—both technical and non-technical—about why Tailwind makes not only technical sense, but business sense, as well. Here are four reasons why I believe that's true:

Developer Ramp-Up

Every CSS framework has its own set of naming conventions, and it's reasonable to expect a bit of a learning curve. For example, a parent grid class:

No matter the framework, a developer's only solution is, frequently, rote memorization.

This is true when learning Tailwind, as well, but the authors have improved upon the frameworks above in two substantial ways:

Human Readability

Tailwind classes are written in a legible, consistent, and concise manner. Variations like spacing and color, which get shared across a variety of rulesets, are always presented in the same way. There's still memorization involved, but the Tailwind team has taken great pains to name classes in the most logical, predictable way they can.

Specificity

By resisting the allure of styled UI components, and instead focusing on a single rule per class, Tailwind allows developers to style HTML in an extremely literal way. Rather than having to remember what a class like badge-secondary entails, a developer can instead focus on the individual attributes of the element that she needs to style.

For example, badge-secondary instead becomes bg-grey-300 text-bold text-white px-5 px-3 rounded. The result is more verbose, but also more flexible. If a developer needs to change a background color or font weight, she can avoid the slippery slopes of badge-tertiary, badge-secondary__blue or style: background-color: blue !important. Instead, she modifies the classes being used directly in her view: bg-grey-300 becomes bg-blue-300, and she never needs to touch the accompanying CSS file.

As a bonus, Tailwind supports a first-party Intellisense plugin for VS Code, which detects when you start writing class names, and presents an autocompleted list to choose from. For example, typing bg- will show a list of all available color options, plus all background-related rules: bg-cover, bg-contain, etc. This provides a handy contextual look-up tool, and prevents the need to memorize color and spacing variants out of the gate.

This approachability means that new developers can ramp up and become productive more quickly—even if they've never worked with Tailwind before.

Developer Flow (or, Never Name Another Name)

Over the years, many brave and talented folks have brought their expertise to try and wrangle CSS naming conventions. OOCSS, SMACSS, BEM, ITCSS and others have done great work in attempting to standardize and unify how we write CSS.

The challenge, though, is that each of those style guides still forces developers to name things, and naming things is famously difficult, time-consuming, and subjective. One developer's main-nav is another's primary-nav, and another's header-nav. Sidebars are even worse.

By focusing on an element's styling, as opposed to the role the element plays within the larger web page, Tailwind entirely removes the burden of naming that element. main-nav instead becomes bg-black text-white flex items-center justify-center. The result is, once again, more verbose, but a developer avoids the pitfall of having to pause, assess the role of the element, name it (and invariably re-name it), and resume styling. This improves overall flow and productivity, while also improving organization and maintainability.

(This distinction between style and role is at the center of Adam's "CSS Utility Classes and Separation of Concerns" article, which offers far more insight and detail than makes sense to discuss here. If you're interested in the underlying rationale and thought process of this approach, though, I'd strongly recommend the piece.)

Improved Organization

As developers, how many times have we seen something like this, slipped into the bottom of a style.css file?

/* Extra stuff */
.btn.that-one-btn-that-marketing-wanted {
background-color: $green !important;
text-size: 18px !important
}

Everyone writes CSS differently. As discussed above, even using a strict naming convention still leaves room for individual interpretation. If a new developer inherits a project, or a maybe a back-end developer "just has to fix this one quick thing," the impulse can be strong to just tack on a few extra rules at the bottom of a stylesheet.

Every working developer has fallen prey to it at some point (except me—I would never). The problem here is that doing it once gives permission for future developers to do it again: the practice becomes a slippery slope, snarling your stylesheets over time and rendering even the most carefully organized atomic structure moot. Eventually, a developer throws up her hands, and argues that the whole thing be tossed and rewritten.

Out of the box, Tailwind creates classes for every commonly used CSS rule—and even classes for more complex concepts like gradients and transforms. This means that a developer has ready access to every tool she might need. If marketing wants her to make that one button green, she can do it. If one page headline needs to be bigger than another, she never needs to write .page-headline__xl again.

Tailwind makes it far easier to create an organization structure that persists across new features, new developers, and new product directions. That structure prevents developer frustration, improves maintainability, and helps to avoid the threat of costly "burn it all down!!!" rewrites.

Project Performance

Since version 1.4, Tailwind has included a first-party integration with a plugin called PurgeCSS. When compiling assets for production, PurgeCSS will evaluate your views, and strip any unused rules from your final production file.

Given the breadth of the CSS that Tailwind offers, a minified production file can weigh upwards of 200KB. Using PurgeCSS, I can routinely bring that weight down to a 5KB or less. By modern standards, that's an incredible savings, and a fantastic production file size. Enabling GZIP—or better yet, Brotli—on a production server makes this even more efficient.

In addition, PurgeCSS makes it easier to incorporate Tailwind into existing projects, and migrate styles over time without the weight of loading two competing CSS frameworks. If a developer installs Tailwind, and chooses only to use font-bold, then PurgeCSS will ensure that only font-bold makes it into the production stylesheet.

This makes it easy to transition projects over time, progressively decreasing load times and increasing overall performance.


Caveats and Conclusions

Of course, there are caveats here. I've seen folks object to the appearance of HTML with Tailwind in it (though I invite those folks to look at the HTML that a React app generates), and against the notion of utility-first CSS on the whole. I understand those reactions: no single tool will suit every developer, every team, and every context.

In my career, I've spent most of my time working with either:

  • agencies that are frequently under budget constraints
  • small companies that are frequently under budget constraints

To that end, efficiency and transitionability are my two guiding development principles: how quickly can I write code, and how easily can somebody else maintain that code.

Writing CSS with those goals in mind can actually be quite tricky! Tailwind has offered a more effective solution to that problem than any other approach I've found, and for that reason, above all else, I have nothing but ❤️❤️❤️.

Last updated on October 2, 2020

Now listening: Orville Peck, "Winds Change"