I just use Vanilla Extract (with their Sprinkles API) and call it a day, it uses TypeScript as the preprocessor language and then compiles it to raw CSS, similar to SCSS but without writing SCSS.
I just use Vanilla Extract (with their Sprinkles API) and call it a day, it uses TypeScript as the preprocessor language and then compiles it to raw CSS, similar to SCSS but without writing SCSS.
I don’t think tailwind is perfect but coming into a well-established codebase I am so much happier to see tailwind. I can’t think of a single issue I’ve encountered with tailwind in this context.
You can certainly write good, maintainable CSS and I’m sure tools like Vanilla Extract make it easier but to say tailwind is worse is just wrong (in my experience, anyway).
But in the days of components, Tailwind simply is worse to me from a maintainability perspective than just having scoped CSS. It is at best equal to CSS classes because inevitably the pattern used is with @apply or making a space separated string of all the Tailwind classes in JS in order to add that as a variable to whatever div you needed to. Which is, well, CSS classes reinvented.
The only problem with tailwind is it goes super overboard with the idea. You want to use probably 30% of tailwind and use their naming convention. But once people start to write some long on demand single classes its always better just name a class and use CSS.
I think its because the authors need to be seem they are making updates all the time and can't accept that it's pretty much finished project. They also don't want to accept that utility classes are not solution to everything and good old CSS still has lots of use.
If you have a design system, Tailwind.config can be used to both extend and limit the classes. Notably, we cut all tailwind colors out and only define theme colors. We also define all sizing, shadows, and text styles around our design system. This constrains your design down to only “legal” values. This doesn’t mean every design will be magically right, but it separates the possibility of non-standard values out at the very least and has actually caught bad mocks as well.
I think, to me, tailwind isn’t done and I need one thing: let me group classes with modifiers.
I want xl:[text-bold p-4] instead of xl:text-bold xl:p-4
Ultimately I don’t think tailwind is perfect at all…but no CSS framework is. In fact, I think part of the reason it is a hit is because mixing custom components with both custom css AND bootstrap is a mess as well in the real world. At least Tailwind has a single source of truth.
Your example xl:[text-bold p-4] is performance anti-pattern. Don't forget that main reason utility classes came to be was performance. It's fastest to put class directly on element and you end up with very small css file because you don't repeat. When you start to do xl:[text-bold p-4] you will end eventually write xl:[text-bold p-4 pb-2] or even xl:[p-4 text-bold]. Now you lost one of the main advantages of utility classes and end up in more confusing world than pure css.
Yes you can make utility classes for typography styles..that’s entirely the point of extending the framework, they are extremely clear that you should even. None of this precludes the idea that it is configurable to the point of making it a better solution for one’s needs.
Personally the vanilla extract example looks like literal boilerplate hell for any sort of actually complex application. It might make complete sense if the whole thing was based on a declarative template where the objects also define elements but here it is just SCSS done elsewhere.
The reason why people like Tailwind at build time is that it removes a step of defining classes out of the flow and puts all your styles in one place. That is the innovation: mental, not technical. I have a pet theory that Tailwind is more preferred by those with ADHD as it completely removes a mental blocker element.
Additionally, CSS Modules is not a replacement for TailwindCSS. TailwindCSS ships and strongly promotes the use of design tokens. It is harder to NOT use design tokens in TailwindCSS.
Because of this, there is no CSS Modules v. TailwindCSS. It is CSS Modules + X v. TailwindCSS. Where in the worst case "X" is just a stand-in for "everybody does whatever" which produces horrendous unmaintainable stylesheets whether they are global or not.
In the first example of vanilla extract, it uses exact px measurements which already demonstrates it’s not geared to solve one of the primary selling points of tailwind (using config as a constraint to reduce mental overhead when building things).
> I’ve found what you said to be completely untrue unless you’re totally lazy.
Ah yes, the laziness argument. Let's not blame our tools but ourselves for the tools are always good and righteous. If only those darn C programmers weren't so lazy writing their memory leaks.
Once you know the syntax of Tailwind you can jump into any codebase and instantly know what’s going on. With “standard” CSS you’re forever jumping between components and class definitions.
Only if you already have no clue what CSS is. If you know CSS and can’t figure out what a given tailwind class does, then I don’t know if anyone can help you.
That said, I do often feel that I might as well just write the css directly. Writing tailwind feels like another translation layer.
I've never fully committed to TailwindCSS, but I have tried out my own utility classes on a smaller scale, and I found myself having to parse the entirety of the code to figure out what was going on.
My preference now is a mix of utility classes for super basic things that would be tedious to set a class on, and custom classes for everything else. Especially if media queries are involved, because good lord is that ever tedious to do with utility classes. If I find myself setting more than 2-3 utility classes on an element, I usually end up moving that to a CSS class for one reason or another. I don't define the utility classes until I need them, and I really don't use very many.
.reset {
display: inline;
appearance: none;
font: inherit;
border: none;
border-radius: 0;
margin: 0;
padding: 0;
color: inherit;
background: none;
list-style: none;
text-align: inherit;
user-select: inherit;
}
This is defined first in my CSS index file, so that any other classes will override it.(Note that there's probably a better way of writing this rule. This is just something that evolved organically.)
The problem is, everybody already knows Bash. Tailwind? Not so much.
Highly doubt it.
> at the cost of readability.
You mean the readability of "p-2 bg-red-500 text-lg font-medium" or "i-dont-remember-what-this-class-does"?
I'd argue the readability in Tailwind is better. Tailwind is highly indicative of what it does and doesn't waste time when it comes to consistency.
The only real argument is that it adds extra length to the class attribute, but then again, it doesn't cause issues like finding the same class in 50 different CSS files or not having any auto-completion.
No, I'm pretty sure he means the readability of "absolute bottom-0 text-sm md:text-base text-white leading-relaxed tracking-tighter transition-all duration-300 ease-in-out m-3 md:m-4 px-6 md:px-8 py-4 md:py-6 opacity-0 w-full", as opposed to a single well-named class such as "image-caption".
If long class names aren't your thing, then sure, use CSS, but I'd rather save time and have understandable code than maintain those CSS classes like "image-caption".
Well, I don't appreciate the snarky comment, quite honestly. But okay, I'll assume you have had more experience than me, and you've managed things I haven't, have a good day.
> I'd rather save time and have understandable code than maintain those CSS classes like "image-caption".
Sorry, but the snarkiness was in your comment first, and when you said you didn't want to maintain those classes, that's exactly what it sounded like to me, that, well, you didn't want to maintain said code. If you had a different point I'd be happy to hear it.
> I've often found that people who are in the frontend don't properly learn CSS and just hack it together. That was me too for a long while which is why I hated it. Then I started learning it from first principles and it makes a lot of sense. Now I can build whatever I need in plain CSS classes.
So sometimes people just... misunderstand or use the tool wrong?
CSS is definitely a write-only language. I've yet to see anyone understand CSS in a large system and refactor it. You end up with dozens and hundreds one-off classes and overrides everywhere.
Worse.
With Tailwind you have a consistent set of classes scoped usually per component. Thos p-x, m-x, and others don't change from component to component or from project to project.
Hell if I know what `.chip-text__content` is, how it's different from `.icon-button__content`, why it interferes with my CSS, and what other 15 CSS classes I need on top of that to make it work.
How are you going to maintain consistent values across components such as spacing colors etc? Those tend to grow to the size of Tailwind
Every design system I've come across contains any combination of:
- rigid inflexible components that need complex overrides even for the simplest cases
- multiple classes with seemingly innocuous names like "col col-8" that get increasingly obtuse and one-off like "uxg-menu-header uxg-avatar-hero-block uxg-avatar" [1] or "fas fa-fw fa-bell pf-c-alert pf-m-info pf-c-alert__title" [2]
- multiple often contradicting css variables (esp. colors)
- ... i'm missing something else, but it's late here and my brain doesn't work ...
[1] Design system by some new age finance company: https://design.fusionfabric.cloud/components/app-bar?tab=dev
[2] Opensource design system by RedHat https://www.patternfly.org/v4/components/alert/html
I've been writing CSS since 1997 and tried every fad technique that's come along. Tailwind is the first one that didn't make me dread dealing with CSS.
Of course you can build big things with semantic CSS. You also can with Tailwind.
Some people like Tailwind and find it incredibly helpful.
Some people don't.
Some people actively despise Tailwind.
No one has to 'win'. All these opinions can coexist.
Even in this thread there are people doing so: https://news.ycombinator.com/item?id=34921960
I understand perfectly well why people like Tailwind. The problem is not initial productivity; indeed, I can write bash scripts too very quickly that make me feel infinitely productive. It's what comes afterwards, the maintenance, the teasing of code written, that Tailwind makes so difficult.
And sure, use what you want, but I won't use it.
The maintenance is what makes Tailwind awesome. I've written CSS professionally since Internet Explorer 6 and have gone through many different strategies for writing maintainable CSS (BEM, OOCSS, SCSS and multiple different CSS-in-JS methods) but Tailwind is the first time I actually feel relieved of all the issues. To me, it's such an enormous improvement from normal CSS that people arguing against it feels like someone trying to convince me not to use syntax highlighting.
That's what CSS is, a HUGE inheritance graph, just even more convoluted, because absolutely every "class" is part of the same graph.
Yes, being able to copypaste self-contained HTML with all styling included and no depedencies is amazing.
Your copy pasting analogy makes no sense because "syntax highlighting" was referring to you trying to convince me to stop using something I can't live without and had nothing to do with Tailwind. Anyway, nothing wrong with copy pasting code and avoid premature abstractions until they are needed. Being religious about DRY and trying to shoehorn subsequent iterations of similar code into an inflexible abstraction leads to unmaintainable monstrosities.
Eh, when the heading prominently mentions TailwindCSS, I’d say the topic is very much about that choice. If it were a minor implementation detail, it would be different.
This is exactly the situation Tailwind prevents.
Unless your team has incredible discipline, CSS across a large system very often becomes a tangled mess where you can’t change one thing without unintentionally affecting another.
When you change the Tailwind classes on an element, you know there’s no risk of subtly breaking something somewhere else.
Don’t conflate “visually busy” with “unmaintainable”.
Web apps, not as much.