TailwindCSS: Adds complexity, does nothing.

If you work in the front-end, you’ve probably heard a lot about TailwindCSS, a CSS library, much like Bootstrap. Much unlike Bootstrap, however, Tailwind takes a different approach – it is all “utility classes”.

And I am not a fan. I got a whiff of i…


This content originally appeared on DEV Community and was authored by Brian Boyko

If you work in the front-end, you've probably heard a lot about TailwindCSS, a CSS library, much like Bootstrap. Much unlike Bootstrap, however, Tailwind takes a different approach - it is all "utility classes".

And I am not a fan. I got a whiff of it and quickly learned the name is appropos: it was as welcome and useful as passed gas.

Before we start, let me try to explain what a utility class is. Let's say that you have many components, and many of them need to have the CSS style property: "display: flex;". Instead of writing that over and over in your css, multiple times, instead you create a class called "flex"

.flex {
  display: flex;
}

Then, in every component that needs to be flexed, you add that "flex" class.

This is not a bad thing. I have written, and used utility classes a great deal myself, especially when I'm writing CSS without the aid of CSS-in-JS solutions or a preprocessor like Sass/SCSS.

What Tailwind does is take that concept to the extreme, with the idea being that you almost never have to write CSS, you just write different classes based on what styles you need to apply.

Which is an interesting choice, because...

This is just inline styles with extra steps

This is just inline styles with extra steps.

That's it. Writing <div class="flex">foo</div> has the same exact effect as writing <div style="display: flex;">foo</div>. Well -- slightly different in that inline styles have higher priority than classes, but that's not really relevant in this context.

So - with that in mind, with the exception of CSS prioritization, any argument you could make against using inline styles in your codebase is also an argument against using Tailwind. For example: Lifewire: Avoiding Inline Styles for CSS Design. Or StackOverflow: What's so bad about inline CSS?. Or LogRocket: Why you shouldn’t use inline styling in production React apps.

I know it seems a bit lazy to rehash other users criticisms of inline styles to explain what's wrong with Tailwind, but it really is a 1-to-1 mapping. It's just inline styles with extra steps.

Some of the problems Tailwind shares with inline styles:

It's WET, not DRY.

When you want to change your site styling in a major way, if you've used utility classes, you need to go through each use of those utility classes - that is, every component - and visually determine what needs to be updated. For example, let's say that your company's primary color is blue. You'll have lots of blue stuff in your website, marked with things like: "text-blue-500" or "bg-blue-300" to determine different shades of blue. And that's fine until your company decides to rebrand, and all of the buttons - but only the buttons - on the site need to be red.

Now you have to go through each component and manually change "text-blue-500" to "text-red-500". And with 1000 edits comes 1000 oppertunities to introduce a bug. It is almost a textbook definition of why the DRY principle is in place.

Alternatively, if you're using regular-old CSS, what you probably did is create a class called ".button". You can just go into that class and change a single line: "background-color: 'red';". Any element that uses that class definition will now be red.

That brings us to the next point:

HTML should only concern itself with the structure of your page, not the styling of the page.

People talk about seperation of concerns a lot in development. CSS Modules (and especially .vue files) have done a lot to dispel the notion that you need to segregate structure, behavior, and style of the same basic building block of your site in seperate folders, but there is something to be said for seperating concerns. That is - each part of your code should be "loosely coupled and highly cohesive."

In other words, your HTML (structure syntax) shouldn't have information about what the styles should be, it should only contain information about the structure of the page.

Indeed, the ultimate reason for the invention of CSS, the whole point of the entire enterprise of CSS... was specifically so that you could seperate content from presentation.

And the method for doing this is through the "class" attribute.

The whole point of "class" is specifically that you can tell the computer what an element is - that is, describe an element's content. Once you've defined the content, then you just need to decide what content of that type should look like.

This not only means that you can go and change how an element looks without worrying about the underlying structure of the page, but also means that you can use these classes to describe what an element is. Indeed, part of the reason for BEM's naming syntax is that BEM names not only tell you what the component is, but also what it's relationship to other components in the document is.

