Which... is asinine. One is simply a redacted and simplified expression of the most common implementation of the other case.
Tailwind falls into the same bucket - in my opinion. Like most frameworks, it's not there to handle your niche and complex use-cases. It's there to provide bumpers that push you into a pit of success for common use cases.
When you need to do something that's not common - use the escape hatches that are built in. That's not leaking - that's giving you the flexibility to fall back to a custom implementation.
The goal just isn't "abstraction" from css. It's common-sense, local, and consistent styling for common cases. I can build most lego sets from single square blocks - but it's nice to have a bigger selection available. Does that mean I need to understand those bigger pieces to make sure they fit, don't have weird gaps, and line up? Absolutely. Does that mean I shouldn't use them? No, probably not. But it does mean that sometimes I still need single square blocks.
Let’s look at typescript, or sass. There is (afaik) no construct in the underlying js or css that cannot be represented using them.
You could conceivably never learn javascript, learn typescript and basically be fine.
So when people say “leaky abstraction” they seem to be assuming that tailwind, which is a framework will allow you to represent every possible css output.
…which it can’t do, obviously, and was never intended to do.
All I’m pointing out is that the expectation that it could might not be quite so daft when viewed from the lens of “I expected tailwind to be a framework in the same way sass is” or perhaps “the same way this framework that compiles using sass is”.
It’s like if I was using vue, and found that the template language can’t express complex logic without writing js (h() expressions) and not using the template language at all.
It’s wrong to say it’s a leaky abstraction; but it’s maybe not completely asinine to say, it a bit rubbish that you have to do that as soon as you hit any non trivial use case…
> Like most frameworks, it's not there to handle your niche and complex use-cases. It's there to provide bumpers that push you into a pit of success for common use cases.
…but as you say. Quite so. Im just saying I can see the frustration people encounter when they have the naive expectation that those edge cases are rare enough they’ll never hit them, and then immediately run into them.
I don't love Tailwind, but I can understand the spot it's trying to fit in, and I value the things it's trying to offer (locality, consistency, sane guidelines).
I think the sweet spot for that value proposition is projects where the designs don't need to be pixel perfect or extra fancy - they just need to work, quickly. I've used it successfully several times in those cases. Not to mention personal projects where just having a decent template made that I can tweak is great.
I would probably not use it anywhere you have real UI constraints or concerns, and you care a lot about specific animations or exact pixel placement. I tend to reach for styled-components in those spots these days. Since it gives me a fair share of the same value proposition (locality, consistency) but removes the guidelines/bumpers.
They play pretty nicely together (with some constraints), though - again, use the different lego blocks where they make sense. Stop trying to treat everything like a tailwind shaped nail you have to beat in with just that hammer.
You can play this "leaky abstraction" game with almost any concept, without the ability to reach down an abstraction level you lose flexibility. Its not a smell to be slightly leaky.
All abstractions are leaky; some are useful