Hacker News new | ask | show | jobs
by alwillis 37 days ago
> tailwind frees you from having to spend excessive time building abstractions of styles/classes that will invariably change.

Abstractions like a hero image, a menu, a headline? Sure, it's easy to overthink things but most of the time, it's not that complex.

> placing the styles directly into the markup that is affected by it reduces cognitive load, prevents excessively loose selectors

In my opinion, it's the opposite. Besides the obvious violation of DRY and the separation of concerns, inline CSS can't be cached and it creates a lot of noise when using dev tools for debugging. It actually increases cognitive load because you have to account for CSS in two different locations.

Lots of people use Tailwind because they don't want to deal with the cascade, usually because they never learned it properly. Sure, back in the day, the web platform didn't provide much built-in support for addressing side effects of the cascade, but now we have @layer and @scope to control the cascade.

Tailwind uses a remnant of '90s web development (inline CSS) and built an entire framework around it. I get why it appeals to some people: it lets you use CSS while not requiring an understanding of how CSS works, beyond its most basic concepts.

12 comments

> Sure, it's easy to overthink things but most of the time, it's not that complex. then you sir are the one that have not worked on complex projects. i'm currently the lead on a design system for a fortune 100 company with nearly 100 block level components and many other smaller elements. responsive, multi-theme/site support, animations, accessibility, robust interactivity, etc. not even a button or link is simple when you're building complex systems tailwind allows us to reason more clearly about these often very complex components

> inline CSS can't be cached

this shows your lack of understanding. first off, it's not inline css, they're classes and thus you only ever define "flex" in one place vs many many places in non-utility css approaches. in fact, sorted html classes are compressible over the wire so you're doubly wrong.

> because they never learned it properly condescending

> it lets you use CSS while not requiring an understanding of how CSS works, beyond its most basic concepts also condescending and just such a boring, over used argument i always hear from haters of tailwind maybe try and counter my arguments without the attitude? maybe understand seasoned veterans of css might have their reasons to choose it?

if you're writing class="flex-inline width-30 font-large" it's even worse than inline css because it has an abstraction layer and dependencies.

just write css, tailwind has always been total junk.

There are legitimate problems with using CSS, especially in a large team setting. I think we all have experience with append-only stylesheets. That's what tailwind addresses.
I have used tailwind and tachyons and they are fine. I do winder though it seems like you end up being stuck with them. How would you migrate to traditional CSS without effectively rewriting all of your css?

I also wonder if it is necessary still with css modules and the fact web frameworks allow for scoped css per component.

Tailwind is just CSS so there's no lock-in to speak of and no migration necessary. If you had a specific instance where Tailwind wasn't a good fit you can just hand-write as needed.

Sure, if you wanted to stop using Tailwind altogether you would have a lot of rewriting to do but I'm not sure how that's uniquely different or worse than, say, migrating a project from React to Angular.

I disagree with that conclusion. I see tailwind as a cleaner more succinct version of css that is much easier to manage and add features too.

Sure it’s not as dry, but I’ve been bitten in this regard because css framework and templates are so intransparent, preventing me from simply changing padding or margin.

CSS is too detailed and too verbose. Frameworks like bootstrap are too high level and don’t give enough control. Tailwind hits the sweet spot whilst allowing me to be detailed if I want to. It allows me to just get it done.

> Sure it’s not as dry, but I’ve been bitten in this regard because css framework and templates are so intransparent, preventing me from simply changing padding or margin.

How does this happen? You can always override css values. Either by ordering, !important, inline or, to make very sure, with inline !important.

When you inherit a front-end project for the Nth time, those `!important` become a nightmare.
I found that once I started needing to use inline styles or !important or in-line important, I was in for a world of hurt and felt sorry for whoever maintained the project after me.
With CSS names are global. You have to be careful not to accidentally create a class that conflicts with another one used elsewhere in a different context. You have to worry about whether modifying your class will have downstream effects on elements you weren’t intending to impact. It’s a giant pain. I’ve done it by hand for around 20 years before switching to Tailwind.

Can vanilla CSS be used for a complex app? Yes. But, it takes discipline, and I only have a limited amount of that. I’d rather spend my discipline budget on other things.

That said, nested selectors and CSS variables have gone a long way towards making the vanilla experience much more pleasant. I may have to give it a shot on a side project one of these days.

> With CSS names are global.

Not necessarily. Nested selectors make it pretty easy to apply styles in a modularized way. See https://rstacruz.github.io/rscss/

> With CSS names are global.

You can limit selectors (not custom properties) to a subtree by using @scope.

On the horizon is @function [1] where custom properties can be local to the function.

