DEV Community

Cover image for Challenging the Skeptics: Unveiling the Undeniable Goodness of Tailwind CSS
Nick Taylor for OpenSauced

Posted on • Updated on

Challenging the Skeptics: Unveiling the Undeniable Goodness of Tailwind CSS

People definitely have opinions about Tailwind. There are staunch supporters and staunch haters, but I really don't want to get into all that. Head on over to Twitter if you want to waste some time.

If you're pretty well versed with Tailwind, this article might not be for you, but who knows? Read on and maybe you'll learn something.

I'm coming in with what, I think, is a fresh perspective. I'm using Tailwind for the first time professionally. Furthermore, I don't consider myself a CSS expert, but I think I have pretty solid CSS skills.

I mention all this, to convey a sentiment, I've seen many people exhibit. You're using Tailwind because you don't understand CSS. I do understand CSS.

So the first thing that I've seen when people say when they do not like Tailwind, is that it's not CSS, or it's inline CSS. This is completely false, even coming in as a newbie to Tailwind, all Tailwind is, at the end of the day, once it's compiled, is CSS utility classes.

Comparisons

So let's look at some comparisons between Tailwind and "real" CSS. I'm going to put the vanilla CSS in a style tag, but you could also put it in a .css file and link it in the head of your HTML or however your application bundles CSS. This is just for the sake of comparison.

First Glances of Tailwind

Vanilla CSS

<style>
  .my-list {
    display: flex;
    flex-direction: column;
    gap: 1.5rem;
  }

  .my-list li {
    border-width: 1px;
  }
</style>
<ul class="my-list">
  <li>Item 1</li>
  <li>Item 2</li>
  <li>Item 3</li>
</ul>
Enter fullscreen mode Exit fullscreen mode

Tailwind

<ul class="flex flex-col gap-6">
  <li class="border">Item 1</li>
  <li class="border">Item 2</li>
  <li class="border">Item 3</li>
</ul>
Enter fullscreen mode Exit fullscreen mode

So the first thing someone might say is that Tailwind is repeating the border CSS class on a list item, <li>, instead of using a selector that can target the li DOM elements. This is true, but Tailwind allows you to create the equivalent of .my-list li. You can do the following:

<ul class="flex flex-col gap-6 [&_li]:border">
  <li>Item 1</li>
  <li>Item 2</li>
  <li>Item 3</li>
</ul>
Enter fullscreen mode Exit fullscreen mode

This is probably where someone might say, "Well, now you're just writing inline CSS." This is also false. It will generate a CSS rule based on the [&_li]:border CSS class name. It will compile it to literal CSS that will generate an equivalent CSS rule comparable to the CSS rule for the .mylist li selector.

In fact, this is what it compiles to. I've formatted it since it gets minified.

.\[\&_li\]\:border li {
  border-width: 1px;
}
Enter fullscreen mode Exit fullscreen mode

You could make an argument that the "real" version looks nicer, but this isn't a strong argument, and you have CSS source maps if you open the browser dev tools.

I'll say it here and repeat it again later. Tailwind is a utility-first CSS framework. It's not inline CSS.

If you want to see an example of this in production grade code, check out a recent pull request (PR) of mine to the OpenSauced app repository.

fix: add missing skeleton loader for insights panel #2524

Description

Adds a skeleton loader for the insights panel component used in the application sidebar.

What type of PR is this? (check all applicable)

  • [ ] 🍕 Feature
  • [x] 🐛 Bug Fix
  • [ ] 📝 Documentation Update
  • [ ] 🎨 Style
  • [ ] 🧑‍💻 Code Refactor
  • [ ] 🔥 Performance Improvements
  • [ ] ✅ Test
  • [ ] 🤖 Build
  • [ ] 🔁 CI
  • [ ] 📦 Chore (Release)
  • [ ] ⏩ Revert

Related Tickets & Documents

Fixes #2525