Remember that when we write code, we write it for two audiences: the first is the computer itself, which doesn't care how the code looks so long as it runs, and the other is your fellow programmers. The easier it is for them to quickly identify what parts of your program are and how they interrelate, the more quickly that they can fix bugs, add features, and bring value to the organization.

Which brings us to:

It's hard to read

If you look at some HTML with Tailwind in it, you might say to yourself that the HTML looks "busy" or even "ugly." That's true, but it's missing the point.

Say what you will about inline styles, but they're at least providing enough context to let you know what's happening. Tailwind code is full of semantically obscure abbreviations; most of which are just redefinitions of already well known CSS properties.

Worse still, when they're not redefinitions, they can become downright cryptic. Tailwind prefers to use prefixed class names instead of media queries. Here's an example from Aleksandr Hovhannisyan

So this in Tailwind:

<div
  class="w-16 h-16 rounded text-white bg-black py-1 px-2 m-1 text-sm md:w-32 md:h-32 md:rounded-md md:text-base lg:w-48 lg:h-48 lg:rounded-lg lg:text-lg"
>
  Yikes.
</div>

could be expressed as:

<style>
.thing {
  width: 16px;
  height: 16px;
  color: white;
  background-color: black;
  padding: 0.25rem 0.5rem;
  margin: 0.25rem;
  border-radius: 0.25rem;
  font-size: 0.875rem;
  line-height: 1.25rem;
}

@media screen and (min-width: 768px) {
  .thing {
    width: 32px;
    height: 32px;
    border-radius: 0.375rem;
    font-size: 1rem;
    line-height: 1.5rem;
  }
}

@media screen and (min-width: 1024px) {
  .thing {
    width: 48px;
    height: 48px;
    border-radius: 0.5rem;
    font-size: 1.125rem;
    line-height: 1.75rem;
  }
}

</style>
<div class="thing">Yikes.</div>

Now, the first example, I grant, is an awful lot less code to write, but look at how the second example is explictly defining height and width at specific breakpoints.

It is verbose - as raw CSS usually happens to be, but there are other solutions - such as Sass/SCSS, or solutions such as Emotion, Styled Components, etc. which allow you to use much more terse syntax without losing the cohesive meaning behind it.

Again, this is programmer 101. It's why senior developers get on junior developers for naming variables "const h = 10" instead of "const height = 10"

Another reason why the latter is easier to read than the former - Tailwind's classes are arranged horizontally, while the CSS is written vertically. The wider text is, the harder it is for a reader's eyes to jump to the next line, and the harder it is to find the one particular word you're looking for in a wall of horizontal text.

I bet your eyes started glazing over the second you saw the horizontal scroll bar on that Tailwind code sample, didn't they?

You lose a lot of the features built into standard CSS

I won't harp on this too much, but it should be pointed out that because Tailwind doesn't allow you to use the power of many of CSS's basic features. You can't chain selectors together, like so:

.foo:focus,
.foo:active,
.foo:hover {
  /* css code */
}

You can't use combinators.

.foo p {
  /* all p that are decendants of a .foo */
}
.foo > p {
  /* all p that are direct children of a .foo */
}
.foo + p {
  /* all p that are directly -after- a .foo */
}
.foo ~ p {
  /* all p that are siblings of a .foo */
}

It solves a problem that doesn't exist.

One of the craziest things is that there's an obvious limitation to Tailwind's utility-class paradigm. What happens if you want to group related styles together? Rarely is "display:flex;" used without "justify-content: {value}", for example. CSS allows you to group these styles together into (wait for it), classes.

There's a tool for grouping related Tailwind classes together too. It's called @apply. It's special, non-standard syntax that goes in your CSS file (a directive) and allows you to string together a collection of tailwind classes and place them all under one class name.

