
I’ve been contemplating writing a critique of Tailwind CSS for years. Initially, I assumed Tailwind was simply “not for me” and moved on. However, as it has grown in dominance, I’ve realized its impact on the ecosystem is impossible to ignore.
Technically, Tailwind is a CSS generator. It scans your project for utility classes and generates a stylesheet based on predefined rules. This approach ensures that unused class names are excluded, and the use of shorthands (aliases) instead of long-form CSS rules is understandably popular. At first glance, the benefits are clear: reduced bundle sizes and the convenience of styling elements without switching to a separate CSS file. It seems peaceful—but that peace is fragile.
If you stick strictly to Tailwind’s built-in classes, you are safe for the time being. However, the moment you implement custom plugins to support modern CSS features, you hit a wall. The CSS standard is evolving rapidly, and Tailwind cannot always stay up-to-date. To access new features, you must often do the heavy lifting yourself. Writing complex @supports fallbacks within a Tailwind configuration file result in code that is far less readable than native CSS.
Furthermore, there is the risk of technical debt. You have no way of knowing if your custom solution will align with Tailwind’s future official implementation. One day, you may be forced to migrate by replacing obsolete class names, or worse, your design may break due to naming conflicts.
Complicated styles are particularly difficult to express in Tailwind. Styles that require deep nesting or heavy reuse become chaotic when crammed into class attributes. This “flat” approach makes maintenance a nightmare. For instance, writing calc() functions in Tailwind is a frustrating experience compared to the clean syntax of a stylesheet.
One might argue that we should simply switch to native CSS for complex styles since Tailwind is compatible with it. However, in the era of modern at-rules, nesting has become essential. When dealing with multiple at-rules, nesting provides structural clarity and improves the quality of the developer’s logic. It allows me to compose refined CSS more quickly because I can see the hierarchy in a clean list rather than a compact muddle of strings.
While native CSS nesting is now widely supported, I still cannot abandon Sass. I cannot ignore the ~8% of users on browsers that don’t support native nesting; without it, the entire layout breaks. During this transition period, Sass remains crucial. Yet, when looking for guidance on integrating the two, the Tailwind documentation states:
“Think of Tailwind CSS itself as your preprocessor — you shouldn’t use Tailwind with Sass for the same reason you wouldn’t use Sass with Stylus.”
This is dogmatic. Tailwind is powerful, but it is not a total replacement for a preprocessor. By failing to acknowledge its weaknesses or accept superior tools for specific tasks, Tailwind Labs is letting down developers.
As CSS evolves, development is becoming more straightforward, not more complex. Modern features such as @scope, nesting, sibling-index(), and scroll-driven animations allow us to build maintainable projects without legacy overhead. CSS is becoming more structural and comprehensive.
Structure overshadows flatness. Clarity comes from organization, not obfuscation. We should not step back to a time when we put all our styling in I’ve been thinking of writing a post to criticize Tailwind CSS for a long time, maybe years. I used to suppose that Tailwind didn’t have much to do with me. However, as it developed, I gradually became wrong. Tailwind, in fact, should be considered to be a CSS generator. It finds all mentions in your project and generate CSS according to its rules. So unused class names are not included in generated CSS. Plus, Tailwind’s class names are utility-first and are shorthands of the original CSS rules. This is highly appreciated. No long CSS rules any more, the developers use aliases. It’s easy to expect that the bundle size is reduced. Developers no longer need to go to a separate CSS file for their styles. Seems peaceful? I hope so. If you only use Tailwind’s built-in class names, you’re safe for now. But if you implemented some custom plugins to extend support for more CSS features, you have no way out. CSS standard is changing fast, therefore Tailwind can’t be always up-to-date. To access new CSS features, you’ll have to do this job for Tailwind. With complex And, you don’t know whether your solution corresponds to the future Tailwind’s. You may need to migrate to official support in some day in the future by replacing all your obselete class names. Or even worse, your design may break in an unexpected way because of naming conflicts. Complicated styles are particularly hard to convey in Tailwind. Some styles need nesting and heavy reuses. Writing them again and again in class names not only creates chaos, but also makes it more difficult to maintain. Calculation in CSS is one of the most notable point here as it requires rational logic and clean syntax to avoid mistakes. You won’t love the experience of writing Till here, you may say that we should switch to native CSS for complex styles when needed because Tailwind is compatible with CSS. But in the era of at-rules, nesting becomes so essentially that I cannot live without it. Especially when dealing with many at-rules, nesting helps me make structure clear and improve my thinking quality. I’m able to compose a fine CSS in a shorter time because I can see what I’ve done in a clean list, not a compact chaos. However, though native CSS nesting is now widely supported, I still cannot remove Sass. I can hardly abandon the 8.07% browsers that doesn’t support nesting because the whole webpage breaks without it, which makes it crucial, not optional. As for now, we still need Sass during the transition. After that, when I’m trying to look up the docs for the guide on how to add Sass to a Tailwind project, I found: Think of Tailwind CSS itself as your preprocessor — you shouldn’t use Tailwind with Sass for the same reason you wouldn’t use Sass with Stylus. That’s dogmatic. Tailwind is powerful, but not enough. Tailwind Labs is not facing up to their weakness, meanwhile not accepting better replacements, making CSS developers like me feel disappointed. As CSS develops, CSS developing is only becoming more straightforward and never more complex. Modern CSS features like nesting, allows you to build maintainable projects without the tools we used to use. CSS is evolving to be more structural and comprehensive. Structure overshadows flatness. Clarity comes from organizing, not mixing. Do not step back to the time when we put all CSS in style attributes. For the sake of our common future, please do not choose Tailwind.Manuscript
@supports for fallbacks, your Tailwind configuration file will be much more unreadable than native CSS.calc() in Tailwind.style attributes. So do not Tailwind please, for our common future.
About this Post
gemini-3-flash-preview. The cover image is generated by gemini-3-pro-image-preview.