Mobile & Desktop Screenshots/Recordings

https://github.com/open-sauced/app/assets/833231/6a8e09f6-44e6-47ef-8056-4e6c822e3dee

Steps to QA

N/A. You can test it out in Storybook.

Added to documentation?

  • [ ] 📜 README.md
  • [ ] 📓 docs.opensauced.pizza
  • [ ] 🍕 dev.to/opensauced
  • [x] 📕 storybook
  • [ ] 🙅 no documentation needed

[optional] Are there any post-deployment tasks we need to perform?

[optional] What gif best describes this PR or how it makes you feel?

Styling pseudo-elements

What about something more complex like pseudo-elements? Let's take the ::before pseudo-element for a spin.

Vanilla CSS

<style>
.pizza-time::before {
  content: attr(data-inset-label)
}
</style>
<p data-inset-label="🍕" class="pizza-time">
  OpenSauced is awesome!
</p>
Enter fullscreen mode Exit fullscreen mode

Tailwind

<p data-inset-label="🍕" class="before:content-[attr(data-inset-label)]">
  OpenSauced is awesome!
</p>
Enter fullscreen mode Exit fullscreen mode

Here's what it generates as CSS when Tailwind compiles that CSS class.

.before\:content-\[attr\(data-inset-label\)\]:before{
  --tw-content:attr(data-inset-label);
  content:var(--tw-content)
}
Enter fullscreen mode Exit fullscreen mode

You could complain that that is one hell of a bloated CSS class name, but again, I don't think this is a colossal deal.

If you want to see an example of this in production grade code, check out a recent PR of mine to the OpenSauced app repository.

feat: created the day range picker component #2552

Description

What type of PR is this? (check all applicable)

  • [x] 🍕 Feature
  • [ ] 🐛 Bug Fix
  • [ ] 📝 Documentation Update
  • [ ] 🎨 Style
  • [ ] 🧑‍💻 Code Refactor
  • [ ] 🔥 Performance Improvements
  • [ ] ✅ Test
  • [ ] 🤖 Build
  • [ ] 🔁 CI
  • [ ] 📦 Chore (Release)
  • [ ] ⏩ Revert

Related Tickets & Documents

Closes #2553

Mobile & Desktop Screenshots/Recordings

CleanShot 2024-01-29 at 19 48 45

Steps to QA

N/A currently it's only in Storybook

Added to documentation?

  • [ ] 📜 README.md
  • [ ] 📓 docs.opensauced.pizza
  • [ ] 🍕 dev.to/opensauced
  • [x] 📕 storybook
  • [ ] 🙅 no documentation needed

[optional] Are there any post-deployment tasks we need to perform?

[optional] What gif best describes this PR or how it makes you feel?

Animations

If you're looking to add animations, Tailwind ships with plenty of useful animations and CSS classes to leverage them.

Need a custom animation? You can do that as well. I won't go into it here, but here's a great post about writing custom animations in Tailwind.

Accessibility

You've got all these cool animations, but what if someone has specified prefers-reduced-motion? Tailwind can handle that for you as long as you prefix your animation with motion-safe:, e.g.

<p class="motion-safe:animate-spin">Spinning text</p>
Enter fullscreen mode Exit fullscreen mode

There's other useful Tailwind classes for accessibility, like sr-only, which will remain in the page, but only be visible to screen readers.

I think something that would be interesting to add to the Tailwind a11y story is using Tatiana Mac's (@tatianamac) approach of taking a no-motion-first approach to animations.

Define some base styles

I'm all for components, and I'm a big fan of JSX. Tailwind pairs nicely with components, but I do think that it's still good to have some base styles defined, even if you are using components.

For example, a base font size and colour, focus state styles, headings etc. This is what I ended up doing in the OpenSauced app repository.

Another Complaint: It's like bootstrap

Tailwind CSS on its own is not like bootstrap. It's just CSS utility classes, whereas bootstrap is UI components and CSS.

