4 ms·
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 contrib
by 9dev 2mo ago
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`.
- guessmyname 2mo agoThe 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.
- gf000 2mo agoIt's not true - agents will visibly struggle more with worse code bases. If anything, certain kind of maintainability matters more in this era, than before, because it is so much cheaper to just generate a huge amount of low quality code.
- deleted 2mo ago[deleted]
- 9dev 2mo agoThat is kind of my point, though—you don't need tailwind-merge, really. There are two cases it solves: One, adding classes from the outside to an encapsulated component with its own, internal classes, to make sure the outside-applied classes take priority. Either use the !important modifier on them (`ms-auto!`), put the components into a container div with the classes for layout concerns, or even better: Figure out why you need to make styling changes to a component that cannot be expressed via props. I would generally recommend components to not have outside-element styling like margins in them anyway, which most often fights with positioning later. Two, merging prop-derived styling with base styles - for example for a `size: 'sm'|'lg'` prop. It's tempting to just use tailwind-merge here: const classList = tailwindMerge( 'p-4', size == 'sm' && 'p-2', size == 'lg' && 'p-6', ); But that isn't necessary at all: The better alternative would be to use data attributes for visual concerns and built-in or aria attributes for interaction states. There are almost always element attributes that can represent what you want to have correctly, and data- where there are not. Then, you can just add a class accordingly: <span class="p-4 data-[size=sm]:p-2 data-[size=lg]:p-6 data-active:font-bold" data-size={size} data-active={active} /> And you'll end up with easier to maintain components that derive their styles from the CSS cascade alone.
- francislavoie 2mo agoI would reach for class-variance-authority (aka cva) instead for stuff like a size prop, it declaratively solves that.
- 9dev 2mo agoInteresting, I didn't know that project yet! I'll give it a thorough read.
- marcus_cemes 2mo agoI 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.
- yurishimo 2mo agoIt’s random sure, but it’s also reliably random. This is one of the few footguns that exist in tailwind and luckily it’s super easy to catch. The IDE plugins will give you a warning if you apply multiple classes that manipulate the same attribute and there is no reason you also can’t catch it in CI. Is it ideal? I guess not, but there are a lot of weird gotchas and footguns in CSS too. Just because they’re in the language doesn’t make them magically more or less of a problem. For a similar weird mental shift, consider adding @starting-style and the native popover open attribute. All the good tutorials online have a warning about cascade order because as a human reading it, it can seem wrong or backwards. Kevin Powell’s most recent video about animating display: none covers it if you want a concrete example.
- andrewingram 2mo ago> conflicting styles don't make sense Sometimes true, but one issue here is that because Tailwind utility classes vary from being a 1:1 mapping to a single underlying style rule, to mapping to several, it's not always obvious which classes will conflict.
- 9dev 2mo agoNote that we're talking about an edge case for an authoring error - applying two conflicting styles to an element does not make sense, it has no defined behaviour, and is correctly flagged by linting tools as such. Should Tailwind really go out of its way to pay a compile time tax, just to make this case resolve predictably? Or should people rather use code editors that point out invalid duplicated styles, which are always added in error?
- zelphirkalt 2mo agoI 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).
- francislavoie 2mo agoAbsolutely not. Semantic classes are the wrong way to go. Your components (and their props API) are what encode the semantics. With Tailwind you never need to try to come up with a name for anything relating to style, you just use utility classes. It reduces cognitive load significantly.
- drdaeman 2mo agoAnd so we’re essentially back to <font color=red size=10>?
- trixn86 2mo agohave that wrapped in a component named ErrorText and it makes perfectly sense. Why would you need a component ErrorText which restates its own name in the classname again when that classname is only ever used in that exact component. If anything you only need it because your atomic styles sit in another file and you somehow need to reference them. If you have both in the same file with a name ErrorText there is nothing more to give any semantic meaning. Semantic class names make no sense in a component context and that's why tailwind feels like a liberation in the context of component-based web applications. A component and its interface is the semantic meaning, the markup and styles it contains are scoped to that component and should not be / need not be semantic at all. This greatly reduces cognitive load.
- boxed 2mo agoProjects with a single gigantic CSS file also work and you can onboard people etc. That's not an argument.
- 9dev 2mo agothey do work… for any value of work. I have been in the industry for a while, and I've never seen a project which doesn't slowly devolve into fights with the cascade over time - arbitrary abstraction layers, ad-hoc organization patterns, developer-specific conventions, inconsistent naming, and so on. All of this usually creeps in the more a project grows. At some point, someone adds postcss or scss or another preprocessor and starts splitting files, and then a whole new set of new, made-as-you-go conventions comes in: Files per component or per view? Or rather per architecture concern? Usually a mix of them. As files are split, the class naming gets even more inconsistent. And at that point, onboarding a new developer always means wasted time on understanding this whole organically grown set of bespoke conventions, class names, patterns, hierarchies, and so on. Tailwind does not really have this pattern of deterioration growing along both time and complexity, it stays consistent on both axes. So it's definitely an argument IMHO.
- crab_galaxy 2mo agoTailwind trades cascade complexity for design drift when working across teams. You can’t ignore that it encourages a different kind of undisciplined sloppiness. Would I take it over the 1000 line cascade problems? Probably, but I’d still prefer css modules over tailwind.
- 9dev 2mo agoWhat kind of design drift do you mean? You set `--color-surface` in your theme once, then all surfaces in the app use the same color with `bg-surface`, regardless of the theme authoring parts of it. I don't know how you could enforce more consistency to CSS authors than Tailwind does.
- boxed 2mo agoWhat do you mean it trades cascade complexity? The cascade complexity in CSS itself, tailwind can't turn that off, you always have that.
- SebastianKra 2mo agoI 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.
- bko 2mo ago> 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?
- DanielHB 2mo agoThere is this implicit debate in web application development of cascading+overriding vs non-cascading-no-overriding. A lot of people don't even realize this is where the line is drawn and mix both together. I call them "component-based", "document-based" and "mixed". Component-based applications are usually better of with no styling cascading and no styling overriding. It makes things significantly easier because components are self contained and don't change in appearance based on styling of parent-elements on the tree (besides physical dimensions available and transparency effects of course). Document-based applications are usually better of with cascading and overriding. Although no-cascading-no-overriding can work too, but requires more code. Component-based is quite difficult to do without some tooling (like tailwind or css-modules, etc). Most CSS tooling support both though. Tailwind implicitly forces you into the component-based paradigm but never explains it properly. There is a reason why people who love tailwind say it just makes things much more manageable. It is mostly because it removes the "mixed" mode that projects silently fall into[1] unless there is some guiding force towards component-based. However component-based approach is quite doable with many different CSS solutions. Tailwind just _forces_ you into it. For example CSS-modules component-based just means one .css file per component with only .className {} CSS selectors and not relying on cascading values from above in the tree (a few global rules can solve this). [1]: Mixed mode as I call it is mixing hyper-local rules with cascading rules. They fall into this mode because that is how plain CSS works without extra tooling and guidelines.
- dzonga 2mo agoauthor 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.
- _heimdall 2mo agoI'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.
- thiht 2mo agoWell yeah, people need to learn the tools they’re using. How’s that shocking?
- bdangubic 2mo agothat ship has sailed loooong time ago, hence endless “why we stopped using _____” blogs that make the front page
- _heimdall 2mo agoIt isn't shocking and that wasn't my point. The OP is pointing to benefits of tailwind related to onboaring new devs, I was just raising that doesn't match my experience. If a new dev doesn't know CSS well it won't help them. If a new dev does know CSS but doesn't know Tailwind, it still won't help. The standardization can be claimed as a benefit, though it really amounts to avoiding having to architect how CSS is managed in a project and at the end of the day the solution is to just inline styles one a time (I.e. no cascade or stylesheets). Though a bit unrelated, I take issue with the core promise of Tailwind - localization of styles on a node. As soon as flexbox and grid enter the picture I can't simply look at one node and know how it will render. Even more egregious is groups, though a useful feature it breaks locality of styling even worse. Throw in less used but valid syntax for attribute selectors, modifiers, sibling selectors, etc and you might as well be in CSS. Last I used TW it also didn't have an answer for using things like :has() though that could have changed.
- simonsarris 2mo agoalso note that `class="text-red-500 text-green-500"` gets flagged immediately by the Tailwind VS Code plugin > 'text-green-500' applies the same CSS properties as 'text-red-500'. tailwindcss(cssConflict) So even if you do it by accident, it will tell you.
- nailer 2mo ago> You can onboard new developers to it, able to contribute productively immediately Maybe it helps with people nee to Web development but as an existing CSS developer tailwind slows me down incredibly. I know exactly what styling I wish to apply, I now have to translate it into another language to apply it. And the browser inspector looks terrible because every element has a long bunch of utility classes added to it.
- FireBeyond 2mo agoThe "rounding" was grasping at straws: > How round is rounded-lg? Author: "In my vanilla CSS, I can read it in the CSS file. In Tailwind, who knows?!?" Reality: You read it from location 2, not from location 1. The horror. I don't even have a dog in the race. I'm past my days of handcrafting HTML and CSS. I have a few Claude Coded apps that use Tailwind, but I've not looked at any of the files (yes yes, I know. They're personal projects that run in my homelab. I don't care.)
- 9dev 2mo agoI would even say the answer is... however round "large rounded" should be. Tailwind doesn't force arbitrary opinions on these things upon you - it's a set of utilities to enforce your design system. If rounded means 6rem, so be it. There is, as you said, a single place to configure your design system (a CSS file, fwiw), which is objectively better than "well for these card-like containers we usually use 5px everywhere." Besides, I'm really wondering what sad jokes some people use to edit code that don't even offer tooltips for the styles getting applied by Tailwind classes.
- meerita 2mo ago[flagged]