This is such a bikeshedding debate. While you don't recommend it, projects with Tailwind work. Over years. You can onboard new developers to it, able to contribute productively immediately. Likewise, you can pick up work after months or years and don't have to remember or rediscover how your styling layer works.
The conventions and class names come really naturally fast, and you can always look it up. It's just not as a big of a problem people make it.
But the most ridiculous part of the article I found the cascade complaint:
<p class="text-red-500 text-green-500">I am some text</p>
Yes, this does not work. Why should it?! There is not a single use case where this is a good idea! In classic CSS, you might want to override something based on modifier classes, but that is just not a thing with Tailwind! If you end up programmatically layering class names, you're looking at a code smell. Instead, you want to use attribute or state modifiers, like `aria-hidden:opacity-0`.author of the article is making a logical argument - in matters of human behavior. that never works.
author should've instead asked himself & the world - why people are drawn to tailwind. yeah technically it's inferior - but in terms of being optimized for how people do things - tailwind is superior.
I can see this argument both ways. On the one hand, logically you'd expect the last assignment to take precedence, like the style attribute. On the other, conflicting styles don't make sense.
The random outcome, entirely dependent on the Tailwind generation internals, is the worst of all worlds though, it's just an unfortunate side-effect of relying on cascading sheets to drive atomic styles.
I wouldn't even write such a class name. It smells like bad styling and layouting already. A CSS class should convey some semantic meaning. I would name it after the thing that should be red or green, not "red"/"green". That doesn't tell me anything. Maybe its name could be something like "danger" or "active" or something. Also the 500 looks very sus. Responsive design is best when it avoids such hardcoded numbers and depends on its content and dynamic viewport width calculations, and perhaps a few minimum sizes, if necessary to decide when things float, wrap, shrink, grow, etc.
It's a red flag (ha).
The fact that “text-red-500 text-green-500” resolves by stylesheet source order rather than anything visible in the markup means the “locality of behavior” promise quietly breaks exactly when you compose components dynamically, which is why tailwind-merge exists at all, and needing a runtime dependency to answer “which of my two classes wins?” is a real design smell, not a bikeshed.
> If you end up programmatically layering class names, you're looking at a code smell.
Why wouldn't you? Suppose you have Button class with `btn btn-primary`. The Button accepts className override so you can do <Button className='btn-secondary'>. In this case you use tailwind-merge or clsx. Your Button implementation would be clsx('btn btn-primary', className), in which case right most class name prevails.
Other than that, I agree tailwind is great. It lets you keep things all in one place. Names aren't particularly difficult to memorize and reason about and autocomplete does a great job. Build utility classes or proper components to encapsulate the styling and you're fine. What benefit do I have going to a css file to review my button styling over the actual Button component?
I agree that all of this is bikeshedding, but the cascade complaint is actually real.
It's so common, that there is an expensive runtime package, `tailwind-merge`, that is used by default in the most popular component library.
Projects with a single gigantic CSS file also work and you can onboard people etc. That's not an argument.
I've never found tailwind to help someone who isn't already a reasonably skilled web developer. If you don't know CSS tailwind gets your far enough sometimes, but you have to learn many of the same paradigms as you would in CSS and you can still create issues that aren't as simple as missing "text-green-500".
Tailwind seems most useful for devs who don't want to be responsible for managing multiple CSS files and all the naming conventions that come along with it. They're basically looking for using inline styles after having likely heard for a long time to not use the style tag.
For me at least, any value from tailwind went out the window when frameworks started leaning into single file components and scoped styles. I keep components small enough that generally my style selectors are only using element and attribute selectors, I dodge the class naming issue entirely and still get to use CSS instead of inline styles.