I've never used it, but maybe you could fall into this trap with Tailwind UI.

Tradeoffs

Like many things, there are tradeoffs. I think the biggest one is learning the Tailwind CSS classes and naming conventions for building them, but I think the benefits outweigh this. And to be honest, once you start writing the classes frequently, the naming convention just sticks in your head.

And if you have some super complex CSS, for whatever reason, Tailwind can't handle, there's nothing wrong with adding some custom CSS.

Wrapping Things Up

I literally only started using Tailwind September 18th of 2023 when I started at OpenSauced.

Tailwind has made me super productive while building out OpenSauced, and I've used it in some other projects since then.

Remember, Tailwind is a utility-first CSS framework. It's not inline CSS.

I encourage you to give Tailwind a go. They have outstanding documentation and great IDE support to help you along the way.

If you give it a go and say it's not for me, that's OK. Use what makes you the most productive.

Stay saucy peeps!

If you want to know more about my work in open source, follow me on OpenSauced.

Top comments (23)

Collapse
 
woldtwerk profile image
Willi

Most of the examples above should not be used in production, since they don't scale. Using arbitrary variants, children selectors etc. tend to be singletons in your compiled CSS file. Thus they will be unused on most pages in your app.
Sometimes style="padding:3px" is better than p-[3px], if your CSP is fine with it.

Collapse
 
nickytonline profile image
Nick Taylor

If you want to elaborate, I'm curious what doesn't scale exactly? Also, if you don't want to use Tailwind, it's all good. Use what works best for you and your team.

Collapse
 
nickytonline profile image
Nick Taylor • Edited

I just added this bit to the accessibility section in case you already read the article, but I think something that would be interesting to add to the Tailwind a11y story is using Tatiana Mac's approach of taking a no-motion-first approach to animations.

Collapse
 
ryandotfurrer profile image
Ryan Furrer

As someone who waited (and somewhat hated on it) on learning Tailwind, I used it in my recent portfolio revamp and now I LOVE it. I don't think you need to use it all the time and vanilla CSS certainly has it's place, but people make it out to be this villain in the CSS space.

It's also quite intuitive once you get the hang of it.

Collapse
 
nickytonline profile image
Nick Taylor

Kylo Ren on Undercover Boss giving a thumbs up

Collapse
 
cmcnicholas profile image
Craig McNicholas

Tried again and again to like tailwind, it is just online CSS and I'll die on this hill.

I've worked on large (2m+ LoC frontends) and small sites, i always find plain CSS and following a good structure e.g. BEM is more readable and maintainable in the long run.

Collapse
 
nickytonline profile image
Nick Taylor

Thanks for giving it a read Craig!

Like I mentioned at the end of the blog post, "If you give it a go and say it's not for me, that's OK. Use what makes you the most productive."

Hot Rod saying Cool beans!

Collapse
 
ben profile image
Ben Halpern

Tailwind is good

Collapse
 
nickytonline profile image
Nick Taylor

Jack Nicholson nodding yes

Collapse
 
klimd1389 profile image
Dmytro Klimenko

Great overview! You've covered all the key aspects of this topic in detail and provided clear examples to support your points.

Collapse
 
nickytonline profile image
Nick Taylor

Thanks for reading Dmytro!

Actor Leonardo DiCaprio as Gatsby doing a cheers

Collapse
 
lymah profile image
Lymah

Great post ,@nickytonline.

Collapse
 
nickytonline profile image
Nick Taylor

Thanks @lymah!

Chow Yun-fat giving a thumbs up

Collapse
 
latobibor profile image
András Tóth

I very frequently cite this: every-layout.dev/rudiments/global-...

Utility first will mean you will have too many utility classes.
Tailwind will be gone in 3 years maybe. I still use many early CSS I have learned before 2010. I have used and forgotten many ORMs, yet my SQL chops are still needed.

