Source: Scalable Path Blog

Scalable Path Blog Tailwind CSS: Caught in the Crossfire of the Front-end Divide

Very few technologies in front-end development raise such a passionate divide as Tailwind CSS. From people madly in love with it claiming that "it fixes CSS" to detractors that discard it as "just abstracted inline styles", It would seem that no month can go by on Tech Twitter without a flame war about Tailwind. However, I believe the arguments about Tailwind are rarely scoped to the framework itself, but part of much deeper discussions. Let's go through how it really works, dismantle some of the arguments from both camps, and address the most important question: is Tailwind the future of CSS?What is Tailwind CSS?If we had to put it in a one-liner, we could say that Tailwind is a utility-first CSS framework, but I guess that won't mean much if we don't get into a little bit of CSS architecture first. Historically, one of the biggest challenges of CSS has been keeping things organized, especially as the team grows and more people work in the codebase. Someone said that "the max number of people that can productively work on CSS is one", and there's quite a bit of truth behind that joke. If we don't set clear guidelines, CSS can be particularly tricky to maintain. Several CSS architectures have been developed throughout the years to help address the issue. From the good ol' Object Oriented CSS (OOCSS) to Block Element Modifier (BEM) and Scalable and Modular Architecture for CSS (SMACSS), numerous solutions have been proposed to keep our classes organized while embracing the power of semantics, the cascade, and the fundamental paradigm of separation of concerns. But as the web shifted towards a JavaScript-heavy modular architecture, we've seen other approaches emerge. In one way or another, these approaches seem to be more compatible with the modern web (or at least, with the people developing it): various flavors of CSS-In-JS, styled components, and Utility-First CSS. The Utility-First Approach and Tailwind The utility-first approach (also known as Atomic CSS or Functional CSS) aims to take the single-responsibility principle and apply it to CSS, allowing us to compose complex components from simple, single-responsibility CSS classes. Instead of assigning a class with a bunch of declarations to an element, we can explicitly declare how it looks, bit by bit. No more .sidebar__title--highlight, simply assign it a class for its font size, another for the font-weight, and so on. As the biggest utility-first CSS framework, Tailwind provides us with an enormous library of pre-built CSS classes that we can use to compose our styles. It allows us to create prototypes incredibly fast, not having to worry about naming conventions (or naming at all), making changes feel safer, and generally resulting in smaller CSS files. The utility-first approach and Tailwind, in particular, mean such a radical departure from traditional CSS architecture that it catches a lot of flak from some CSS developers and a lot of praise from others. Let's get into some of the arguments of both camps and check exactly what claims stand. Is CSS Broken? One of the boldest claims from some Tailwind evangelists is that CSS is broken somehow, and that Tailwind fixes it. Despite how loud those people can be on Twitter, I believe nothing can be further from the truth. However, we need to understand where that claim comes from and what people mean when they say "CSS is broken" or "CSS is hard" in order to know exactly what we are really discussing when we talk about Tailwind. As CSS occupies a weird place between design and development, "CSS is hard" can mean extremely different things. For starters, it can mean "design is hard", as in choosing colors, fonts, keeping a consistent vertical rhythm, etc. This is evidently true, as it is a completely alien skill set to most programmers. And it's no wonder, as it even works on a completely different part of our brains: graphic design relies primarily on visual-spatial intelligence, while programming works primarily on a logical-mathematical basis (and I would add CSS is mostly verbal-linguistic, but that's a topic for a whole other post). What Tailwind does here is provide pre-vetted choices that simply work. Instead of worrying about which tones of red go well with each other, you simply declare .bg-red-100, .bg-red-400, etc. Instead of worrying about the exact pixels to keep a correct vertical rhythm for your font sizes, paddings, and margins, you simply declare .text-lg, .p-1, .m-1. Need to tweak the padding? try .p-2, .p-3, and so forth.By limiting our choices and providing sensible defaults, Tailwind allows non-designers to rapidly prototype visually pleasing components. "CSS is Hard" can also mean "Implementing said design into code is hard", simply because of the declarative nature of CSS and the limited time allowed for learning it in most front-end courses. I sincerely believe that 99% of the recurring issues with CSS can be prevented by properly learning the cascade, formatting contexts, stacking contexts, and two or three extra key concepts of CSS theory. You'll be far less likely to get stuck if you understand how things work under the hood. But most developers are not even aware of those, and apparently can't be bothered to learn them properly. CSS is deceptively simple, and that's its demise. This is probably one of the most controversial arguments for and against Tailwind. It will help people who "know CSS (but not really)" to get away with it, by pretty much avoiding the cascade, and getting around collapsing margins and such by simply resetting everything to zero through preflight, it's a very opinionated set of base styles built on top of modern-normalize.Last but not least, "CSS is hard" can also mean "making the architectural decisions to build CSS in a sustainable way is challenging". And this is definitely true. We all have seen codebases where the CSS gets incredibly verbose due to devs just adding stuff on top and never removing anything, fearing it would break the styles for some part of the codebase they may not even be aware of. Not to mention, incredible specificity wars where people will even reach for hacks to prevent their styles from getting overwritten. Tailwind's utility-first approach means that the CSS file won't be getting bigger, and sets the specificity flat so no wars ensue. Adding styles will rarely add weight to the CSS files. If anything, only your HTML (in whatever form you're generating it) can grow.It's Not "Just Abstracted Inline Styles" An evident downside of utility-first CSS is how dirty our HTML looks. I have yet to meet a developer whose first reaction to a Tailwind component hasn't been one of disgust. Seriously, just look at the thing. It's ugly. <div class="mt-4 md:mt-0 md:ml-6"> <div class="uppercase tracking-wide text-sm text-indigo-600 font-bold">Why work with Scalable Path?</div> <a href="#" class="block mt-1 text-lg leading-tight font-semibold text-gray-900 hover:underline">Building teams is our business</a> <p class="mt-2 text-gray-600">Our personalized, step-by-step approach, powerful hiring platform and network of pre-qualified talent accelerates the hiring process and stacks the odds in your favor.</p> </div>But hey, it works for many teams all around the globe, so there's definitely merit behind it if you can look past that. Apparently, some people can't, and they make the equally bold claim that "it's just abstracted inline styles". While I believe there's some truth to that statement, it differs from inline styling in a million ways: You can't apply inline styles to pseudo-elements or pseudo-classes. Utility classes can, and there's plenty in Tailwind to handle your hover styles and everything you can possibly need. Inline styles won't cache. And this is a huge hit for performance. Normally the browser will keep your stylesheets in cache, meaning it can access and apply any style much faster, whether that's traditional or utility CSS. Inline styles are shipped as part of your markup, so they won't cache and have to be processed every time. Single responsibility doesn't mean single declaration. Unlike inline styles that declare properties and values one by one, utility classes are not necessarily limited to one declaration, but to one function. The best example of this can be found in the clearfix hack, which is probably the most widespread utility class ever. It's also one that we've used even before that name was coined, let alone proposed as an architecture. In the clearfix hack we have a single responsibility - to fix the issues derived from using floats for layouts, but that's achieved by three declarations.clearfix:after { content: ''; display: table; clear: both; }If you're interested in further exploring the differences between inline styles and utility-first, I'd recommend Sara Dayan's article on it. But again, I believe this is misinterpreting what people making this claim really mean: the utility-first approach means you'll compose the look and feel directly in your markup (and have to learn a whole new set of words in order to do so). And to that, the other camp would reply: that's exactly the point. To be fair, most of the class names are fairly intuitive and can be learned in just a couple of hours, and their documentation is exceptionally complete and well-written.The discussion, therefore, goes back to the start. It's not about inline styles, it's not about Tailwind itself, or about the utility-first approach. It's about whether or not we should embrace the most fundamental design feature of CSS, the one in the name itself: the cascade. Tailwind CSS File Sizes and PerformanceWe've all seen amazing claims of size reduction after refactoring old codebases from traditional CSS into Tailwind. I've seen cases where they went from a dozen CSS files that weigh a mind-blowing total of 60Mb to a single file weighing a few Kb. This is not a small difference, in many cases, we're talking about orders of magnitu

Read full article »
Est. Annual Revenue
$100K-5.0M
Est. Employees
25-100
CEO Avatar

CEO

Update CEO

CEO Approval Rating

- -/100