That is to say, completely defeating the purpose behind the utility-class paradigm. If you end up having to use @apply, then *why don't you just use normal, ordinary, conventional CSS, which is easier to read, understand, modify, and doesn't require special tooling or parsing. CSS syntax can be complex, but it's been pretty stable since the late 90s, and isn't going to radically change anytime soon.

There's a very simple mental experiment I'd like to conduct with you.

Imagine a world in which CSS was never developed, but something akin to Tailwind was. That is, webpages could only be styled through repeating these individual class names... presumably through using

tags for layout. (To give you an idea of how old I am, I used to code web pages as a summer job in my junior year of high school in 1996 - and we used a LOT of
tags.)

If you could go from the limitations of Tailwind to CSS, wouldn't you consider that a quantum leap forward? Expressive syntax! Semantic naming! Style grouping! Selectors and combinators!. It would be like moving from Assembly to C for the first time. If so, why are we considering replacing CSS with something that does less, is more complex, creates bad quality codebases, and possibly ends up with massive vendor-lock in down the line?

If you want better than CSS, there are already solutions.

So a lot of the hype around Tailwind is that you can get rid of CSS. I know, everyone knows CSS can be hard to work with - especially if you have legacy codebases where the CSS wasn't written that well.

But for the most part, there are other, better improvements on CSS that actually do make styling simpler. There's the various CSS-in-JS solutions that allow you to leverage the power of Javascript to create dynamic class definitions; there's preprocessers such as Sass/SCSS/LESS; there's linters like Stylelint; there's best-practices methods like BEM/SMACSS. Is there overhead in learning these technologies? Yes. Is there tooling that needs to be part of your build chain? Yes. But unlike Tailwind, all of these solutions actively provide a tangible benefit to your code -- which is something that Tailwind can't claim.

It literally provides no value, and tons of problems.

At the end of the day, what do you get for all these problems? What are you left with? You're basically left with a less readable, more complex version of inline styles, a coding technique that we've been trying to breed out of junior developers for the past decade or so.

If you adopt Tailwind, it's going to provide problems for you and your team for years to come, and it's going to be hard to remove it.



This content originally appeared on DEV Community and was authored by Brian Boyko


Print Share Comment Cite Upload Translate Updates
APA

Brian Boyko | Sciencx (2021-04-19T19:39:13+00:00) TailwindCSS: Adds complexity, does nothing.. Retrieved from https://www.scien.cx/2021/04/19/tailwindcss-adds-complexity-does-nothing/

MLA
" » TailwindCSS: Adds complexity, does nothing.." Brian Boyko | Sciencx - Monday April 19, 2021, https://www.scien.cx/2021/04/19/tailwindcss-adds-complexity-does-nothing/
HARVARD
Brian Boyko | Sciencx Monday April 19, 2021 » TailwindCSS: Adds complexity, does nothing.., viewed ,<https://www.scien.cx/2021/04/19/tailwindcss-adds-complexity-does-nothing/>
VANCOUVER
Brian Boyko | Sciencx - » TailwindCSS: Adds complexity, does nothing.. [Internet]. [Accessed ]. Available from: https://www.scien.cx/2021/04/19/tailwindcss-adds-complexity-does-nothing/
CHICAGO
" » TailwindCSS: Adds complexity, does nothing.." Brian Boyko | Sciencx - Accessed . https://www.scien.cx/2021/04/19/tailwindcss-adds-complexity-does-nothing/
IEEE
" » TailwindCSS: Adds complexity, does nothing.." Brian Boyko | Sciencx [Online]. Available: https://www.scien.cx/2021/04/19/tailwindcss-adds-complexity-does-nothing/. [Accessed: ]
rf:citation
» TailwindCSS: Adds complexity, does nothing. | Brian Boyko | Sciencx | https://www.scien.cx/2021/04/19/tailwindcss-adds-complexity-does-nothing/ |

Please log in to upload a file.




There are no updates yet.
Click the Upload button above to add an update.

You must be logged in to translate posts. Please log in or register.