[HN Gopher] CSS's problems are Tailwind's problems
___________________________________________________________________
CSS's problems are Tailwind's problems
Author : coltonv
Score : 105 points
Date : 2025-07-22 16:07 UTC (6 hours ago)
(HTM) web link (colton.dev)
(TXT) w3m dump (colton.dev)
| jackdh wrote:
| I used to be a naysayer of tailwind. However after getting
| practically forced into it I'm now drinking the koolaid. Yes
| things like having to duplicate styles using multi cursor is kind
| of silly, however for the vast majority of the time, having the
| styles written clearly each time, for me, makes it worth it.
|
| There is also nothing stopping you mixing and matching.
| pier25 wrote:
| > _There is also nothing stopping you mixing and matching._
|
| Yes, common sense. Having multiple approaches to solve the same
| thing tends to be a bad idea.
| hugeBirb wrote:
| This is an extremely limiting view. They are both CSS at the
| end of the day. If extracting the complicated inline
| TailwindCSS class to its own vanilla CSS class makes sense
| for readability then what's the harm? You could also just
| define your own variables. Tailwind gives you full control to
| do this.
| pier25 wrote:
| The harm will be in a complicated project where you might
| have to figure out where some styles are coming from.
| jackdh wrote:
| My point is that there is no one CSS library to rule them all
| and likely never will be. The closest to that is going back
| to pure raw CSS which I highly doubt people will do.
|
| And yes while it's obviously not ideal to have a hundred
| competing libraries in your code, you can create what works
| for you / your team.
| pier25 wrote:
| > _The closest to that is going back to pure raw CSS which
| I highly doubt people will do._
|
| Huh? Tons of people write vanilla CSS which is getting
| better every year.
| varbhat wrote:
| ...then goes on to promote "CSS-in-JS"
| Lammy wrote:
| Everything old is new again:
| https://www.w3.org/submissions/1996/1/WD-jsss-960822
| lenkite wrote:
| If you go even minimally outside the beaten path, the tailwind
| CSS declarations can mutate into a frankenstein monster that
| makes regular CSS look like a friendly, cute koala
|
| Example: https://www.nikolailehbr.ink/blog/realistic-button-
| design-cs... shows an "old fashioned", 90's are back-in-vogue, 3d
| button.
|
| Tailwind CSS for it becomes <button
| class="relative cursor-pointer overflow-hidden rounded-md border
| border-neutral-950 bg-neutral-900 px-3 py-1.5 text-neutral-100
| shadow-md inset-shadow-2xs inset-shadow-neutral-600 transition-
| all before:absolute before:inset-0 before:bg-linear-
| to-b before:from-white/20 before:to-transparent
| hover:bg-neutral-800 active:bg-neutral-950
| active:shadow-none active:inset-shadow-neutral-800">
| After </button>
|
| I got eye-strain and headaches after taking over maintenance of a
| tailwind based website where the original developer had left the
| team. The class declarations are so huge with 15-30 class names
| in one line that you always forget where you are. Incidentally,
| also the top-voted discussion:
| https://github.com/tailwindlabs/tailwindcss/discussions/7763
| micromacrofoot wrote:
| I can't believe people find even half of this acceptable, do
| they never use a browser inspector in their work?
| aidos wrote:
| I do, and it's great having the styles right there and
| hackable.
| recursive wrote:
| How can styles ever not be hackable? Inline styles always
| take precedence. What can ever stop you from slapping in
| more inline styles?
| ericwood wrote:
| To be fair, this is the case with any styling approach; if
| the style is applied to the element, it's there for you to
| toy with in the inspector.
| thaumasiotes wrote:
| Huh? You have the styles right there and hackable
| regardless of your tooling. That's what browser inspectors
| do.
| Alupis wrote:
| If you write enough CSS for a site... eventually you end up
| building utility classes anyway.
|
| Now, you re-invented Tailwind... but in your own proprietary
| way that nobody else understands.
|
| Tailwind takes the inverse approach. The example posted by
| the parent above is _completely unambiguous_ - what you see
| is what you get, and it 's done the same way everywhere
| Tailwind is used. You can read the component's styles and
| understand what it should look like without having to do a
| bunch of look-ups, or alter classes which might impact other
| areas.
|
| So now instead of memorizing a bunch of custom classes like
| `pad-left-20` (because you didn't discover the `leftp-20`
| your colleague added 8 months ago)... you now have a standard
| way.
| squidbeak wrote:
| There's a big difference between using utility classes for
| utilities and using utility classes for everything.
| 9dev wrote:
| And here we're on firm bike-shedding territory. Where
| does a utility stop being a utility and start being... a
| non-utility?
| H1Supreme wrote:
| It's less of when it becomes a "non-utility", and more
| that it becomes an incomprehensible mess of classes on a
| div.
| Alupis wrote:
| Honest question... why?
|
| Can you tell me, without looking at the implementation,
| what effect `btn-atc-primary` applies when the user
| hovers? No... you cannot.
|
| It's less important to have "clean" looking markup than
| it is to be unambiguous in intention and implementation.
| If you read a component that uses Tailwind classes, you
| know - without any doubt - what it does and what it looks
| like. That's pretty cool...
| micromacrofoot wrote:
| You can just write padding-left: 20px; and not memorize any
| additional layer? If you really love abstraction that much
| you can do padding: var(--pl20);
|
| Bonus is that you actually know how to use CSS
| antonio07c wrote:
| In your example you are creating a class for a single
| property which is what people are complaining about. I
| would create a .card class that contains the padding (and
| all needed styles) and probably use a --site-padding
| variable.
| zelphirkalt wrote:
| When I write CSS, I think in layers:
|
| (1) General CSS, global effect, like basic font size
|
| (2) semantic components on my pages, like a special kind of
| list or something, that I give a well thought out name.
| These CSS definitions are always scoped, obviously to ".my-
| class-name something" selectors. They cannot affect
| anything that is not inside a semantic component. It is
| very simple.
|
| (3) layouts/containers, that contain the components, like
| some flexbox or grid or something that behaves a certain
| way, which I also give a meaningful name
|
| (4) A theme, a CSS file that contains CSS variables, which
| have values used in the other layers. Often when I need to
| change something, I only need to change my theme.
|
| I do not understand, why web developers en mass are unable
| to cooperate with each other to develop their semantic
| units for CSS and then stick to those, instead of
| sprinkling stuff everywhere and using !important to make
| shoddy work. If they disagree about the semantic units,
| then that is the same problem as we have in any other
| software development arguing how to box things.
| Furthermore, the semantic units should be part of the
| design language of the business. The designer should
| realize "We have 3 kinds of buttons. Each has its own set
| of rules." and then what is easier than making 3 CSS
| classes? -- I am sorry, I do not understand where the
| difficulty is with just using CSS. Someone please, please
| explain to me, what is the problem in this day and age.
| mejutoco wrote:
| There was a time when not having css and html completely
| separate was considered sacrilege. And having html in
| javascript would have been a mortal sin.
|
| Eons ago I was at a job where we dynamically generated css on
| the server (php in that project). Anyone would have said:
| what about separation of concerns? Now everyone says it is
| best practice to have components with css, html and (gasp)
| Javascript all in one unit, because someone, for ex. Facebook
| said it (React). And the truth is it is very useful, and it
| is another way to structure frontend code.
|
| My point is: it is a spectrum and it can be useful to change
| the styling right there in the browser inspector. That works
| with tailwind the same as css. And with components, you can
| hide the repetition, although the browser will still have the
| repeated classes. Is this better than having css on another
| file with maybe some unused classes? I have done both and I
| can see each has pros and cons.
| vehemenz wrote:
| The thing is, they were never _really_ separate. The source
| files were separated, sure, but the way 90% of the world
| did CSS, there were hidden abstractions relating the class
| definitions in the .css file and the DOM structure in the
| .html that weren 't documented anywhere.
| tshaddox wrote:
| This Chrome extension is widely recommended when using atomic
| CSS:
|
| https://chromewebstore.google.com/detail/atomic-css-
| devtools...
| mohsen1 wrote:
| I used to be against Tailwind. Now that I've used long enough I
| can tell you that code is perfectly fine. I can read it and
| easily modify it. You can comment it out if you care
| <button class={cn( // layout &
| positioning "relative cursor-pointer overflow-
| hidden rounded-md", // border & background
| "border border-neutral-950 bg-neutral-900",
| // padding & text color "px-3 py-1.5 text-
| neutral-100", // shadows
| "shadow-md inset-shadow-2xs inset-shadow-neutral-600",
| // transition "transition-all",
| // background gradient positioning
| "before:absolute before:inset-0", //
| background gradient "bg-linear-to-b from-white/20
| to-transparent", // hover
| "hover:bg-neutral-800" // active
| "active:bg-neutral-950 active:shadow-none active:inset-shadow-
| neutral-800" // disabled
| "disabled:opacity-50 disabled:cursor-not-allowed"
| )} > After </button>
| cogman10 wrote:
| Reading though this, I really have to wonder how this is
| better than <button style="css
| blob">After</button>
|
| Why make a bunch of css classes when it looks to me like the
| "style" will be roughly the same amount of code and
| readability.
| chuckadams wrote:
| You can override classes, not so much inline css.
| cogman10 wrote:
| Is anyone ever going to override the "px-3" class?
|
| You can also change styles through javascript if you
| really want to.
|
| It just seems like we've lost the entire reason for css
| in the first place when every css attribute gets turned
| into it's own class.
| chuckadams wrote:
| Special cases in layout are a thing, happens a lot once
| you start nesting third-party widgets. So yes, there may
| be enough of a use-case for overriding px-3 that it
| wouldn't make sense to specifically omit it as a utility
| class -- to say nothing of it being useful as a utility
| class to begin with.
|
| I only sprinkle in the very occasional tailwind class via
| UnoCSS. I don't have the fire in me to dig trenches for
| either side of this battle that some people want to make
| all this into.
| mvdtnz wrote:
| > Is anyone ever going to override the "px-3" class?
|
| No, but they will change things like their constants
| ("bg-neutral" or, in this case, the spacing constant).
| wwweston wrote:
| You're correct in the sense that they're both big noisy
| blobs that dilute semantic/functional signals.
|
| You're neglecting the design system work that goes into
| tailwind classes. I don't particularly like its choices
| (and generally consider tailwind to be a minimal local
| maximum for a set of tradeoffs deserving of faint praise),
| but they're something, and in an engineering culture that
| won't adopt a better mindset or better tooling, it's
| something that solves a few problems well enough.
| dontlikeyoueith wrote:
| > generally consider tailwind to be a minimal local
| maximum
|
| I feel like I've been nerd sniped trying to figure out
| what you mean by this.
| wwweston wrote:
| Heh, fair, not a super clear phrase. What I'm trying to
| evoke is that tailwind has a few merits that do produce a
| local elevation on a few points of front end dev
| experience... but not much (and for some the tradeoffs
| cancel it out) and that more is possible.
| shkkmo wrote:
| It took a sec but I parsed "a minimal local maximum" as
| "from the set of all local maximums, this local maximum
| is near the bottom." Thus it is a local maximum, so any
| small change produces a worse result, but it is one of
| the worst local maximums you could have found.
| dontlikeyoueith wrote:
| > Thus it is a local maximum, so any small change
| produces a worse result
|
| I have ML engineer brain, so to me any small change from
| a local maximum is an IMPROVEMENT (because we try to
| minimize loss functions).
|
| Your reading makes more sense.
| nine_k wrote:
| It's the lowest hill in the range of CSS frameworks, it's
| not reaching the heights of proper semantic CSS, but the
| valleys of haphazard, unsystematic style attributes are
| an even lower point.
| vehemenz wrote:
| What do you mean by "proper" and "semantic?" The CSS spec
| never took much of an opinion on how classes should be
| organized or mapped to elements in the DOM. It's a
| technical standard. The way people used to write high-
| abstraction CSS was completely a cultural convention
| that, in hindsight, overstayed its welcome.
| douglee650 wrote:
| I am a convert, once you get the hang of the
| configurability it's very good (Tailwind 4). You don't have
| to go to separate files which is more streamlined, esp when
| doing in React.
|
| I like to format in logical chunks per line, for example
| here's a pretty complex grid setup that is easy to adjust
| in the template: ---- <section
| className=" w-full px-8 py-16
| md:px-16 "> <div className="
| grid gap-2 auto-
| rows-[minmax(0px,1fr)] grid-
| cols-[repeat(1,minmax(4rem,1fr))] grid-
| rows-[repeat(1,minmax(4rem,1fr))] md:grid-
| cols-[repeat(6,minmax(6rem,1fr))] md:grid-
| rows-[repeat(3,minmax(6rem,1fr))] xl:grid-
| cols-[repeat(8,minmax(6rem,1fr))] xl:grid-
| rows-[repeat(2,minmax(2rem,1fr))] justify-
| center "> ----
| danenania wrote:
| The real equivalent to that example would be something
| like: <RetroButton variant="primary" />
| dsego wrote:
| The style prop doesn't give you a design system, it's just
| raw values. Maybe you could use something like open props
| though.
|
| https://open-props.style/
| tshaddox wrote:
| The simple answer is that inline styles lack support for a
| bunch of basic stuff like pseudo-classes and media queries.
| I think the Tailwind team would tell you that they would
| love to have native web support for full-featured inline
| styles and that this would obviate many of the reasons to
| use Tailwind.
| hnthrow90348765 wrote:
| This is some "put the comma in front of the column name in
| SQL" logic
| chuckadams wrote:
| Some judicious use of @apply would go a long way. But for some
| reason a few years ago they were actively deprecating its use,
| favoring the above insanity instead. Now @apply seems to be
| back in good graces, but I guess not everyone got the updated
| memo.
| cheald wrote:
| @apply in CSS modules to compose the above sort of thing into
| something more semantic and readable without creating a bunch
| of global artifacts is definitely the way to go, IMO.
| crowcroft wrote:
| Is that more or less verbose than button {
| position: relative; cursor: pointer; overflow:
| hidden; border-radius: 0.375rem; border: 1px
| solid #0a0a0a; background-color: #171717;
| padding: 6px 12px; color: #f5f5f5; box-shadow:
| inset 0 1px #525252, 0 4px 6px -1px rgb(0 0 0 / 0.1),
| 0 2px 4px -2px rgb(0 0 0 / 0.1); transition: all 150ms
| cubic-bezier(0.4, 0, 0.2, 1); } button::before {
| content: ""; position: absolute; inset: 0;
| background: linear-gradient(to bottom, rgba(255, 255, 255,
| 0.2), transparent); } button:hover {
| background-color: #262626; } button:active {
| background-color: #0a0a0a; box-shadow: inset
| 0 1px #262626, 0 0 #0000; }
|
| Sure, separating the code into a CSS file means it's not in
| your HTML but that doesn't mean it doesn't exist. Similarly you
| can move the button out to a component and reference that if
| you want to hide the code.
|
| I find it easier to locate things in the HTML broken into
| components because the style is co located with the object
| being styled. I find it much more difficult to navigate through
| CSS and find out what classes are doing what exactly.
| Especially when a project grows over a long period of time and
| different people write CSS differently (and throw a few
| !important's in to make sure they can meet a deadline).
|
| Each to their own though.
| jakelazaroff wrote:
| It's not quite apples-to-apples because the Tailwind code is
| using design tokens and the CSS is not. You should (for
| example) replace the long `box-shadow` value with
| `var(--shadow-md)`.
|
| Anyway, to me this question is kind of like asking "Is it
| easier to break your writing into paragraphs, or write
| everything in one long block?"
|
| Like, what would you think if I formatted my comment like
| this?
|
| _> It 's not quite apples-to-apples because the Tailwind
| code is using design tokens and the CSS is not. You should
| (for example) replace the long `box-shadow` value with
| `var(--shadow-md)`. Anyway, to me this question is kind of
| like asking "Is it easier to break your writing into
| paragraphs, or write everything in one long block?" Like,
| what would you think if I formatted my comment like this?_
| pyman wrote:
| This isn't something a web developer should be doing in
| 2025. The styling should be generated by the software used
| to design the UI.
|
| Why aren't the companies building design tools solving
| this?
| mdhb wrote:
| I think you should find a new job.
| pyman wrote:
| XML developer
| micromacrofoot wrote:
| Adobe has been trying to build this product for 30 years
| and still haven't figured it out. Figma is trying and the
| best you can get is partially usable copy and paste CSS.
|
| This is a "why don't they just make self-driving cars"
| question. The answer is that there are too many edge
| cases.
| crowcroft wrote:
| Most people use Tailwind with components, and so when you
| talk about breaking things out into paragraphs, that would
| be the equivalent.
|
| Sure that html looks a bit messy, but once you write it
| once you're never looking at it again. In your view files
| you're just writing. <Button>Click
| Me!</Button>
|
| Or perhaps injecting variables etc. <Button
| color="red" style="outline">Click Me!</Button>
|
| I'm not really trying to argue that Tailwind is better or
| worse, I'm just saying it's a valid way to do things and
| there's nothing inherently wrong or flawed with it.
| nikkwong wrote:
| 100% this. People have all of these highfalutin arguments
| about tailwind being the wrong abstraction/non idiomatic etc.
| But, as someone who writes a lot of CSS--not having to jump
| back and forth between a CSS file and a HTML file is a game
| changer. CSS files are just another thing to maintain, and a
| painful one at that, since CSS is mostly organized relatively
| arbitrarily. This is why Tailwind won; reducing the surface
| that developers have to maintain is a big deal.
|
| There are simply so many decisions when choosing how to
| implement CSS in a project--where should we put the files,
| should they be component based or global, what preprocessor
| if any, etc etc. With Tailwind, you don't have to worry about
| any of that.
| pluto_modadic wrote:
| 1. highlighting
|
| 2. syntax checking
|
| 3. language servers.
| vehemenz wrote:
| There is also additional risk by overusing CSS's built-in
| selectors and inheritance, whereas there's zero risk with
| Tailwind.
| wg0 wrote:
| To each their own, the Tailwind version is more readable for
| me.
| 827a wrote:
| There's a lot of people, including oftentimes the tailwind
| dev(s?) themself, who view Tailwind as a replacement for both
| CSS and Components.
|
| I think this is an L take. Tailwind is a solid replacement for
| 99% of the CSS you'll have to write. Its not a replacement for
| components. It makes components better.
|
| Just wrap that monstrosity in a component; at that point I'm
| not sure why it matters. Have you ever looked at the component
| definition for an @mui/material button? Its a cthuluian
| insanity. The people who maintain that library likely need
| therapy every week just to remain functional humans. And, I
| thank them deeply for their service, because I so rarely have
| to look at those innards; they just work from the outside.
| roguecoder wrote:
| The power of CSS is that it can capture semantics. Tailwind
| gives up on all of that.
| zaphar wrote:
| What? Since when did CSS become about capturing semantics?
| That's what the Html elements are for. CSS is about the
| presentation.
| seanwilson wrote:
| I see buttons used as an example a lot but buttons are one of
| the most style heavy elements on many websites so it's not a
| good comparison imo.
|
| For a lot of pages, you're often only adding maybe 1 to 5
| styles to each element to change some flexbox settings, add
| some margin, set a background color, or change a font. With the
| traditional CSS approach, you're forced to come up with class
| names for each element and put the styling into a separate
| file, which makes iterating on style and layout really
| laborious compared to Tailwind.
|
| That's a much bigger benefit to focus on rather than looking at
| how (single element) buttons are styled. It's not like the CSS
| for styled buttons is pretty either.
| dminik wrote:
| I can't take this article seriously since the recommendation is
| to use CSS-in-JS. Perhaps the worst CSS related invention ever,
| easily surpassing tailwind in it's awfulness.
|
| Just use CSS modules. Just use CSS modules.
| coltonv wrote:
| I'd really appreciate reading the whole article before
| commenting like this. I point out the problems with CSS-in-JS
| and do not wholly endorse it, and I do recommend using simple
| CSS as a solid solution for many people.
| dminik wrote:
| I reread the conclusion. I apologize for jumping to
| conclusions so fast but ...
|
| You specify like 4 approaches:
|
| 1. Tailwind - apparently awful 2. Regular stylesheets - also
| not good 3. Inline Styles - some flaws 4. CSS-in-JS - minimal
| flaws when using vanilla-extract
|
| Reading through the article, my first thought was that you
| really like vanilla-extract. When I got to the conclusion
| section, and the first line is "I like vanilla-extract" I
| wrote the comment.
|
| Nonetheless, even after finishing that section, without
| knowing better, I would assume that vanilla-extract is what I
| should be looking at further.
| jakelazaroff wrote:
| vanilla-extract has zero runtime impact, right? I
| personally prefer using CSS modules (by a lot) but I don't
| see a huge difference between the two.
| coltonv wrote:
| I do think you should look at it further! It's a great
| library, though I can see why people won't like it for the
| reasons I mentioned in the article (i.e. having to build
| and enforce your own constants system). If you are going to
| use something like Tailwind, you're already okay with
| putting styles in Javascript and adding a bundler plugin,
| the two main "leaps" required to use something like
| vanilla-extract.
|
| Since the style sheets are extracted into CSS and do not
| contribute to JS bundle size, I'm not sure visceral CSS-in-
| JS reaction is justified when it comes to vanilla-extract.
| Tailwind is still basically CSS-in-JS, but more of a hybrid
| of CSS-in-JS and CSS-in-JSON. Could you elaborate on your
| frustrations with CSS-in-JS as it pertains to vanilla-
| extract, the one CSS-in-JS library I recommend?
| jakelazaroff wrote:
| This is subjective but the DX of writing CSS in JS object
| syntax is absolutely miserable. Here's an example from
| the website: export const myStyle =
| style({ display: 'flex', paddingTop:
| '3px' });
|
| I would much (much!) rather write normal CSS and have
| some build process extract the class name for me, like
| with CSS modules: https://github.com/css-modules/css-
| modules
| blain wrote:
| I'm sure many still like Tailwind but I never liked it, maybe
| because I worked with pure CSS or SCSS for many years before it.
|
| In the end its just another library that if you learn it well it
| will work for you and it has as many downsides as any other
| library ever used.
|
| By the way the article seems a bit like an advertising for
| vanilla-extract library.
| hugeBirb wrote:
| I don't understand the point of the rule sets and constant
| classes? TailwindCSS still obeys the same specificity rules of
| CSS so instead of `font-medium` on every <a> tag under nav why
| not just put `font-medium` on the parent <nav> tag?
| eithed wrote:
| I'd like to hear authors opinions about BEM
| ARandomerDude wrote:
| > Which class comes first in the generated stylesheet is not
| predictable. Tailwind's recommendation is to, once again, ignore
| basic coding principles and recommend you duplicate your business
| logic...
|
| Use tailwind-merge and never worry about this again. No
| affiliation, just a happy user.
|
| https://www.npmjs.com/package/tailwind-merge
| throwaway290 wrote:
| This describes nicely why I don't use it... I read tailwind docs
| year+ ago and didn't get what's really the point. You use a
| bundler anyway and so just use css modules...
| M4v3R wrote:
| I can't believe this article made it to the front page. It feels
| like the author has some personal vendetta and just doesn't care
| about the facts.
|
| > Tailwind decided to burst on to the scene and become the
| default styling solution for all modern web development despite
| taking each and every one of these problems, exacerbating them,
| and applying them to places that didn't have them before
|
| If Tailwind is so bad and has literally no upsides then how on
| earth it managed to take the frontend world like a storm? In
| authors eyes frontend developers have to be either stupid, or
| ignorant, or both if they decided to choose such a bad solution
| en masse.
|
| To me (and probably many others) using Tailwind is all about
| speed and reducing file hopping. If I ever need to adjust style
| of anything it's always trivial - just locate the component and
| adjust the classes. Writing new code is so much faster because I
| don't need to think about what classname to invent for every
| single html element I would like to style, I don't need to create
| separate definitions, files etc. for them. For my particular
| workflow it's a huge win.
|
| > If you misspell one of these plain strings your editor is not
| going to tell you. You'll just have to find out once you get into
| the browser. Did you notice that txt-blue is wrong, and it should
| actually be text-blue? No? Get used to it, you'll make that
| mistake daily (...)
|
| This is just plain wrong. You can install Tailwind autocomplete,
| checks or eslint rules in literally any editor/IDE of your choice
| and you will never have an issue of misspelling the classes. Most
| solutions will even autocomplete your custom classes defined in
| your Tailwind config.
| coltonv wrote:
| > If Tailwind is so bad and has literally no upsides then how
| on earth it managed to take the frontend world like a storm? In
| authors eyes frontend developers have to be either stupid, or
| ignorant, or both if they decided to choose such a bad solution
| en masse.
|
| Please read the entire article before commenting. I have an
| entire section on this. I don't think frontend devs are idiots
| and never said they were. Tailwind offers global constants
| configuration out of the box, which is the most important
| problem people are looking to solve, which is why I think such
| a flawed library has so much success.
|
| > To me (and probably many others) using Tailwind is all about
| speed and reducing file hopping. If I ever need to adjust style
| of anything it's always trivial - just locate the component and
| adjust the classes. Writing new code is so much faster because
| I don't need to think about what classname to invent for every
| single html element I would like to style, I don't need to
| create separate definitions, files etc. for them. For my
| particular workflow it's a huge win.
|
| Part of my point is that this already exists with inline
| styles. In react for example you can set up some plain JS
| constants and import them to do inline styles. And you get the
| benefits of type checking and other JS features. That's not a
| perfect solution either, and it's not one I'd endorse past
| hobby projects, but my point is that Tailwind just takes an
| existing pattern and makes it worse.
|
| > This is just plain wrong. You can install Tailwind
| autocomplete, checks or eslint rules in literally any
| editor/IDE of your choice and you will never have an issue of
| misspelling the classes. Most solutions will even autocomplete
| your custom classes defined in your Tailwind config.
|
| These are okay but trip over themselves and cause issues if you
| have any plain CSS class usage, which is necessary in certain
| situations in my experience.
| jwblackwell wrote:
| It works much better with AI though, which is really all that
| matters at this point
| recursive wrote:
| That's crazy. Coding without AI doesn't even matter anymore? I
| could understand saying it's not preferred by some. Or that
| it's sub-optimal. Or old-fashioned. But it doesn't matter at
| all?
| movedx01 wrote:
| Is that true though? Every time i tried to get Sonnet to write
| out any actually complicated layout/component, I ended up with
| a novel of classNames with a ton of duplication and useless
| additions. Those are very hard to spot inside a soup of
| tailwind classes, whereas I can see them immediately in a
| nicely laid out stylesheet. This happened extremely often when
| I tried to iterate with Cursor/CC on the given design, instead
| of giving up immediately after it failed to one-shot it.
| latchkey wrote:
| I recently started using it for a SPA I'm building and quickly
| realized, I don't care if it's the worst, or not. It works, and
| it works well.
|
| The best part? I can just tell AI what I want, and it spits out
| exactly what I want, even all the goofy framer-motion animations.
| If something's off, I can tweak it without ever opening a CSS
| file.
|
| Massive respect to the devs behind tailwind. I don't care what
| your blog post says, you'll have to pry it from my cold, dead
| hands.
| iambateman wrote:
| Tailwind was better for me before AI, and it's WAY better for me
| with AI.
|
| Claude can write CSS and HTML together in my templates, without
| needing to reference back and forth. It's very, very good at
| writing tailwind.
|
| Perhaps Tailwind is the worst of all your worlds, but it's better
| than Bootstrap and Bulma and all the other stuff I genuinely
| tried.
|
| I don't get why people can't just let Tailwind users be happy.
| Like, I'm not writing blog posts about how terrible it is to
| write HTML in JavaScript for React...I just don't use it. Live
| and let live!
| throwawaymaths wrote:
| yeah I was going to say this. AI is incredibly good at writing
| tailwind. Part of it is probably exactly the colocation issue.
| Context windows are precious.
| hombre_fatal wrote:
| Also, Tailwind is included in Claude's artifact/preview
| system and Claude is prompted to use it by default. Hard to
| beat that compared to "oops, pls implement it in Bootstrap"
| and then copying the output to JSFiddle with Bootstrap loaded
| just to see it. :(
|
| I don't use Tailwind but what usually happens is that it
| creates a great Tailwind mockup that I'm happy with, and then
| I tell it to port it to Bootstrap (which involves a mix of
| Bootstrap classes and custom CSS) and it always looks worse,
| heh.
|
| So Tailwind + LLM support is pretty big advantage.
| nicce wrote:
| AI was incredibly bad when Tailwind v4.0 was released. All
| the models trying force me to use the config file I did not
| want to and so on, every time.
| iambateman wrote:
| Use Context7 or another documentation MCP server for that.
|
| Then you can say "Tailwind4 has major changes, please
| review using context7" and it'll sort out some of that.
| anonzzzies wrote:
| At least claude code can just global.css without anything on a
| level that beats anything I see around. And if not, people give
| me tailwind prototypes, I paste it into CC and tell it I want
| that and get it in light, pure css without compile, small and
| fast.
| jakelazaroff wrote:
| I'm surprised that the official Tailwind docs recommend putting
| the `font-medium` class (i.e. `font-weight: medium` in CSS) on
| every child element of that <nav> and using multi-cursor editing
| to change them all simultaneously. `font-weight` is inherited,
| meaning that they could just add it once to the <nav> element.
|
| I dislike Tailwind and don't use it, but I wonder how many
| papercuts like this come down to just not knowing CSS very well.
| mootothemax wrote:
| Tailwind is magical to me for one reason alone:
|
| I can now design.
|
| As someone who spent 20+ years as a jack-of-all-trades / full-
| stack developer, specialising in back-end and database skills,
| this has largely been... confusing.
|
| Before, I couldn't even make plain text work. Totally hopeless, I
| didn't have the eye for things.
|
| _Now_ though, now I help my kids lay out their homework to be
| more visually pleasing. It 's bizarre.
|
| (caveats: while I can put together a visually pleasing and
| consistent websites, I'm not saying that design is easy, nor that
| designers don't have talents way above my own. I view this more
| like an enthusiastic amateur at the piano rather than having
| become a concert pianist.)
|
| I know of one other dev who's experienced the same. I'm keen to
| learn if there are more of us out there.
| kccqzy wrote:
| A decade ago Bootstrap helped a generation of programmers who
| don't know how to design make pleasantly looking websites. I
| fail to see how Tailwind is better suited to that task than
| Bootstrap.
| mootothemax wrote:
| yeah that's not what I'm saying
| 9dev wrote:
| With bootstrap, there was a fixed set of components to pick
| from. For a lot of things, there were no suitable components,
| so people used those that they had for everything else, kind
| of like designing furniture in Minecraft with blocks. This
| makes bootstrap interfaces bland and overly similar, in a way
| that Tailwind doesn't: its design system is fundamentally
| based around design tokens arranged in sensible steps, not
| full components. That allows for a lot more flexibility and
| stylistic control.
| dontlikeyoueith wrote:
| Because it's newer and trendy and that's important for
| programmers learning their first tool that solves an old
| problem.
|
| Whether it should be important is another question, but it's
| a simple fact that it is.
| _the_inflator wrote:
| I am very thankful for these insights.
|
| Is there any project using React that uses something other than
| Tailwind? It is the default for many projects, especially those
| that are new.
|
| Aesthetically, it was well deserved. There is a reason why
| component libraries build on top of Tailwind.
|
| But every time I touch the framework, I miss Bootstrap. Tailwind
| is an aesthetic masterpiece, but the code quality feels like a
| regression. BEM, Bootstrap, Material. Different beasts, even
| jQuery UI, but Tailwind would be something I might consider, not
| a masterpiece, judging by the code.
| hbn wrote:
| Been using Tailwind since starting my job 5 years ago where we
| have a ton of webapps standardized on Angular+Tailwind, and you
| may have to hop into a webapp you've never heard of before to fix
| a bug. Couldn't be happier with how much easier it is to build
| and maintain compared to traditional CSS.
|
| Many many words I've read trying to convince me why I shouldn't
| be having a good time using it, yet here I am more productive
| than ever thanks to it. Less experienced devs are by default
| funnelled into writing code that's easy to understand, only
| looking at one file, as opposed to people trying to do cute
| tricks where styles could be coming from anywhere in the project.
| It's SO much easier when the styles are on the component I'm
| looking at and I don't have to cross-reference between files.
| Plus people sticking to increments of 0.25rem instead of everyone
| using their own preferred units is huge.
|
| When you work at a big company you can't expect everyone will
| write nice CSS. But Tailwind plays a huge part in making sure
| everyone writes something that's much more easier for the next
| person who has to read it.
| vijivishali wrote:
| I echo this. For all the supposedly bad things it is, Tailwind
| provides a level of common denominator in a big team still
| making sure the CSS at the basic level is nice.
| yowzadave wrote:
| It doesn't even require a big team to be useful--I won't
| remember how I organized a set of styles a few months from
| now, and having Tailwind require a minimal set of
| constraints, and keeping the styles easily editable in the
| place you use them makes things more maintainable over time.
| sorcercode wrote:
| i appreciate the OP's take and insight but couldn't agree more
| with this comment.
|
| > yet here I am more productive than ever thanks to it. i have
| first hand experience with most of the css frameworks. heck,
| even wrote a custom scss one at one point, but eventually
| there's a simplicity (admittedly to a fault at times) to
| tailwind that just makes you more productive.
|
| > Plus people sticking to increments of 0.25rem ins this is
| another really good point that doesn't come through as much.
| Tailwind also does a fantastic job of picking the right
| defaults which 90% of the internet won't do.
|
| from the OP's original piece
|
| >> it demands the developer who installs it set up a config
| file that lays out all codebase-wide style constants: colors,
| margin sizes, fonts, border radii, etc.
|
| ... or importantly, it sets up a solid set of defaults.
| theSherwood wrote:
| The advantages of Tailwind are:
|
| - the styling is colocated with the markup - sensible defaults -
| avoids rule hierarchy/inheritance - minimal JS at runtime
|
| Disadvantages:
|
| - build step and configuration - dynamic styling complexity
|
| I don't think that's a bad tradeoff. And we're talking about
| styling on the web, here. So there are no _good_ solutions. But
| there is a _bad_ solution and it 's CSS-in-JS.
| freddydumont wrote:
| I have come to the same conclusion as the OP: people like
| tailwind not for its API or ergonomics but for its design system.
|
| Tailwind can actually be decent for templating systems and it's
| likely why it's shipped with Phoenix for example.
|
| But for React components, it's definitely a step back from CSS-
| in-JS, which gave you style encapsulation out of the box. Not
| sure what's up with the knee-jerk reaction against it in the
| comments. With vanilla-extract (mentioned in the OP) or PandaCSS,
| there is no runtime at all.
|
| Just components that defined their structure and style, in a
| readable way, with less abstraction than Tailwind.
| mejutoco wrote:
| I just use tailwind inside components. This problem is because
| of no components + tailwindcss, not because of tailwind usage
| alone. Nothing is stopping one from using components that use
| tailwind.
| directmusic wrote:
| Say what you want about Tailwind's usefulness, but the author's
| claim in the section titled "Rule sets" is objectively false. In
| the Tailwind documentation they mention the @apply directive
| which allows you to use Tailwind's styles in your primary
| stylesheet.
|
| Here is the portion of the documentation which talks about this:
| https://tailwindcss.com/docs/functions-and-directives#apply-...
|
| In my own project, I moved to Tailwind recently and found @apply
| to be very useful. I experiment with the inline styles and move
| them to a CSS class when (and if) needed. Additionally, the
| Tailwind CLI translates the states like hover: and active: as
| well. I personally have found it super convenient.
| ahuth wrote:
| Can't agree that Tailwind is popular because it forces you to
| setup a centralized config file (although I guess that is nice).
|
| It's because, as ugly as a long line of inline classes can be,
| it's easy to know exactly what styles are being applied to an
| element. Especially when there are more than 1 or 2 devs writing
| styles.
| roguecoder wrote:
| ... do people not know about browser developer tools?
|
| Unless a project has really messed up, it is trivial to see
| what styles are being applied to any element.
| ipsento606 wrote:
| I've been working on a nativewind [1] app for the last year or
| so, and all these complaints resonate with me, and then some.
|
| It feels like I have to have a mental model of CSS, tailwind,
| React Native stylesheets _and_ nativewind-specific conventions to
| actually accomplish anything. It 's terrible.
|
| I agree with the author that the only actually good part is
| having a single, easy-to-use list of global style constants.
|
| Everything else sucks.
|
| [1] https://www.nativewind.dev/
| rc_kas wrote:
| I love a good bit of dissent. Also I love Tailwind.
|
| > There are only two kinds of languages: the ones people complain
| about and the ones nobody uses.
|
| So yeah. Amen.
| jasonthorsness wrote:
| I've used Tailwind to style all of my sites. The author
| acknowledges but IMO doesn't give enough credit to the filters
| like dark:, lg:, hover:, etc. that let you concisely create very
| responsive designs.
|
| The latest Tailwind version lets you even style with data:
| attributes: https://tailwindcss.com/blog/tailwindcss-v3-2#data-
| attribute....
|
| Using Tailwind I get a world-class CSS expert (Adam Wathan)
| helping me out. The actual raw CSS doesn't go nearly as far in
| the DevX direction.
| CreepGin wrote:
| As someone who maintains multiple JS libs and provides support on
| Discord, the #1 reason I default to using TW is because it lets
| me drop code snippets in chat without lugging around an extra CSS
| file or walls of inline styles, keeping everything compact and
| easy to read (tons of vertical space saved).
|
| Example: https://onejs.com/docs/web/tailwind#quick-example
|
| Without TW, that snippet may need to take 3x more lines.
|
| ---
|
| My major issue with TW at the moment is that I use TW in a non-
| browser environment (Unity), so TW3 is fine since I can tweak
| everything with JavaScript. TW4 shifts everything to CSS, gives
| zero workarounds, and my setup crumbles.
| moron4hire wrote:
| In 5 years, Tailwind will be old and ugly and there will be a new
| hotness that everyone will crow "solves" styling, and everyone
| will argue about it and burn $$$ on reimplementing projects with
| it.
|
| And in 5 years, I'll still be doing CSS, not slowed down one bit.
| My old projects will still work. My new projects will get out the
| door on time and budget. And the new front-end devs who met me
| during a back-end discussion meeting will continue to assume I
| don't know anything about front- end and will still pressure me
| to switch. And my team will still be called in to clean up after
| them when they fail to deliver.
| maxmaio wrote:
| I use tailwind on all of my projects now and like it. I've used a
| lot of the css fads of the last decade (css in js was the worst
| which ironically is what the author recommends) and tailwind is
| the most ergonomic for me -and apparently most web devs
| considering how popular it is.
|
| "Did you really say bundler?" If you dont use a bundler this is a
| fair point. But I'm confident you do use one so adding tailwind
| is ~3 lines of code.
| coltonv wrote:
| I should have phrased this better. My point isn't to say that a
| bundler is a bad idea (I of course use bundlers on most
| projects at this point). My point is to say that a library that
| feels like it does so little still requires a bundler feels
| wrong.
| wuz wrote:
| Tailwind has taken the world by storm because it let's engineers
| completely ignore actually learning the technology that powers
| the web. That doesn't make it good - and it isn't. It's a bloated
| mess with tons of random technology surrounding the ecosystem in
| an attempt to make it usable.
|
| Tailwind literally only becomes usable for large scale
| applications once you have combined base tailwind, postcss, a
| number of tailwind plugins, custom themes, tailwind-variants,
| tailwind-merge, clsx/classnames, some custom written typescript
| typing tools, and a number of editor and linter plugins.
|
| People here saying "It works well with AI" is such a wild take
| for so many reasons, not least of which is just straight up
| admitting that you don't mind your code being unreadable garbage
| because you aren't reading it anyway.
|
| The `@apply` syntax glazing here is wild too - you're literally
| just writing CSS at that point. Just use vanilla CSS. Like that
| is all this is: ```css .select2-dropdown { @apply rounded-b-lg
| shadow-md; } .select2-search { @apply rounded border border-
| gray-300; } .select2-results__group { @apply text-lg font-bold
| text-gray-900; } ```
|
| The only "good" thing about tailwind is that right now the rest
| of the ecosystem is woefully lacking for a number of reasons and
| tailwind has the benefit of being used by a ton of random
| projects so you can find tools and references to make it better.
| But it's not good.
| roguecoder wrote:
| Web technologies succeed when they let people not have to
| understand things. React is the same as tailwind: it captures
| the box model experts already used to reason about web pages
| and made it literal.
|
| As long as the job of "web developer" is about assembly-line
| delivery of features, it will continue to be strategic to
| choose tools that are worse for experts and better for
| amateurs.
| dcre wrote:
| The idea that Tailwind prevents you from learning CSS has
| always been very silly because Tailwind _is_ CSS. You cannot
| learn Tailwind without learning a lot of CSS. The Tailwind docs
| are the most concise and practical CSS docs around.
| 827a wrote:
| My complaint with tailwind is that it doesn't do a good job of
| working well with components. E.g. if I have a component that
| wants to set a default background color for a button, but makes
| it customizable, I might think to do something like this?
| export function MyButton({ className }) { return
| <button className={clsx("bg-red-500", className)} /> }
| <MyButton className="bg-green-500" />
|
| But that doesn't really work, because ultimately we've just
| provided both the bg-red-500 and bg-green-500 classes, and we're
| leaving it up to the precedence rules in the browser CSS engine
| (which I'm sure are consistent, but that feels like a no thanks
| from me)
|
| So instead I end up doing something like:
| export function MyButton({ bg = "bg-red-500" }) {
| return <button className={bg} /> } <MyButton
| className="bg-green-500" />
|
| But that also feels unsatisfying, because while that prop is
| named 'bg' you could literally provide any tailwind class you
| want through it; there's no way to constrain it to only allow
| tailwind classes which are functionally interchangeable with bg-
| red-500.
|
| Anyone else run into this and have a nicer solution?
| jakelazaroff wrote:
| Yeah, use CSS variables. I wrote a TIL on doing this exact
| thing (customizing a button's background color from outside)
| with vanilla CSS: https://til.jakelazaroff.com/css/dynamically-
| change-styles-f...
|
| In Tailwind you could probably replicate this with custom
| variants or whatever they're called.
| wwweston wrote:
| This is a novel take that I think genuinely adds something to
| tired tailwind discourse:
|
| > I think the most important factor in Tailwind's success is that
| it does one thing very correctly: it demands the developer who
| installs it set up a config file that lays out all codebase-wide
| style constants: colors, margin sizes, fonts, border radii, etc.
| Writing individual styles that do not use a pre-configured
| constant from the config file is clunky in Tailwind. This is a
| good thing, an unironic win for Tailwind. More than anything
| else, this is what a large codebase with multiple frontend devs
| needs: a rigid set of global constants that everyone is strongly
| incentivized to use.
|
| I'm still considering its merits, but it at least goes beyond the
| "How I learned to stop worrying and embrace tailwind's
| standardized soup" vs "I can't stand this, it goes against every
| organizing principle I've found useful" familiar dichotomy.
| roguecoder wrote:
| It is also a great example of where worse is better, when it
| leads people to doing work they always needed to do.
| treyd wrote:
| But this isn't unique or new with Tailwind. SCSS and that
| family of tools had this 10 years ago.
| wwweston wrote:
| I think the SCSS and SASS implementations I used 5-10 years
| back had the capability but didn't _require_ any set
| variables, and I think one point of the argument is that this
| has more benefits than you'd think.
| hombre_fatal wrote:
| Since Tailwind looks obviously bad on first pass with all the
| class spam, I'm more curious to see someone steelman Tailwind.
|
| I have some ideas, like how the dead code elimination + granular
| but consistent classes lets you build novel components that are
| still consistent with your UI which might be essential for making
| a 3rd party component library work.
|
| I've been using Bootstrap since it came out 15 years ago but it
| never developed a 3rd party component library. I assume because
| it doesn't have the same sort granular building blocks for
| building novel components.
|
| Then again there are also component libraries like
| https://ui.mantine.dev/ that don't use Tailwind.
|
| I sadly never really looked into these modern options since when
| I want to build something, the last thing I want to do is dick
| around with a whole new UI solution vs Bootstrap muscle memory.
| moritzwarhier wrote:
| I think the best argument for Tailwind still is the blog post
| that the creator wrote to promote the idea (it was before the
| first alpha release iirc):
|
| https://adamwathan.me/css-utility-classes-and-separation-of-...
|
| Everything is a tradeoff. I don't miss Tailwind in my day job,
| but I would certainly if I had to work on the type of project
| where I last successfully used it.
| timr wrote:
| > I've been using Bootstrap since it came out 15 years ago but
| it never developed a 3rd party component library. I assume
| because it doesn't have the same sort granular building blocks
| for building novel components.
|
| Except, it does now. Presumably because of the popularity of
| Tailwind, Bootstrap has all of these inline utility classes,
| and LLMs absolutely _love_ to spam them across your code. It's
| really annoying when you have a stylesheet with a few dozen
| well-scoped lines, and the LLM just starts bashing inline
| styles everywhere.
| omnimus wrote:
| I think the tricky part is that Tailwind (and other functional
| css frameworks) are loved by 1. complete noobs who dont know
| css and 2. absolute killer css devs in agencies making content
| sites.
|
| Most devs on this website work on aplications in big teams
| maintaining projects for years where css is component scoped
| and there is time and there are quality checks.
|
| Now when you work in agency you come to a extremely visualy
| complex product website or magazine. You haven't seen the
| codebase for a year (or never) and you need to change little
| thing and add new section to homepage... all without breaking
| any other part of the website. And while you have 5 hours
| budget.
|
| In that context Tailwind is best middleground. It establishes
| system to follow and it is selfdocumenting. Everyone who can
| read tailwind instantly knows whats going on. And it is much
| better than inline styles because you can make it responsive
| and not get to specificity hell.
|
| People here bash funtional css thinking that those who like it
| don't understand css. I've worked both in agencies and on
| products and sorry writing css for a CRUD app forms is piece of
| cake compared to css for beautiful product site where every
| part is unique and you are required to have deep understanding
| of how browsers render so you can exploit that inverted
| position sticky so some ui cards align just right in performant
| way.
|
| What i am saying is there are many kinds of websites and people
| who like Tailwind might just be in very different situation and
| sometimes they might even know way more css than those who hate
| it.
| vehemenz wrote:
| > Since Tailwind looks obviously bad on first pass with all the
| class spam
|
| Why is "class spam" bad? Argument? Go read the CSS spec.
| There's nothing telling how developers/designers how they
| should abstract their classes.
|
| High abstraction classes are, I'm convinced, a holdover of the
| early days of the web when everyone thought XML and XSLT was
| going to take over the world.
|
| The great thing about functional CSS (especially Tailwind) is
| that I can see exactly which styles are being applied,
| immediately, anywhere I want in the DOM. I don't have to
| consult a separate stylesheet or refresh my browser. There's no
| context-switching and everything gets built 3-4x as fast.
| jollyllama wrote:
| Yeah, but, Tailwind has a standalone compiler that lets me avoid
| NPM, so I'll still use it every time.
| zhengkyl wrote:
| In regards to developer experience, UnoCSS https://unocss.dev/
| has a better implementation of tailwind for the JS ecosystem. It
| uses the build step so you can write code like
| hover:(bg-red-500 text-white font-bold)
|
| and it compiles to separate classes.
|
| It's very configurable for better or worse, and the VSCode
| extension is better too.
| jbreckmckye wrote:
| I'm a bit of a luddite with CSS. I learned BEM about five years
| ago and I've more or less always stuck to component scoped CSS
| files.
|
| Sometimes I use CSS-in-JS if a component system demands it, like
| Material. I don't mind it as much as others do, I like that
| there's no CSS concatenation weirdness. But otherwise I feel
| quite happy with a component file and a style file.
|
| For Tailwind fans (or even detractors), what's the main benefit
| I'm missing?
| omnimus wrote:
| In my case of many small long running projects with multiple
| people...
|
| 1. Speed - you can get stuff done quickly without making
| problems globally.
|
| 2. Self documenting - both in visibility of html but also
| because of system/config it forces. People understand to use
| only values (spacing, sizes, colors) in the config or document
| that they had to add something and why.
|
| 3. CSS specificity is not issue.
|
| 4. Performance - straight simple classes are very performant.
| Complex selectors and pseudo classes can be surprisingly taxing
| without people realizing it. Thats how functional css started
| btw
| jbreckmckye wrote:
| (not sure why I said "five years ago" - I learned BEM back in
| 2014)
| jrub wrote:
| I get the frustration, but I think Tailwind's biggest win is what
| it trades:
|
| structure and locality instead of style purity.
|
| Traditional CSS gives you basically nothing in terms of hierarchy
| or organization. You end up writing long, awkward selectors like
| .checkout .summary .item-title .price, which still aren't that
| readable. And if you're tracking down why there's 4px of padding
| instead of 6, good luck figuring out which of the five CSS files
| is messing with it.
|
| Tailwind flips that. Putting the styles right on the element
| means the structure is obvious. You don't have to context-switch
| or go hunting through a bunch of files just to see what's going
| on. It's all right there.
|
| Yeah, sometimes it gets verbose. Especially when you've got a div
| with 20+ classes. But when that happens, you've probably got
| something reusable anyway. And Tailwind actually shows you that.
| If you copy and paste the same set of classes to another element,
| you've just signaled that you're repeating yourself. That's your
| cue: take the extra 60 seconds and extract it into a component or
| class. With vanilla CSS, that signal is way more opaque. People
| end up not writing composable styles at all. Instead, they name
| every div, then name every element inside the div, just to avoid
| writing selectors like .component div h1 span--which is even
| harder to reason about than .component .title .icon.
|
| And honestly, writing Tailwind is just faster. Typing px-4 is way
| easier than padding: 0 4px;, and I don't have to stress over
| naming a class that won't collide with anything else. Naming
| things sucks. Tailwind helps you skip that whole mess and just
| build.
|
| Another bonus: Tailwind is easy to delete. You don't get tangled
| side effects or some random override breaking stuff in weird
| ways. Kill a class and you know exactly what changed because it's
| right there in the markup.
| blast wrote:
| "Tailwind is the Worst of All Worlds"
|
| "it does one thing very correctly"
|
| ... so there's at least one worse world then
| exiguus wrote:
| I agree. You can also use Tailwind in CSS modules or in SASS, or
| create your own CSS helper classes. There are many tools
| available that merge and allow conditional CSS classes.
| Basically, you can use the same tools as in vanilla CSS to
| organize your code.
|
| If you use any component library, most of your CSS should be
| within the component library, not in your application. Components
| can have variants, such as primary and secondary buttons, for
| example. This adheres to the DRY principle. Your application can
| also have reusable components, which helps minimize the use of
| CSS and HTML. This adheres also to DRY. You can also build your
| own Component-Library.
|
| You can apply the same programming principles and organizational
| patterns to HTML and CSS as you would to any other code. This
| becomes much easier if you separate the view from the rest of the
| application.
| tptacek wrote:
| Early in the article, the claims is made that Tailwind has
| "become the default styling solution for all modern web
| development despite taking each and every one of these problems,
| exacerbating them, and applying them to places that didn't have
| them before". Later, the case is made that this happened because
| Tailwind offers a single configuration file. How true does this
| sound? How little credit does it give to the huge number of
| front-end teams that have adopted it?
| aeonfr wrote:
| The whole block about performance is just... not correct?
| Tailwind, and atomic CSS libraries, scale better, not worse! Look
| at how facebook leverages atomic CSS to reduce CSS by 80%
| https://devmohit.medium.com/facebook-generating-atomic-css-t...
|
| Even if we consider small codebases, the examples OP shows seem
| to ignore Zip compression and how it works, which is ironic for
| someone who is arguing about performance as if it could be
| measured only in bundle size...
| gizzlon wrote:
| I would not expect compression to help performance in the
| browser??
|
| Bytes transferred, sure, but that's not what OP is talking
| about
| bonthron wrote:
| I like utility classes, but not tailwind. It's predecessor,
| Tachyons is small, simple, and all I've ever needed.
| https://github.com/tachyons-css/tachyons/
| etchalon wrote:
| Tailwind's problems can be summed up as "There are a lot of
| people who don't want to learn CSS, and even more who don't want
| to learn how to maintain it well."
| jmuguy wrote:
| It would be helpful to link to the Tailwind section about
| duplication https://tailwindcss.com/docs/styling-with-utility-
| classes#us...
|
| As someone that used Tailwind for years at this point, you're
| right about why its so popular. To me it was just a better
| version of Bootstrap. Its defaults look nice, its color choices
| are nice. I would also mention that their docs are top notch and
| Tailwind UI makes it really to just copy and paste some decent
| looking basic components.
|
| As someone that spends most of their time on backend, I just
| don't really care that much about CSS. I think that's something
| that's lost with all the bikeshedding about it to me its similar
| to higher level language vs something closer to the metal. So
| when people say "just use CSS" its like someone telling me I
| should write in C rather than Ruby. No thanks, I don't have to -
| why should I?
| darepublic wrote:
| Setting up the tooling around tailwind is more a pita than
| vanilla CSS imo. If you are using tailwind just for the nice
| default styles there are already myriad simpler solutions for
| that. Comparing the use of vanilla CSS to.. writing in C, I
| don't get it.
| darepublic wrote:
| Just goes to show how many noxious weeds grow in the JavaScript
| garden. And how they have fanatical adherents whose careers are
| based on trying to get square wheels to roll. Even without AI
| this was a bubble waiting to burst
| shmolyneaux wrote:
| I don't really do much in the web ecosystem, but I'm surprised
| how many people have a strong dislike for tailwind. I've had a
| lot of success using it.
|
| I'm really suspicious about the performance concerns brought up
| in the article. Does the author think that long strings are
| really such a huge issue for the size of the JS bundle or
| processing time in the browser?
|
| From my experience it's much easier to refactor the styling of a
| page using tailwind than modifying CSS. Needing to name a bunch
| of classes in HTML to reference in CSS adds a lot of obfuscation
| and it can be difficult to come up with those names. When the
| structure of the HTML changes the CSS inevitably breaks. I find
| that it's easier to keep the styling working when using tailwind.
|
| I think that the value of keeping styling DRY is overblown. The
| author gives an example of some tabs that all use `font-medium`
| and how bad it is to need to modify all the uses at once. This
| seems like a non-issue to me. If you see the web page you would
| immediately see the issue if you forgot to change anything.
| Alternatively, you can still use `@apply` and classes if you
| don't want to repeat yourself. Even further you probably want to
| create reusable components anyways.
|
| Tailwind is very easy to debug. I've never had an issue
| understanding why styling wasn't working when using it. In CSS I
| found that getting the styling right was a constant struggle.
|
| The author mentions the issue of setting the text to red and blue
| in the same class attribute. He compared it to using `!important`
| in CSS, which is so far from the truth. You can immediately see
| the issue if the color isn't what you want. Inspecting the
| element in the browser would immediately show you that you set
| the text to multiple colors.
|
| Tailwind solves a bunch of problems for me. Components are more
| self-contained. The class names are much easier to remember that
| the underlying CSS. The set of attributes you can use are focused
| to a small set of usable features. Animations are much easier.
| Responsive designs are easier to create. Flexbox (the most useful
| part of CSS) is easier to use. I work with a number of older
| developers (very smart folks that just haven't done web
| development) and I have a much much easier time getting them
| proficient with tailwind than CSS.
|
| I strongly believe that tailwind is better for individuals,
| better for teams, better for beginners, easier to set up, and
| easier to maintain. If you're already a CSS expert or if you have
| an existing design system I can imagine that you wouldn't want to
| pick up tailwind. But for most websites and most teams I expect
| tailwind is a great option.
| vehemenz wrote:
| > Tailwind does nothing to reduce the mental load on your
| developers to understand, read, and write in your codebase. In
| fact it does the opposite. Your developers are not spared the
| hassle of learning CSS by instead learning tailwind's
| abstractions. Developers have to understand not just that
| background-color is the CSS key to set a background color, but
| they also must understand that classes prefixed with bg- mean
| background color. Every feature of CSS, such as media and
| container queries, will need to be learned twice, CSS style and
| Tailwind style.
|
| Just wrong. The whole point of 1:1 style:class mappings is that
| you don't have hidden structures relating the DOM to your
| stylesheet's class abstractions.
|
| If you're going to talk overhead, talk about all the abstractions
| and hidden structures you have to learn in a codebase written in
| the "correct" way to do CSS. It's just incomparable.
|
| Tailwind's class names are trivial to learn for anyone that
| already understands CSS. It's minimal overhead compared to
| learning CSS. "Learning it twice" is completely inaccurate.
| Francute wrote:
| But you can achieve the same thing (1:1 style:class mappings
| without hidden structures) using other libraries, like the ones
| mentioned here; styled components and vanilla-extract. You can
| even achieve that natively with web components.
|
| So, I truly agree with this blog post, and I even wanted to
| rant the same things showing that you should not compare
| tailwind against classic CSS stylesheets from 2010, but against
| how different solutions looks like using different tools the
| community seems to have thrown away or forgot.
|
| And I know is not relevant to your comment, but I will add that
| "but you will have to maintain more files instead of just a
| single HTML file" is not a valid argument for me. If that were
| something good, then just put everything into a single giant
| server.<your_language> file + separated lib dependencies.
|
| We want maintainable easy to follow and understand files.
| Having a clean html with no cluttering + intuitive CSS styles
| being applied where we expect them and looking exactly as we
| expect them while reading the html, is the big win for me, and
| Tailwind definitely does a step back on this, especially when
| other tools can achieve that. (Lastly, we have set multiple
| projects with different tools, and the amount of "wtf"s we've
| seen with tailwind is way higher than just styled components to
| give one example)
|
| I agree that the only good thing Tailwind achieves, is setting
| a default convention on having a single config file where you
| can set everything that you will need on every design across
| all your html files
| p4bl0 wrote:
| I _never_ liked Tailwind. The point of CSS was to separate
| content and presentation. Tailwind not only goes backward on that
| but does it a lot worse than HTML did before, because the
| presentation not only is mixed with HTML but is also just a long
| random string rather than structured into HTML attributes. It 's
| just like CSS using only style="" attributes, only with a
| different, almost proprietary syntax that you have to learn on
| addition to actual web standards.
| gherkinnn wrote:
| Oh why can't this idea go away. That might or might not have
| been the idea, but it does not scale beyond a text document. It
| so does not.
|
| If it did, we wouldn't have 15 years of Sass and Less and
| Stylus and CSS Modules and Styled Components and BEM and SMACSS
| and Tailwind. I have been through it all and Tailwind is the
| easy winner both for productivity and maintenance over 5 years.
|
| I sort my cutlery by knife/fork/spoon, not handles and
| implements.
| jumploops wrote:
| I hated Tailwind when I first used it.
|
| > (Tailwind) demands the developer who installs it set up a
| config file that lays out all codebase-wide style constants
|
| > I believe this is where Tailwind has succeeded and other
| libraries have struggled.
|
| This isn't why Tailwind has "succeeded," in my experience.
|
| Until Sonnet 3.5, LLMs were pretty awful at creating any sort of
| UI with normal CSS, but were partially usable with Tailwind due
| to the colocation of styles with elements. Even with Sonnet 3.5+,
| Tailwind seems to perform better than other CSS solutions (though
| the gap is getting smaller with each new model release).
|
| The author calls this out, but with the wrong conclusion:
|
| > Lastly, Tailwind has also been buoyed by being by being the
| default styling that just about any LLM or vibe coding tool will
| produce [..] Plenty of developers started using jQuery because
| the first StackOverflow result in their search explained how to
| solve that problem with jQuery.
|
| Maybe the reason jQuery was so popular wasn't due to
| recommendations on StackOverflow, but it's prevalence on
| StackOverflow was due how easy it was to adopt?
|
| Tailwind has "succeeded" for the same reasons it's excelled with
| LLMs:
|
| - colocation of styles with elements
|
| - decent defaults (i.e. bg-sky-600, font-bold)
|
| - simple solutions to common challenges: -
| responsive design (lg:flex-row) - dark mode
| (dark:text-white) - conditional state (hover:bg-
| red-600 focus:outline-violet-500
|
| Obviously, Tailwind, just like other CSS-in-JS solutions has it's
| problems/limits, but it's easy enough to fall back to normal CSS
| for these one-off solutions.
|
| I now use Tailwind everyday, and it's no longer the worst thing
| in the world.
| huksley wrote:
| Tailwind is great for layouts. For configurable components, not
| sure. I also dislike the mess with colors.
|
| Cursor IDE uses those navy-100, red-100 absolute colors, instead
| of using text-destructive, etc (for light/dark mode support), and
| it is also difficult to tell it does otherwise. So I need to fix
| this manually, and it is quite time-consuming.
___________________________________________________________________
(page generated 2025-07-22 23:02 UTC)