Another criticism I would make is that many of these libraries work only well, if you already have deep understanding of CSS.

<p class="motion-safe:animate-spin">Spinning text</p>
Enter fullscreen mode Exit fullscreen mode

To know why you have to write motion-safe means you have to know about prefers-reduced-motion.

Both Bootstrap and Tailwind suffers from basically saying "flex" but in their own words: you need to know flex-grow before you can use grow, but then why don't you just write regular CSS flex-grow? Because it is 5 characters longer?

And finally: what happens when you have to restyle everything?

Anyone here remembers CSS Zen Garden? An HTML page with 221 different styles - with only CSS being different. You can't do a thing like this with utility classes.

Collapse
 
nickytonline profile image
Nick Taylor • Edited

Thanks for giving it a read András!

Every Layout is great! I really enjoy Andy Bell's (@hankchizljaw) work along with Heydon's. Andy's Cube CSS is another great project.

I also was a fan of CSS Zen Garden and a more modern version of it in Stephanie Eckle's (@5t3ph) work, StyleStage.dev

I don't think CSS utility classes are going anywhere, and I still think it's important to know how CSS works like.

You might not like the syntax of some of the CSS classes, and that's OK. Like I mentioned at the end of the post, "If you give it a go and say it's not for me, that's OK. Use what makes you the most productive."

Collapse
 
latobibor profile image
András Tóth

Thanks for your correct answer, I'll check out Stephanie's work.

Collapse
 
ifrim profile image
Vlad Ifrim

I personally fail to see the goodness of tailwind from your article.
You're basically forcing yourself to learn a new syntax and writing it awkwardly in an attribute, repeating yourself, losing the semantics along the way.
While missing out on other goodness-es of css like layers, nesting and others.
But it's fine. I hope we can all live together in a world where some people love it and find it productive while others find it simply dumb. No offense intended.

Collapse
 
brense profile image
Rense Bakker

I mean that is really what it boils down to right? People who don't think its a big deal to invent a new language with bloated class name attributes in html code and people who do think that's a big deal. Tailwind is also notoriously bad at doing anything slightly more dynamic, or support slightly more advanced things from the css spec. There are things like cva that make tailwind slightly less of a headache, but why not just go for a styling framework that has those things built in, like PandaCSS, with none of the downsides of inventing a completely new language for styling that is not feature complete.

Collapse
 
nickytonline profile image
Nick Taylor • Edited

If Panda CSS works great for you, awesome.

Like I mentioned at the end of the post, use what makes you most productive.

A panda djaying

Collapse
 
brense profile image
Rense Bakker

I specifically mention PandaCSS, because it works exactly like tailwind, but with none of the downsides of having to learn utility class names instead of actual css.

Collapse
 
szeredaiakos profile image
szeredaiakos

I've been using css since IE5. If someone sais he understands css he has very little idea how to css. Not saying I have perfect css skills, but quite the opposite. I am capable to write up 200 lines of the stuff and have it work on the first try. With normal programming languages one could build an entire 10k line app and have 0 problems on the first try.

So, yes. If you can't express at least 50 correct lines before you end up in an endless cycle of trial and error go for Tailwind but keep in mind, the time you invest in learning it will be wasted in 5 years... You'll have to learn the next css thing... Still worth it tho.

Collapse
 
nickytonline profile image
Nick Taylor • Edited

I still think it's important to understand CSS, but Tailwind is a tool. I don't think it will disappear in 5 years, but we shall see. I also don't think it's for only people that don't understand CSS.

There's SASS, CSS modules, BEM conventions, CUBE CSS, all kinds of tools and methodologies to write CSS

Use what works best for you.

Stephen Colbert saying Welcome to the Nerd Zone my friend

Collapse
 
szeredaiakos profile image
szeredaiakos

Whatever works is not that simple if you are building apps which are expected to las 10 years.

And yes, no tool will ever disappear, people who use it will.