Serious question: is there a need to reach for tailwind if you are building a new site? Won't using vanilla CSS while taking advantage of the latest features be pretty good, since humans are not manually making edits (which removes many of the pain points of maintaining CSS), while simplifying dependency and the build pipeline?
In my experience, if you're going to aggressively componentize whatever you're building (i.e. a button isn't a css class on a simple `a` tag but a distinct component that exists in it's own file somewhere) there's huge advantages to having your styling be associated directly with your components, and Tailwind is a great option (among many) for that.
If you're building something where your unit of organization looks more like a "page" than super fine grained elements, Tailwind will just make things messy and a higher-level library or writing your own CSS would be a better approach.
I don't think this changes much with AI - right now most models are not terrific at maintaining a huge degree of context in larger projects, so I could absolutely see an agent implementing CSS that works well in isolation but breaks due to the cascade. Maybe that changes in the future, but right now if anything I think Tailwind is well suited to AI because it enforces a certain locality to the changes you're making (i.e. you can reasonably assume that a `text-red-500` class on an element isn't going to break things elsewhere and wll do what it says on the box).
Why are your buttons `a` tags?!?
Buttons should be `button` tags. Links should be `a` tags.
It's common to want things that look like buttons that functionally link to a page.
This isn't really straightforward with the HTML `button` tag so `a` tags that appear like buttons are common. I'm not really proposing something out of the ordinary here, nearly every high level component library that has a built in "button" will support applying them to `a` tags and most likely have that as their primary example of a button.
Reading charitably, when writing that part of the comment they probably were thinking of links that look like buttons, for example the "Get started" link in Tailwind's home page.
Regardless of how that specific one looks like, I wouldn't like if it were replaced by a <button>.
Yeah, Tailwind is great as long as you have some way to reuse markup, like React. You don't have to care about class names and whether CSS defined somewhere else affects styles of a current component at all. That last point makes sense for LLMs as well: all the styles that affect the current file are automatically in context since styling is local. Admittedly, there are other ways to achieve this but the ergonomics of Tailwind are just good. Having nice defaults and good training data is an added bonus.
The lack of single-file components is one of several reasons I wouldn't reach for React prior to the LLM craze[0]. For personal projects, I love Svelte. You wouldn't need tailwind there for the reasons proposed given their support for it.
[0] Things have probably changed, but Svelte 5 was a litmus test for how recent the data cutoff was for an LLM model. Meanwhile React _especially_ has no reason to change how the framework is used by coders. Thus there's years of scraped tutorials and sites for how to throttle a function or what-have-you in React.
IMO, Tailwind is just inline CSS with standardised defaults. I think it found its place because most React devs didn't want to bother with CSS
It found its place because working on CSS on any non-trivial scale with multiple engineers is painful. The best way to deal with CSS at scale is not to write CSS. And this comes from me who really likes CSS.
CSS was prob great for early web but now it's just a pig with lipstick on
CSS is one of my favourite things to do and still is. However, most engineers don't really understand it because most engineers don't really bother learning anything, and as a result you typically end up with a mess.
If someone knows what they are doing and is allowed to make a decent UI library, you can have very clean, efficient styling without libs.
Oh why can't this idea die, it has been continuously debunked for 6 years now. So much so, any TW discussion will reiterate it.
Why would it die? How would it die? The vast majority of Tailwind is literally just shorthand for individual CSS properties.
Because what makes it useful , like media queries, can't be put in style attributes. Frankly this whole discussion is just as silly as claiming flex has nothing over table layout.
flex is not a collection of aliases for <td>s and <tr>s
Then again one should aim to not even need media queries and make things responsive intrinsically, breakpoint-free, continuously. A design where things jump at hard coded viewport widths is not actually a great design.
So at least that part is not so amazing.
This is certainly one of the arguments of all time. Thank you, HN.
>inb4 my 1:1 naive mapping of DB to screen works for me
>inb4 the web should be reserved for text documents and hyperlinks and user styles rule and running anything close to applications on the web was a mistake
>inb4 TUI
Never stop posting, you are doing great.
bro your own website has hard coded viewport widths where things jump
If you were so kind to point out, where I used media queries to hardcode viewport width ... "bro".
Oh ya? Is that why the parent prefaced that obvious and indisputable fact with "IMO"?
> Oh why can't this idea die
People like to feel superior to others, so dunking on people using a popular technology tickles some pleasure centers. Considering another viewpoint gets in the way of that, so other viewpoints are ignored.
It's inline CSS, but with all the limitations of inline styles removed. There is a lot of stuff that can't be done with inline styles, like media queries.
It's inline styles, not online stylesheets. Though yes, inline styles are limited.
It was/is inline styles, not inline CSS. It isn't a stylesheet at all, just a single style property.
It is used because UI component frameworks make vanilla CSS an awkward an unnecessary tool (the Cascading part). CSS makes sense as designed for styling a document, but not so much for styling atomic components. If we were designing the web and CSS from scratch around the React model, CSS would not be made to cascade, because that is totally unnecessary and usually leads to more issues than it solves. Apart from theme variables, in a component system there's no reason to have global CSS anywhere; you'd just style each component in isolation. So when in the React model you typically want no cascades at all, the library that is made for that gets popular.
CSS modules are also a solution to the above, but, once you get rid of cascading, and you have one stylesheet per component, it is again unnecessary to have the one stylesheet in a different file from the one component. There's no benefit to splitting a component and its styles into two files; it just makes it more annoying to edit. So we move the styles essentially inline, with either Tailwind or CSS-in-JS.
Thanks for this great explanation of your viewpoint. As an occasional frontend dev who really got into Tailwind, it was always hard for me to explain why I'm so much more productive in Tailwind than in writing CSS. This makes a lot of sense.
That, plus it looks like Forth code
[dead]
I think it is mostly backend dev who don't want to spend time in frontend stuff.
Real answer was always no.
Tailwind is just conceptually bunch of css inline styles repackaged as classes for performance boost. It was always just shifting complexity around, but offered an immediate perception of productivity gain, because you could just make a quick edit here and there.
LLMs seem to work well with tailwind which I assume is because there was a lot of tailwind in the training data. As a human I never found tailwind to be particularly easy to work with anyway (mostly because I can't be bothered to learn another CSS framework) so I was constantly checking the docs when manually writing code. But I do like the rigidity it forces, which is probably a good thing for AI coding as well.
I feel it's better for LLMs. For each class name, the LLM doesn't have to go out and consume CSS files and read all the cascading rules and determine what other classes elsewhere might have an effect. It has everything it needs to determine the styling and layout right in its immediate context
I don't really get this argument. 90% of Tailwind is shorthand for existing CSS properties. There's really not much to learn if you already know CSS.
Except for all those specific shorthands?
I used it for months at s previous job and spent a lot of time googling “how do I write X CSS property in Tailwind”
I’m not sure what to tell you. With only a few exceptions, the shorthand follows a very predictable pattern if you already know the property names. IDE completions help too.
I only do front-end dev occasionally, but these are my 3 goto articles that make me lean towards not using Tailwind:
1: https://www.zolkos.com/2025/12/03/vanilla-css-is-all-you-nee...
2: https://www.joshwcomeau.com/css/subgrid/
3: https://railsdesigner.com/custom-elements/ (more Rails specific)
It's my primary role. I started using jsxstyle a dozen years ago alongside React and really liked the ability to style my components in situ without breaking browser architecture assumptions.
I recently had to help out on a vibe coded project that inherited Tailwind (I think from Figma). It was a short assignment so I didn't dig that deep, but I don't understand the value prop of Tailwind. There was no obvious improvement over what I've been used to; in fact, it seemed a lot messier.
A lot of the time the choice comes down to abundance of resources and community support. So if we're comparing tools (e.g. jsxstyle vs tailwind) maybe Tailwind could actually win on those parameters (no actual idea, just guessing based on the number of stars jsxstyle has on Github), but if we're comparing vanilla to [any tool] then vanilla usually takes the cake.
I often feel like I'm the only person using jsxstyle, which is wild since it was done by Pete Hunt, same guy who spun React out of Instagram.
If I was using React, I'd probably like this tool too. The best counter to "community supported" is "so conceptually simple and small that it doesn't need a community". But perhaps that's kind why I'm not big on React in general.
I’m a full time front end dev, and I’ve basically accepted at this point that some people are really into tailwind, and some people are not. I’m not, and for a while I strongly preferred working with other devs who were also not… but at this point, LLMs have completely erased that distinction.
What's "funny" is that newer/modern CSS is often very clunky to write in Tailwind, or unsupported entirely unless you build your own selectors, but AI doesn't understand those well or how broad their support is, so getting AI to write good/modern CSS outside of Tailwind is pretty difficult. I suppose someone could make a new library that is for AI tools that focuses on the latest and greatest in CSS, but there's no market for it any more because AI would just steal it and generate UIs with it.
Yeah this is my main beef with Tailwind. There are lots of modern CSS features that are really nice that you have to hack into Tailwind because they don’t really fit into a utility model.
(Any complex grid model for example. If you haven’t used grid template areas try them out! They are by far my favorite way to do complex responsive layouts)
Vanilla CSS can take advantage of features like that "cascading" part that Tailwind goes entirely against.
If you are styling a site, there's no competition at all. But if you are styling a single interaction-heavy page, it's a lot less work to put all the formatting inline instead of thinking about a descriptive structure and write your CSS around it.
Apparently a lot of people design entire sites one page at a time.
I started with a UI framework thinking I'd need it but over time I realized that I was using it exclusively for button theming and setting the default font. I was using vanilla CSS and vanilla JavaScript and after removing the framework my package sizes reflect that fact.
I used to use tailwind a lot, but AI has made it redundant largely. There's zero reason to add any library into your stack unless it has significant advantages, tailwinds advantage was largely a developer convenience, and that's not really needed anymore. You can now maintain a design system in CSS really easily and ensure your UI conforms to it using AI tools in a way that seems way more powerful than before.
Not at all, I personally never used nor plan to.
I am a big advocate of classes, not inline styles spaghetti.
The only contact I had with it was due to FE teams jumping into it, however every couple of months is something else anyway.
Believe me, I try all the time. But HTML and CSS are not made for the modern web.
Styling radio buttons, working date inputs, forms that POST automatically, typeahead and server-side validation (eg username already taken.)
You spend all your time reinventing the wheel and then it's buggy and looks like a dog. To say nothing of the inevitable poly fills and Cross-Browser issues.
How does this relate to Tailwind though?
Tailwind does ultimately compile down to CSS. Anything you can do in Tailwind can be done in CSS.
I have not run into cross-browser differences in a long time. That is differences, that actually mattered and for which I would have had to build any workaround. I have built several websites recently, using vanilla HTML and CSS and solved everything using server-side rendering.
What problems specifically do you see with server-side rendering?
From a security perspective I greatly prefer a client-server approach: you have an unsafe frontend where you care about ergonomy and aesthetics, and a backend which provides an API which handles the security.
Two different worlds and often two different kinds of developpers
I think we actually don't disagree there, but we have a different understanding of the term "server-side". Anything related to security must happen on the server since safety measures in scripts running client-side can be defeated.
SSR (Server Side Rendering) provides the browser with a page that is created on the server (and possibly enhanced/hydrated on the client).
Having a separate backed and frontend allows for separation of duties: the client is responsible for the user-facing content and the backend deals exclusively with data flows. This allows to have several independent clients, machine to machine connections etc.
Whatever arrives to the server is untrusted, and the API (or other interfaces) only verify raw data (a JSON for instance) and there are excellent (backend) frameworks for that.
Mixing the visual content with the data is possible (Django does that for instance) but from a security perspective less efficient (again - separation of duties). It also requires to possible double the work to have an independent API.
In other words, if you separate the two you do not care about security on the front at all, and the one who builds the back can focus on their expertise.
How does tailwind solve this vs. vanilla CSS?
This is a good discussion: do LLMs change the calculus for DRY?
A major point of components is having a single place where you can change design and behavior across your entire codebase. With LLMs you can with very good accuracy tell them to change the look of "all buttons that are confirmation buttons in modals but not in the login modal". Doesn't matter if there are 10 such buttons or 1000, it'll take a few seconds for them to accomplish it.
I'm slowly forming the opinion that nowadays having copy-and-pasted "components", with their whole HTML just repeated over and over, is now a much less worrying thing in a codebase. Even a bloated CSS can be quickly fixed by a LLM.
And like you said: you eliminate the build phase entirely and frontend development ergonomics goes back to how it was in the early 2000s.
So you enjoy reviewing your entire code base and relying on an extremely detailed regression suite just to make simple changes? I don't think AI changes good engineering at all, it just changes who or what is doing it.
It definitely changes some aspects of good engineering.
I'm not a huge AI person but it's obvious a host of great tools we've built to deal with our challenges would not have been significant if we had LLMs.
A very crude example: to translate code into a different language someone would need to write a tokenizer, a parser, an AST and finally a translator. All significant engineering challenges, taking days to finish. Nowadays you can tell an LLM to do that in minutes.
Staying on topic: we could easily argue that CSS wouldn't have existed if LLMs existed and could create table layouts from pasted images in a chat window.
I disagree about your last statement. That only covers the initial creation/generation phase. It ignores the engineering aspect of maintaining that design through the entire lifecycle of the product. How do you evolve that table design?
Sure an LLM can update every table in your project every time you make a change, just as a human could. It also can make mistakes and burn significantly more tokens doing so. Or, it could update one component with a one line change and be done. Easy to verify, less change for mistakes.
Engineering is a discipline and does not change dramatically with the advent of outsourcing it to agents.
> to translate code into a different language someone would need to write a tokenizer, a parser, an AST and finally a translator. All significant engineering challenges, taking days to finish. Nowadays you can tell an LLM to do that in minutes.
Do people do that on a regular basis? The most recurring case of building the above is when someone wants to include a language into a project and they usually don't bother with a translator. The second case is when transpilling (ex. LESS to CSS) and that's more akin to macro and other preprocessing tricks than a full blown translation.
> we could easily argue that CSS wouldn't have existed if LLMs existed and could create table layouts from pasted images in a chat window.
All current UI and Document conceptual models include styles (either as direct properties or separate models) and some does include named styles. The novel aspect of CSS is the Cascading concept, not the styling part. And cascading is obvious when we consider that there was supposed to be user stylesheets for documents. I read epub and user stylesheets (created from UI) is crucial.
> Do people do that on a regular basis?
They can now.
https://www.checklyhq.com/blog/agentic-rewrite-nodejs-to-go/
Frontend development in the early days was nightmare. I don't know why people pretend there was some kind of golden age but there really was not.
You could still develop frontend in the old way. Most browsers are very good at supporting old websites. But on one wants that.
Nowadays though, that old way is working very well, because of all the things that were added to HTML and CSS, making things, which used to be annoying or difficult mostly easy.
LLMs change the calculus on DRY in some cases. I would say it's still very much a no-no on the frontend side of things. Code repetition is directly correlated with bad loading performance. When you're optimising for people on slow mobile connections, your HTML/JS/CSS being 500KB instead of 1.5MB matters a lot.
That only matters in context: if this repetition allows you to forego React and a zillion JS libraries you’re better off in the end performance wise.
I have never seen a single website where performance downgrade was caused by HTML.
However I’m not advocating for it, just making the case that it’s very hard to do worse than we’re currently doing with front end development.
> do LLMs change the calculus for DRY?
Yes it makes it insanely easy to refactor duplicated logic into shared and tested modules. Why would you go the other way?
Components as in React, Vue, etc requires a complete overhaul in frontend rendering, many dependencies, changes in deployment and even have an impact in organizational structure.
If one wants to do server side rendering with HTML templates like the old days there is no real “components” way of doing it (although declarative Shadow DOM is coming along). Partials are not the same thing.
In that scenario some repetition can give you the benefit of keeping a clean stack with no client side rendering.
Have you tried Astro? It lets you do exactly that: server-side rendering with HTML templates in component form, with css scoped to the component. No shadow dom needed, no JS frameworks either.
[dead]
There's never been a need to reach for tailwind. It's really a matter of preference.
Yes. Good design and a developer with good taste can make your site so much better than something mechanically excellent, but tasteless or derivative.
Writing CSS in a way that will scale up with the size of your project and team is just as hard as it's ever been, you still have to come up with a convention for doing that, including taking into account what newer features bring to the table. Having to manually edit it was never the pain point.
Short answer: no, not necessary. Long answer: https://mastrojs.github.io/blog/2025-11-27-why-not-just-use-...
Personally I still find it really helpful to have a proven framework to rely on so that I can be confident I'll have a reasonably consistent looking UI across a range of browsers, browser versions, screen sizes, and OS even versions.
Bootstrap was/is popular for the same reason. One framework and your site looks decent on almost any device. The downside is a bit like LLM work in that it all ends up looking like a Bootstrap site unless you’re a good designer.
I like vanilla CSS, but agents in my experience seem to deliver more uniform results when using tailwind.
Imo no
CSS is really good these days. Scope rules and the new selectors available mean you actually have to work hard to mess things up like you did in previous eras
is there a need to reach for compiled languages if you are building a new program? Won't using vanilla assembly while taking advantage of the latest instructions be pretty good, since humans are not manually making edits (which removes many of the pain points of maintaining assembly), while simplifying dependency and the build pipeline?
(Abstractions are still very useful to LLMs)
I believe if react had made inline styling of components less verbose then tailwind wouldn't exist
Yeah I think if React had adopted Vue’s scoped model early on then CSS Tailwind would be much less popular
(I much prefer the scoped CSS model)
As someone that hates Tailwind, I think there is actually a use case here. If you are fluent in CSS reaching for Tailwind is probably a mistake. But for better or for worse there are lots of developers who can write HTML and JavaScript (or more likely React) who will not, and do not want to, learn CSS, for them things like Tailwind is a godsent.
I do think Tailwind is overused, but it obviously has some legitimate use case.
There’s been a lot of devs reaching for StyleX over Tailwind recently. Not sure if hype or there’s real advantages.
Tailwind is still considerably easier to work with than vanilla CSS. You just have to write less.
It still helps deduplicate.
Only if you are using a framework like React, where you create generic Button and other components.
Try using Tailwind with server-side rendered frameworks like Rails or vanilla HTML, and you will find yourself repeating the same stuff over and over again. Basically anytime you want e.g. a <button>, you have to repeat all the inline css for it. (There are plugins for Rails that adds "components", but I found it very clunky)
Not really. Every single button that gets rendered has thirty class names attached to it instead of one. It really bloats markup with duplicated classes.
Don't do a lot of technical work nowadays, but tailwind is still my go-to. Vanilla CSS just doesn't have nice ergonomics.
With AI I guess you could skip it, but I like to understand the code.
What do you mean by vanilla CSS?
I can't be the only one who has no idea what this means. Do you mean high-abstraction classes that are bound to the DOM arbitrarily, and are difficult to change later? We've had 25+ years to see how that doesn't scale.
Do you mean Tailwind-style functional CSS written by hand? What would be the point of that?
Without tailwind LLMs tend to use inline random colors, random sizes and radiuses. Project becomes an unmaintainable design soup really fast. Even with tailwind first priority is to define dark/light theme with semantic colors. After it's a smooth sail (sort of, routing, forms, state ownership and persistent url state are still an alien concept for clankers).
My clanker made my vanilla css with branding color variables. shrug.
Did your clanker reach 40k CLOC?
A few of my teams use tailwind. As someone who used css directly for years, this just means I have to waste time looking up the tailwind equivalent of things I know (if I’m not vibecoding). Strongly dislike it for that. But css management is really bad without it too. If I knew all the tailwindisms, it would probably be a clear winner.
If it's the case that there's almost never the need to reach for it, and I do find myself in that camp, then a harder question is begged, why is it so popular?
I think there's a lot of technologies that are in the category of categoric mistakes to use, but popular enough and inert enough that they don't get dropped. There might be lots of different explanations depending on the technology, a lot have a reason the moment they are released.
Many third party tech becomes de facto standard at some era, then those features get incorporated into more mainstream tooling like browser css, and at that point the third party tooling exists only because of inertia and adds little value, but increasing supply chain and complexity risk.
Another example on this category is Axios which was essentially a cleaner DX for XMLHTTPRequests in client side javascript before Fetch, and later a polyfill for it. Nowadays it's a blunder to include it, but it ended up in stackoverflow answers and training sets, so it's "safe" to include. Developers that are on the bleeding edge drop it, but those that are catching up and reading tutorials or classes from the previous era, or using llms, use the previous era cutting edge technique, because they aren't evaluating all the parameters of a choice, they are just going with whatever someone else is using, which causes a coalescing around certain central technologies like React, Kafka, Redis.
Regarding Redis, my understanding is that it was popular during one era where databases were used to store state because we didn't know any better and people were moving fast and breaking things, so it was developed as a sort of hack to move things from a database into memory. But nowadays people just use it wherever (because it really is the most blank microservice you can think of, you can slap it anywhere), and people implement it off the bat.
There's lots of more specific reasons why bad third party deps persist. In python there's a library called python-dotenv, which is a categorical mistake to include, but people do it because they come from Node where it is a standard practice. But there's the standard nuance that in Node, it is a built in, but in python it is a third party dependency from a random dev (no offense to the dep dev, only to the users of the dep). It literally is replaceable by calling Open(), write(), and close(), but there it is with a lot of downloads waiting for the day it is targetted and hacked to capture millions of .env files. Personally to me it would be strike 1 of 2 if someone imports it, but there you go.
Yes, there's no reason to import tailwind, it adds nothing, the idea of:
red-color { color: red}
big-text { font-size: 14px}
<p class="red-color big-text"></p>
Is as laughably low quality, the application of a technique in form but not substance, similar to Getters and setters in Java, effectively making every property of a class public, but formally implementing the private keyword and access through functions. 100% a categoric mistake to implement.
I've written elsewhere of a phenomenon where devs avoid lerning a base technology, and rather end up learning a tech on a higher abstraction that ends up being a 1-for-1 of the lower tech, but it gave them the hope that they could avoid doing that learning, and they only drop into that realization by piecemeal ala "we did it not because it was easy, but because we thought it would be easy", and the only cost is that they learned the non-portable version of that technology and now they are vendor-locked professionally into that technology so they will spread it to the next repo, company, job posting and so on.
There's analogues in biology of inert viruses or parasites that don't materially cause damages, but their lifecycle depends on the host. Although to some extent, by competing for resources they always cause SOME damage, but it is important to notice that not all viruses or damages are highly damaging, that's a rare situation of very extreme pathogens, it isn't very beneficial to kill or damage your host. In fact many may be commensal, but there is a tendency to harm.
In conclusion, I think tailwind and such pre-ai slop-deps are more popular because they are inert viral parasites rather than because they provide value.
I tend to agree. Software development history is a long saga of things that are bad and still popular. Think of how popular J2EE, XML, and SOAP were at some point, and they're just miserable to use or maintain.
[dead]
there's never a need to reach for tailwind, it's just a pathology some people like because someone else did the design work for them
I think the second half of your statement disagrees with the first.
Much like saying, "there's never a need for Scratch, it's just a way for my kids to code fun things without worrying about semicolons."
That's true about Scratch so what's the problem? You don't need to use Scratch if you learn the syntax of whatever language you desire to use.
Tailwind is a design library for people who don't want to learn or write CSS. They don't technically need it.
Why insult the millions of users relying on Tailwind?
What's the insult? Tailwind is specifically for people who don't like writing CSS because it avoids various ways CSS works and comes with predefined styles.
"Pathology"
it's objectively a pathological use of CSS because it circumvents the C (cascade)
More discussion should be had if the cascade is even beneficial in the first place.
It's ironic because standard software development practices advocate isolation.
I quite like Tailwind. I've had great experiences with it, especially on projects where the skill level of contributors was highly variable.
That said, Tailwind is not as powerful as plain old CSS. It's a bit like training wheels for CSS—you gain some guardrails and prevent newbies from messing things up too badly, but you also give up the power modern CSS affords you.
E.g. I invite you to look at some of Ahmed Shadeed's (https://ishadeed.com) layout tutorials, or whatever you find on the CSS-Tricks/Masters.dev homepage today. It's bonkers what you can do with modern CSS!
Tailwind gives you access some of what's possible with CSS today, and they keep adding support for new features, but it's impossible to express everything CSS is capable of using only utility classes. At some point, you need to write some actual real CSS code.
So personally, it's a tradeoff for me. If I really want the full power of CSS, I use plain old CSS. If I'm willing to trade power for the convenience of Tailwind's built-in design tokens and guardrails, then I pick Tailwind.
Both approaches are good and valid. The right choice is context dependent. With And with LLMs in the mix, it's not that hard to port a Tailwind codebase to plain CSS, or vice versa, so picking the wrong thing doesn't have as high a cost as it used to.