[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/Reference/A...

> With CSS names are global.

In your "programmatic" code (your JS/TS, python, C++, whatever..) your classes are global. Even if the language supports flexible namespaces, or module scoping, you still have to take great care naming because reusing a name will cause you confusion. Giving two things the same name makes them harder to import, and risks clashes and bugs.

No-one complains about this. This is just how you code in all those other languages.

In "programmatic" code, declaring two classes with the same name in the same namespace is generally either some sort of syntax error or one will "shadow" the other; it doesn't just silently merge the behavior of both classes.
TypeScript interfaces just merge. You can aet any property name you like on a plain JS object, at any time.

The CSS version is a risk, for sure. The dev tools in all the main browsers will tell you where the extension happens and show yiu the order the complecting rules are applied, so it’s fairly easy to debug. Bugs/misbehaving code is usually a problem of structure. In other languages, we take on the need to apply structure; just do the same with CSS.

The mechanism that allows this merging behavior is the means by which intentional reuse is composed. It allows yiu to set general and specific rules sets. This seems conceptually similar to OO classes and subclasses, to me.

the 'silent merging' you're talking about is the c in css
Modules make the global thing less of a concern these days.
This is (imo) the most valid argument for Tailwind: the UI semantics of "hero" "card" etc aren't put in CSS, they're put in the module. Modules are typically designed for this encapsulation, and CSS was not.
when i say css modules i mean something more akin to https://css-tricks.com/css-modules-part-1-need/
> You have to be careful not to accidentally create a class that conflicts with another one used elsewhere in a different context.

Has your tried using the cascading part of the language?

Unless you're duct taping together a wide variety of kitchen sink dependencies, namespace shouldn't be a problem.
Your framing assumes incompetence across the board which is unlikely to be true for a framework of its popularity. Consider instead competent people are working on projects with different needs and they’ve recognized there are trade offs to both approaches and still decided Tailwind makes sense in their situation.
To be honest, CSS had the cascade but also had horrible tools for actually managing the cascade for a long time.

If CSS had nesting, variables, media queries, the other nice selector queries like :has, and modules out of the gate, we likely would have not needed much of the tooling like tailwind that eventually got built to manage it all with less boilerplate. We built the tools because even when these features rolled out they came in fits and starts so you couldn’t adopt it without polyfills and whatnot.

When you say modules, is that @scope or something else? I can't find any reference to a native thing called modules but this seems to fill the same role.
So I guess modules is not native, but in a fair amount of JSX oriented systems there is a .modules.css file extension that build steps will recognize and automatically namespace with an ID linked to a JSX component.

https://github.com/css-modules/css-modules

> inline CSS can't be cached

Can you elaborate what the problem is? What is it you want to cache?

> and it creates a lot of noise when using dev tools for debugging.

I don’t think so. The element styles have an own section (assuming you debug the applied styles)

> It actually increases cognitive load because you have to account for CSS in two different locations.

Same applies to no tailwind. You need to account for the html (is parent block / inline / …) anyway.

Tailwind violates DRY but DRY is also not a hard and fast rule. The danger with DRY is that it can force you to build abstraction towers that are difficult to reason about, especially in a static context. And that's where we see the power of Tailwind: I can look at any element and immediately see it's styling. The same is not true with classic CSS, which is additional cognitive load.

Also, DRY can still be somewhat achieved with tailwind by using reusable components, in whatever framework you're using. It could be React, but it could even be blade components in a traditional SSR Laravel app.

Premature DRY and premature attempt at separation of concerns have resulted in absolutely horrible spaghetti code in too many code bases.

Many times it's fine to repeat yourself. Many times it's fine for a component to cross multiple concerns.

DRY is critically important as it pertains to correctness. If DRY is hard to achieve for technical reasons then back-reference comments and whatnot can suffice, but you really do want only one owner for each meaningful fact in your codebase.

That's not to be confused with syntactic similarity. I largely don't care if you have ten different identical circular buffer implementations, so long as semantically it's correct that when one changes the others don't. Depending on the language maybe it would make sense to use type aliases or extract some common subcomponents or something, but duplication itself isn't a problem.

This is an excellent resource for using CSS as it was designed to work. It'll give you a different perspective on using CSS [1].

[1]: https://every-layout.dev

> It actually increases cognitive load because you have to account for CSS in two different locations.

How does doing everything in-line (one place) cause two locations?

Thanks.

> inline CSS can't be cached

Classes are now in-line styling? Why are you doubling down on a subject you're obviously not familiar with?

And the separation of concerns argument is always strange to me because in React, my concern is the component.

Trashing without offering a hands down solution is academic and therefore can safely be rejected.

Please show me only ten of the SaaS you lead that rely on your CSS framework.

You must have one, because you talk about structure and premises. Orderly put and repeatedly applied you get a framework.

I doubt it.

I registered my first domain 1997. I love to debate anyone coming up with a clever not so clever theoretical argument against Tailwind.

Where are all the you might not need jQuery JavaScript guys?

The same goes for Tailwind.

And just as a reminder: CSS started as so called separation of markup and design. A zen garden tried to proof this but only showed how one cannot exist without the other.

Loose coupling as the saying goes.

Since the ACID test CSS went from some proposals to a stunning black hole of finally receiving differential treatment with the level nomenclature.

And you besides all incompatibility issues and different browsers still think that you really grasp CSS or even know how to apply it semantically correct even though by matter of fact many concepts feature bogus terminology due to compatibility issues?

I would love to interview you regarding edge cases. Do you get box models? Collapsing markings? Floats? Clearfix? Order of application?

Print layouts? Views vs fluid design?

Really, attacking Tailwind is the same as “Let’s build our own Google” trope. It shows lack of competence.

> love to debate anyone coming up with a clever not so clever theoretical argument against Tailwind.

Given your attitude (see your last sentence for a prime example), why would anyone want to debate you?