TailwindCSS is a prominent CSS framework that has grown in popularity in recent years. It has a wide range of pre-built utility classes that make styling HTML easy. My opinion on Tailwind is mixed, as it seems to provide the same amount of benefits and drawbacks.
Design Constraints
TailwindCSS's design constraints are one of its greatest advantages. It includes a set of precise design principles that maintain a uniform look and feel across all website parts.
Extensibility & Configuration
Tailwind's config file allows you to create any number of CSS properties, and their new JIT arbitrary values are essentially inline css - which in some cases is exactly the issue with Tailwind.
Preflight
Tailwind Preflight is amazing - built on top of modern-normalize, Preflight resets the default inconsistent styles across modern browsers. In addition to modern-normalize, Preflight:
- Allows devs to apply a border just by setting a border width
- Ensures horizontal rules are visible by default
- Removes gaps between table borders by default
- Resets all font sizes, buttons, and other styles on elements to allow the user to rebuild them without any default styles getting in the way
- And much more
I would actually use preflight in a project without Tailwind.
Tailwind is great, but there are a lot of drawbacks.
Lack of Abstraction
Tailwind CSS doesn't abstract away the underlying CSS. Instead, it provides a set of pre-designed utility classes that simply modify the styles of HTML elements. This can sometimes result in massive, bloated class names that are not that better than inline styles.
Repetition
Tailwind isn't as friendly to reusable components compared to something like BEM. Applying styles to a component becomes tedious, and even Tailwind acknowledges this.
<div class="mt-3 flex -space-x-2 overflow-hidden">
<img class="inline-block h-12 w-12 rounded-full ring-2 ring-white" src="https://images.unsplash.com/photo-1491528323818-fdd1faba62cc?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=facearea&facepad=2&w=256&h=256&q=80" alt=""/>
<img class="inline-block h-12 w-12 rounded-full ring-2 ring-white" src="https://images.unsplash.com/photo-1550525811-e5869dd03032?ixlib=rb-1.2.1&auto=format&fit=facearea&facepad=2&w=256&h=256&q=80" alt=""/>
<img class="inline-block h-12 w-12 rounded-full ring-2 ring-white" src="https://images.unsplash.com/photo-1500648767791-00dcc994a43e?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=facearea&facepad=2.25&w=256&h=256&q=80" alt=""/>
<img class="inline-block h-12 w-12 rounded-full ring-2 ring-white" src="https://images.unsplash.com/photo-1472099645785-5658abf4ff4e?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=facearea&facepad=2&w=256&h=256&q=80" alt=""/>
<img class="inline-block h-12 w-12 rounded-full ring-2 ring-white" src="https://images.unsplash.com/photo-1517365830460-955ce3ccd263?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=facearea&facepad=2&w=256&h=256&q=80" alt=""/>
</div>
you’ll inevitably find yourself repeating common utility combinations to recreate the same design in many different places.
Their solutions are flimsy at best. They recommend that you
A) Use a framework, which not all developers want to do, or
B) extract styles with their @apply
directive, which do anything about the problem Tailwind was intended to solve.
The first solution works fine from a workflow standpoint, but at compile time you're still left with bloated class names (even if Tailwind purges unused css) that in some cases can balloon file sizes.
Aleksandr Hovhannisyan - Why I Don't Like Tailwind CSS
Conclusion
Tailwind is great for rapid prototyping. It's extensibility makes it trivial to stay conformed to a design system. Preflight is one of the best ideas ever, and more people need to use preflight or modern-normalize to make their lives easier. Unfortunately, Tailwind also suffers from large, sometimes unmaintainable class names that can be extremely repetitive and balloon your HTML file sizes.
Thanks for reading! REMEMBER TO USE MODERN-NORMALIZE IN ALL PROJECTS FROM NOW ON
Top comments (23)
Good post.
I agree with the general thoughts here, also feel like Lack of Abstraction is probably the most surprising delight here. The shallowness of the abstraction makes it such a good layer for so much work I've done with it.
I'd say my biggest agreement here is the repetition part here. Tailwind gives you a lot of rope to hang yourself with, and I think the right way to avoid problematic repetition is whatever you come up with yourself, Tailwind isn't helping much!
I’d say that Tailwind CSS is definitely not my favourite CSS tool, but I’d point two advantages of the tool anyways:
speed of development, since it’s a library of pre-defined classes and you can create designs quickly.
consistency, since it reduces the need of custom CSS styling.
I’d say, the configuration is the worst part of it.
Still, CSS can be so powerful and so much more fun to work with, as long as you invest the right amount of time to it. There are far cooler tools to use like Styled Components, for example :)
Disagree, Styled components feels like it's counter-intuitive and it's an unnecessary bloat.
Could you please elaborate on that? I mean, it’s not the easiest tool to learn either, but it does offer more reusability when you compare it to building CSS modules in a React project, but that’s just my opinion. Would be keen on hearing about others’ perspectives as well!
Styled components are 12.42kB min+gzip on base, so a bit large. I do like how it is similar to tailwind in that your styles aren't decoupled from html, and there is twin.macro for tailwind. I also think you should check out Stylify from @machy8, which is a cool hybrid of the two.
I understand your point and reasoning!
Thank you for sharing your thoughts and for the recommendations!🙂
you're right.
I was about to mention configuration. It's still something that bothers me on every project...
I personally believe that traditional CSS is a lot better, it's not that hard, and it's more reliable.
Hi @gravy59 ,
I have posted Best Practices for Utility-First CSS right now and saw your article.
I understand your points, but in the same time I disagree with you.
Even though I am the author of Stylify CSS, which is an alternative to Tailwind, I will defend the Utility-First CSS "base" here.
In my humble opinion, I think, that a lot of "bad things" about Utility-First CSS (Tailwind, Tachynos, others), simply come from "laziness" and the "simplicity of utilities usage" and a lot of them can be avoided by simply thinking things ahead, splitting the code and using the tool features correctly.
You can style any website that is using Tailwind with pure CSS, but let's face it, writing CSS isn't easy. It is for a small blog. But when the project starts to grow, you can get even 200+ css files. It's hard to maintain, clean, and compose together to get the correct bundle for the page, selector names often makes no sense and not even bem will help you, there are lot of duplicates, etc...
Every tool have its cons but utilities solve a lot of issues, not just fast prototyping and small size.
But I understand that not everyone likes to see a lot of classes in one attribute.
I agree that their solutions to repetition are flimsy at best… but they also highlight the fact it doesn't really solve the problem it claims to —as you point out.
If you need Svelte or Vue (or any form of templating) to factor repetitive patterns, this days it means you also have css scoping anyways. Meaning you can just name your stuff carelessly… if you name it at all. I mean, I hardly use classes in Svelte, I just go straight for nodes 🤷 And then, you just jump the problem one level up: you don't name your css classes, but you have to name your components.
And then again, you build fast, but how maintainable is it? Want to change all spacing in cards. You look for
.card-spacing
? Of course not, you hunting formx-4
… ho, unless that one that was anmx-2
with apx-2
and that one that looks like a card but is panel… "We should put names on things, no?"Great article, you got my follow, keep writing!
When I make simple HTML without any CSS, just enough to import tailwind cdnjs and that is enough for joy all advantage, for example: tailwind sticky test - I make one css for
<p>
. Much fare easiest solution, and I never need to think about class names.your example in react:
My brain works best with backend development but I should say that Tailwind CSS is the only frawmework allowing me to build beautiful UIs. It's very logic in its approach and coupled to a framework like NextJS it feels like perfect to me.
Everything is a component, each component has inline CSS. For common things like titles, images, etc... I use the
@apply
directive. Works like a charm, the feedback loop is really fast and unless you have important size constraints I can't see how Tailwind CSS is an issue.But as I said, I'm more a backend developer than a frontend developer so not an expert at all!
Not to mention their solution for repetition: use a framework... A lot of UI component frameworks make using tailwind obsolete.
Another major drawback of tailwind is that it does everything at compile time, making it impossible to access your configuration at runtime, something that css-in-js solutions do support. For example in emotion you can access the entire theme object at runtime. Because tailwind classes are made during compilation you also cant use any dynamic values. For example, if you have to make a white label app... You'd have to use css variables and manipulate those with your own custom JavaScript which is extremely obscure and sucks for maintenance.
You actually can access the config at runtime - just importt your tailwind config as an es module.
There's also twin.macro
Interesting post, @gravy59, but there are a few points that I feel need clarification or expansion to give everyone "the whole picture".
I originally started writing a comment, but it got a little long, so I moved it to a post instead:
TailwindCSS is great; why so much hate?
Dan Walsh ・ Feb 2 ・ 4 min read
Thank you! I appreciate your insight - I also love tailwind but I try to see both sides of an argument. I didn't realize you could gzip html!
I'm glad you enjoyed my post reply! I'm always a little worried it might be taken poorly. So glad we can have productive conversations on dev.to! 😊
Yep, gzip is awesome, but not something (as a frontend developer) you typically have to worry about, as your sever-level configuration should have gzip compression configured and enabled.
Im always use tailwind for Vue project, usually I use the framework too like daisyUI, and I agree about the bloated css class names that's why I use
@apply
I mean sure, if a developer doesn't want to adopt the approach that Tailwind recommends, then they will have an unsatisfactory experience. Tailwind is not for everybody, not everyone wants to adapt to its recommendations. That's OK, but painting that as a downside of Tailwind is like saying that a downside of tea is that you like coffee better. Doesn't really make sense.
Every time I hear the word “framework,” my hand involuntary reaches for the Reset button. When it is qualified by the adjective “opinionated,” it's the 7lb hammer and not the Reset button, for it's ideology sensu primo pushed upon you.
Historically, most of the successful frameworks has never been called so, neither by their authors nor users. In fact, of successful AND self-termed frameworks, I can probably name only .NET. I've been in the trade for 35 years.
In terms of project planning, If you have to use a framework self-termed or widely accepted to be a “framework,” multiply your time estimate by 10. This is my standard.
Oh, and I never wrote a Web site in my life, or heard about this this Tailspin framework, or how it's called. Even less had any reasons to use it. My statement is general.
Good points.