Skip to content(if available)orjump to list(if available)

Tailwind CSS v4.0

Tailwind CSS v4.0

295 comments

·January 23, 2025

jaredcwhite

As a once-strident critic of Tailwind for its many failings and incompatibilities with the state of the actually-modern "vanilla" web art, I am very pleased to see the huge strides they've made with v4. Being able to access the Tailwind theme through native CSS variables (they even have an example in the docs of a button component written in native CSS in an external stylesheet using native variables! Oh happy day!) is absolutely massive, and being able to use a CSS-only config is equally amazing. Finally, Tailwind feels more like it's a utility (ironic, since its claim to fame is utility classes!) which you can add to any project, rather than some bizarro "viral" framework that wants to eat sensible architectures and lives in its own JavaScript-y silo.

Perhaps all the criticism over the years actually had an effect. Or maybe they finally arrived at good conclusions on their own. Either way, I suspect many of the pro/anti-Tailwind arguments are no longer relevant, and that's a Very Good Thing. Now we can get down to business and ship product.

sibeliuss

I'm still a critic in terms of actually using it, but what I find amazing about tailwind is how amenable it is to AI-generated workflows. It seriously works _so good_. Anything can be expressed, and systematically. There's something amazingly useful there.

esperent

> what I find amazing about tailwind is how amenable it is to AI-generated workflows

It's highly amenable to human workflows as well. Of course, humans are more disparate than AIs so it doesn't suit all humans - no tool can. But it sure does seem like a majority of humans web developers like it.

ebiester

So, I wonder how AI is going to work with the new upgrade. Are teams going to delay upgrading until there is proper Claude support, for example?

thangngoc89

Should work well since there aren’t any removal of old features and classes.

bythreads

Its horrible, annoying and gets in the way

tipiirai

> I suspect many of the pro/anti-Tailwind arguments are no longer relevant

I feel there are two issues with Tailwind for me as a designer / design engineer.

* First, JavaScript/Tailwind engineers have hijacked the conversation on design. Instead of "utility-first," "dead code elimination," and "type-safe CSS" I focus more on desing systems. Whether to use Perfect Fifth or Perfect Fourth in typography for example.

* Second, Tailwind makes it impossible for me to participate in the actual craft. Design decisions get buried in React components with cryptic expressions like `flex items-center shadow-lg p-6 hover:bg-gray-50 dark:bg-gray-800 py-[calc(theme(spacing[2.5])-1px)]`. This might make sense for JavaScript engineers, but blocks/makes it hard for systematic design. Instead of expressing precise mathematical relationships through CSS, we're essentially writing inline styles with better ergonomics.

Foreignborn

Tailwind has solved a lot of problems. And this is coming from someone who doesn't use it half the time.

Some thoughts about this topic, not necessarily in disagreement:

- Designers seldom think in the way you describe (explicit computer-readable rules, systems of design). A lot of designers are coming from crafts that are more implicit. It doesn't surprise me design business logic is not the topic of conversation.

- You need to update your tailwind classes to reflect your design business logic. Don't do "bg-gray", do "on-surface-emphasis" or whatever business logic. This is just a simple config change.

- You probably brought up modular scale as just one example, but modular type has become near myopic dogma of frontend engineers who haven't had any typesetting experience. A scale of 1.25 vs 1.5 is so in the weeds as to be useless. There are so many alternative ways to set type (e.g. take lessons from CJK typesetting) or innovate typography on the web (e.g. build your own leading-trim implementation!).

tipiirai

I'm a designer, so I absolutely think in terms of design systems where typography is just one part of the puzzle. There are, of course, many ways to set type — but the point was: no Tailwind engineer talks about typographic scales in the first place. Systematic thinking is absent, which is naturally built in CSS.

skydhash

Maybe Tailwind is useful for bigger projects, but I tend to prefer component based class instead. The biggest DX for CSS is using the web inspector and directly modifying the DOM, then copying the adjusted values to the text editor. For a much serious project, I go with the balsamiq -> figma route to create an actual design system.

tambourine_man

You can allow the inspector to access the filesystem and modify the files without having to copy/paste for even better DX.

lenkite

Man their very playground at https://play.tailwindcss.com/ gives this unreadable crap (sorry for swearing) for the very first `div` on the first line:

    relative grid min-h-screen grid-cols-[1fr_2.5rem_auto_2.5rem_1fr] grid-rows-[1fr_1px_auto_1px_1fr] bg-white [--pattern-fg:var(--color-gray-950)]/5 dark:bg-gray-950 dark:[--pattern-fg:var(--color-white)]/10

How can anyone prefer this gobbledygook over a nice CSS class declaration with line-separated standard CSS properties ? How can one even maintain this ?

Maybe the modern generation of web developers have IQ 200 and 20/20 vision with eidetic memory and I should just put myself to pasture.

thiht

Because your not thinking of styles practically. You don't review style declarations, you review the rendered page/component. You see with your eyes that a component has the wrong border color, and AFTER THAT you go to your component code, find the border color declaration (if any), and update it/add it. Sometimes you'll even inspect the element in browser, and find the faulty class directly, making it even easier to target in code.

The Tailwind classes are "unreadable crap", that's true, but it's not a problem because you don't "read" it, no one does. You roughly parse it and edit it.

orf

Terrible take.

Take a guess at what “dark:bg-gray-950”, “bg-white” or “min-h-screen” means. You get them from context.

Imagine if you put a little bit of effort into learning Tailwind. You’d get the more complex declarations as well.

As to why it’s better than a class declaration, a lot has been written about using atomic, composable utility classes over reams of “write-once” class declarations.

d1sxeyes

No one cares what your typography ratio is if you can’t get it in front of a user quickly enough (dead code elimination), reliably enough (type safe), or cost effectively enough (i.e. if you have to pay for more developer time to implement the same work).

Tailwind is a tool for craftspeople, not artists. It democratises design by making it simpler. For folks that are really good designers, they should be happy that they can up their prices knowing that customers are paying for their expert eye, rather than just the basics again and again.

threatofrain

Tailwind does not democratize design. Tailwind is generally 1:1 to CSS, sometimes 1:2 or 1:3. It's such a thin layer over CSS that you have to remember all the CSS. That does not make design easy or hard. You don't give people Tailwind and end up with design as beautiful as ShadCN, even though ShadCN in some perspective is just another wave of stereotypical startup design. The ability to go from blank button to beautiful Tailwind button is all on the author, not the fact that you're writing in a new lightweight inline syntax.

When I read the Tailwind book, my takeaway was their design philosophy was about the speed of iteration and how that interacts with designs whose parameters are too interdependent. Tailwind follows that philosophy by encouraging ad-hoc repeated edits over DRY. In that sense StyleX also fits the Tailwind philosophy very well even though StyleX is an even thinner layer over CSS.

tipiirai

> Type safe typography ratio

Please explain how this is better than expressing typographic scales with CSS variables and calc()?

null

[deleted]

4m1rk

I just want the color palette of the Tailwind CSS.

arielcostas

Their palette is really neat. I always check it out when I need colour inspiration, especially for "cold greys" and other "state" colours (green for success, red for error, yellow for warning...).

jgalt212

Yes, someone should make a tailwind inspired bootstrap theme.

gedy

I actually did this for a former company that had a Bootstrap-based app - the designers started bugging that "we need to use Tailwind", and I couldn't figure out why they cared what tech we used.

In talking with them, realized they just were bored with our theme, ha. Not publicly accessible though, sorry. I should probably recreate this.

agos

yeah, the palette is neat. My main gripe with Tailwind is that it blends a set of design tokens (which I like) with a technology to apply them (which I don't like)

xigoi

Maybe check out Open Props?

https://open-props.style/

dbbk

Just copy and paste them out?

Spone

Radix Colors ?

4m1rk

I don't want to use React

vim-guru

CSS has become significantly more user-friendly than in the past, with most browsers now behaving consistently. It's worth learning as there is no build step involved, and it avoids cluttering your markup with excessive code.

You could opt to use style attributes directly within your HTML. Historically, we avoided this to maintain a separation of concerns, but it's puzzling why some prefer reintroducing similar methods. Is it just to save a few keystrokes? Using style attributes even seems more straightforward since it doesn't require translating code in your head.

I simply don't see the appeal.

morbicer

There's a bunch of things you can't do with style attributes, just to pick a few:

- Pseudo-classes (e.g., :hover, :focus)

- Pseudo-elements (e.g., ::before, ::after)

- Media queries

- Keyframes and animations

And the DX in a larger project isn't great either.

On the other hand, this upcoming standard is a great addition for collocating styles https://developer.mozilla.org/en-US/docs/Web/CSS/@scope

nilslindemann

jeanlucas

Indeed, it also solves a lot of problems

jitl

These days tailwind is often paired with a component abstraction system that takes place of css classes as an abstraction system. Component abstraction achieves an even more powerful separation of semantics from styling, compare:

    <h1 class=hero>Cool page</h1>
vs:

    <Hero>Cool page</Hero>
In both cases you need to go find the “hero” abstraction, but in component world we are also abstracting over the HTML tag name in addition to whatever styling stuff.

When it comes to defining the “stylistic detail” in either case, it has been separated from the “content” which is our page source file. I am happy to pay a build step to get better separation of concerns - content from presentation.

aembleton

> I simply don't see the appeal.

- Not having to name CSS classes

- Easier to read as it's inline with the rest of your HTML

- Standardised way of naming so that everywhere uses the same conventions

- Not having to manage a separate file and remove unused components

- Being able to use media queries, which I couldn't do in a style tag

- No risk of changing a class that is used elsewhere. CSS has global scoping which has its benefits but is risky.

agos

no, a single html attribute containing "relative before:absolute before:top-0 before:h-px before:w-[200vw] before:bg-gray-950/5 dark:before:bg-white/10 before:-left-[100vw] after:absolute after:bottom-0 after:h-px after:w-[200vw] after:bg-gray-950/5 dark:after:bg-white/10 after:-left-[100vw]" is not "easier to read" (example taken at random from the Tailwind homepage)

oneeyedpigeon

Just viewing the source of the Tailwind homepage breaks me out in a cold sweat. And then there's:

    > console.log(document.querySelectorAll("body > script").length)
    27

aembleton

Easier to figure out what to change without affecting other HTML components, though.

presentation

Use PandaCSS, the result is similar but the syntax is a readable object instead of… that

skeletal88

The problem is that with bootstrap I have card, table, etc. With tailwind I have an unreadable alpabet soup when I am not a designer but a developer and am not familiar with tailwind.

Ralfp

And then you build on that, and you have card-alert, card-message card-message-small, card-body-alert, card-body-message, card-form, card-login-form together with extra sass variables for them.

And then you ask "why not just have variable for each component, not each component's style?" and this is where tailwind steps in.

gedy

I greatly agree with you, but should mention that there is DaisyUI which is a Tailwind plugin that adds these for you. It seems inspired by Bootstrap and others: https://daisyui.com/

mablopoule

This is the big one for me. In any big enough or unfamiliar frontend project, my go-to way to explore the codebase is to launch the front-end, and use the inspector to check the elements, and then search-back in the codebase the relevant classes to see what page/component display that, and how does it fetches the data.

If there is only an alphabet soup, I no longer have a simple set of classes I can grep the codebase with to quickly find the relevant components.

lawn

> Easier to read as it's inline with the rest of your HTML

I really don't think a big blob of text with a bunch of unnamed divs is easier to read.

The styles night be easier to find but they're absolutely not easier to read.

null

[deleted]

benjiro

> - Not having to name CSS classes

Most websites are maybe 20 components and localized pages. Not exactly that hard to name and keep constant. Can not think of names, just ask one of the AIs.

> - Easier to read as it's inline with the rest of your HTML

Only if you do a few styles. The moment you have mobile + desktop + dark/light you start to leave lines half a mile long.

> - Not having to manage a separate file and remove unused components

Counterpoint: Components/templates are still the same hell to manage.

> - Being able to use media queries, which I couldn't do in a style tag

CSS ... literally the bread and butter.

> - No risk of changing a class that is used elsewhere. CSS has global scoping which has its benefits but is risky.

Counterpoint: You will end up with styles that are applied to parts, then copied, forgotten to change, and then have a mix of styles that conflict with each other.

And you do not use global scoped CSS, but localized per page. All you need is local CSS + a single parent id/class and voila. Local scoped will not mess with global. Do not do stupid stuff like button { style style style }. No, make global scoped iButton, so you never run into the issue off having parental styles doing funny things to child styles.

Let me introduce our lord and savvier called Nested CSS + Named CSS tags ... Reusable, standardized, ...

Tailscale is frankly a solution for front end JS frameworks, and less for any server rendered html. Use local CSS for html pages that are really local. No need to make global CSS for price cards that you only use on one page. But if something is used over multiple pages, buttons, ... that is global. Simple, no?

Ironically, i am in the process of actually removing Tailscale everywhere because the recent 3 > 4 upgrade screwed so much up. What stayed good? My actual CSS nexted/tag components that i never.

That is one of the issues with frameworks in general, etc, things between versions can really mean a lot more work vs just having everything "basic".

I feel a lot of issue that people have with CSS are more related to not having a proper understanding about CSS, and ignoring some basics. Like do not style base tags. Use nested + custom naming tags, local css + a local id/css and you have no issue with overlap. Best of all, you gain the ability to make easier reusable components as your CSS are the components, not some JS/... whatever call you need to do to render something. It gets messy fast if your breadcrumbs is a components with items, and you need to change something later on. But if its a basic breadcrumbs{} css, adding feature is just a matter of adding naming.

Trust me, took me years to get out of this mindset (and it helped that CSS evolved a lot but most people do not even realize that CSS today != what they know/grew up with)

65

Big one: Way smaller CSS bundle size.

tipiirai

It's because we've normalized React and tight coupling. Styling belongs to components, not in design systems. I feel the JavaScript-first engineering ecosystem needs brave new design-led companies, who see the power of modern CSS and systematic design.

itzami

> Historically, we avoided this to maintain a separation of concerns, but it's puzzling why some prefer reintroducing similar methods. Is it just to save a few keystrokes?

In bigger projects, if we start looking at the amount of files one has to deal with, Tailwind becomes very appealing. We've went through the regular `.css` route but then you have weird names, and, potentially, duplications or even conflicts. `css modules` is an option but you've now essentially duplicating the number of files that you have for each component / page. `sass` or `less` essentially bring the problems from `css modules` and regular `.css` into one.

I don't inherently like or dislike Tailwind (although I very much started by absolutely disliking it) but you feel its value in a project with 200+ files composed of components and pages

dbbk

You're seriously advocating for inline styles in the year 2025, it does not surprise me you are confused.

bern4444

My initial reaction to Tailwind was: what a pain. I already know CSS, now I have to learn CSS again...

I imagine its how parents might feel when they go to help their children with math homework only to find the math is now totally different from when they were in school and their methods (while still valid) for solving problems are no longer accepted by the school and their child is annoyed by having to reconcile the two systems...

I get the, tailwind works well in a team and scales nicely and you just have to use it, mentality. I've experienced it.

I still prefer a plain style sheets that targets elements by a class or tag (especially since CSS supports nested selectors!).

There is an issue in managing stylesheets, and for that I really like how Remix/React Router manages CSS where CSS flies are defined and applied at the route level. Where that isn't enough or dynamic styles are too complex for a .css file:

    style={{...}}
is always available.

CSS is so powerful, flexible, and extensible, tailwind feels like a limitation rather than an enhancement. I don't understand the continued appeal, but clearly many others do. I'm not sure why, but I am confident we'll all have moved on to something else in another 3 or 4 years too.

jitl

I agree it’s frustrating initially to re-learn CSS… I used to make the same arguments. But after contributing to an open-source project using Tailwind I got up to speed, and now I feel differently.

Tailwind is essentially just stenography for style={{…}} - a single utility takes 15 characters that would take multiple lines in a .css file or style object. It greatly reduces the amount of time I need to spend googling stuff like “visual text replacement css” or perusing various css cheat sheets or skimming through css-tricks blog posts from 8 years ago. Instead I always go to tailwind docs, and quickly learn the utility class that just does the thing I want. A surprising amount of it fits in my brain cache, much more than trying to cache the css for all the tasks I might need to do in a layout.

Aeolun

I think it’s because now your entire component is contained in a single file. No more separately messing around with CSS. The styles are right there on the element they apply to without having to cross reference anything.

You could do this with just the css attribute, but that has the issue that everyone has always been taught it is wrong to do that, and a list of strings that contain a bunch of utility is easier than writing those plain CSS objects.

arkh

> You could do this with just the css attribute, but that has the issue that everyone has always been taught it is wrong to do that

But why is it wrong to use the style attribute? What makes using tailwind to do the same thing "not wrong"?

Also this https://tailwindcss.com/docs/hover-focus-and-other-states#us... and https://tailwindcss.com/docs/hover-focus-and-other-states#st... look like reinventing the Cascading of CSS with an awful syntax.

Aeolun

> But why is it wrong to use the style attribute? What makes using tailwind to do the same thing "not wrong"?

The time people were taught it was wrong is thr time when all your elements were rendered on the server and the style was duplicated for every component it applied to.

Client rendered JS only sends it over the wire once and then duplicates it on the client.

Tailwind only allows a few options, so it’s less likely you have slightly different styles everywhere.

I think the awful syntax you talk about is really nice, since it covers 99% of everything I ever need to do with it. The cascading part of CSS is really cool, but 99% of the time it’s confusing when I don’t need it.

jitl

Tailwind I use for hobby projects but we’re still sticking with style={{…}} at Notion. Since the app launched there’s been many generations of CSS-for-React (Airbnb Aphrodite era, styled-components/Emotion era, styled-jsx/linaria era, CSS modules era, Tailwind era) come up, get hype, and then thrown in the trash heap. Probably the best move for us would be an optimizing compiler for style={{…}} or our useStyles hook.

atonse

I think it's also about automatically purging and slimming down your CSS, which is easier to do when you're just comparing tokens.

Although nowadays I'm sure they could technically do the same thing with the built in parsers without having to rely on just simple tokens.

sebmellen

Limitation reduces available complexity and that’s why tailwind wins. It’s a composable, standardized, and modularized wrapper around a very massive and complex system. That’s a big advancement.

nedt

I'm learning math with my kid and it's not different to what I learned. Can still solve everything quickly.

On the other hand there are those posts on social media mixing multiplication and division and telling you there is only one true answer to those. Tailwind isn't that bad, but it's more into this direction for me as an old fart ;)

mrits

In the US you can get all the right answers on a test and still fail

khana

[dead]

nakovet

I love tailwind, used in 3 projects in the past 4 years, it’s intuitive, well documented, simple. I don’t miss the days of emotion and styled components where I would have to think of a name for every styled div in the project, with tailwind a container is just a div and a few classes nothing else. Less bike shedding discussion, less brain cycles spent naming things, less time wasted in reviews.

dbbk

> I don’t miss the days of emotion and styled components where I would have to think of a name for every styled div in the project

I see people mention this issue fairly frequently, and it puzzles me a little. I have never once spent probably more than 1 second thinking about what to name something. Is it actually a blocker for some people? Are you really paralysed by this?

agos

especially since with any decent CSS solution (any css in js, or CSS modules) you can reuse names

dbbk

Like really, I use Styled Components, just call it a Wrapper or InnerWrapper or Row or whatever and move on

gausswho

There was a time when BEM ruled (and scarred) the world. But names aren't a problem if you abandon the C in CSS and scope all styles to component.

Kerrick

What I don't understand is why BEM is scarring. If you're talking about the reason or timing something looks different, you must have named it in that conversation. Just use that name.

"When the menu is wide, the items' icons and text should be visible. When it's skinny, only the icons should be visible. This button toggles between them."

    .menu {}
    .menu--skinny {}
    .menu--wide {}
    .menu__icon {}
    .menu__text {}

werdnapk

I'd say BEM was a passing fad, but didn't rule the world. I also think tailwind will suffer the same fate, but we'll see how it plays out.

notjoemama

> a few classes

You must be working with very good product owners then. The ones I've worked with love to specify the hell out of every possible detail. Like a web form is their personal HGTV renovation. I tried tailwind once and the classes ended up being an order of magnitude more than the markup. It got hard to read, quickly.

lowercased

you can use @apply to merge the various utility classes together in to something resembling a name, like

.btn-primary { @apply py-2 px-5 bg-violet-500 text-white font-semibold rounded-full shadow-md hover:bg-violet-700 focus:outline-none focus:ring focus:ring-violet-400 focus:ring-opacity-75; }

But their v3 docs seem to be very against this.

"Whatever you do, don’t use @apply just to make things look “cleaner”. Yes, HTML templates littered with Tailwind classes are kind of ugly. Making changes in a project that has tons of custom CSS is worse."

Reasons:

* You have to think up class names all the time — nothing will slow you down or drain your energy like coming up with a class name for something that doesn’t deserve to be named.

* You have to jump between multiple files to make changes — which is a way bigger workflow killer than you’d think before co-locating everything together.

* Changing styles is scarier — CSS is global, are you sure you can change the min-width value in that class without breaking something in another part of the site?

Yet... my experience using projects that use tailwind is that every button everywhere is styled the same way, but it's repeated in multiple areas. The 'kinda ugly' part, but also... it's repeated in multiple places. Trying to change the universal focus behaviour of buttons in a project like this is hard, because... I can't search focus:outline-none without finding everything that has 'focus:outline-none' on it. I can't just search/replace, because it'll impact other stuff.

So I end up spending way too much time trawling through way too many scattered specific styles all over a codebase, vs having a defined 'btn' style someplace. "well, that's just the project's fault"... possibly, but it seems to be the promoted/preferred/evangelized way of using tailwind, judging by the projects I've had to get involved with the past few years. IME, this approach may have good short term benefits, but poorer longer term maintenance, doubly so when the original people are no longer involved in the project, and outsiders have to come in to deal with it.

msoad

I agree with Tailwind's stance on this. You really don't need @apply if you're breaking things down to smaller components. I often see people have things like <ul><li className="long_list_of_classes">text1</li><li className="long_list_of_classes">text2</li>...</ul>. This is where I think we need a linter to warn against things like that. Make those <li>'s a component!

davedx

For buttons, I think the 'blessed' way to do it is to use (react) components and have the tailwind classes encapsulated there. It makes sense; you have a layer of abstraction where the implementation of your theme is in the "lower level building blocks" of your components. (Call it a component library if you want)

I generally only use @apply when there are some heavier external interactive libraries that are hard to style. Like for example if you're embedding markup in your application, and you need to apply a set of styles to the markup it generates, and you can't do that directly in react because you don't control that part.

null

[deleted]

djhn

> I can't search focus:outline-none without finding everything that has 'focus:outline-none'

Would a regex not work? Something like <button[^>]*?focus:outline-none

Aeolun

I generally use tailwind in combination with daisyui, and I don’t think about styling a lot any more beyond choosing the proper theme.

fintechie

Gave it a go for several projects, but didn't like it... for big projects it gets messy, fast. It also feels like it has become the new bootstrap.

I'm very happy with my current CSS-in-JS workflow. Crafting good old css with LLM help. You just show the LLM a pic, ask for the components.... boom, done (with proper naming, etc)

_heimdall

This is actually one of the main reasons I avoid react when I have the option. Styling in react is terrible, I'll use tailwind with it but only as the least bad option.

If I am using a frontend framework and a build step, svelte and astro are nice depending on the use case. I can style with plain old CSS and rarely have to reach for class names, if you keep components small you can get away with element selectors and let the framework scope styles at build time.

asimpletune

I used tailwind for my site and ended up liking it a lot, but maybe for reasons that are not often mentioned? The real value of tailwind is being able to read all the styles that affect a an element in one place. Sure the classnames can get long, but it’s still a lot faster to read that long line, than open the browser tools each time or scroll up and down one (or many) stylesheets.

Then when you come back to that code later, you can confidently edit it without worrying about causing changes to other elements.

The cascading nature of CSS is still helpful, but I find that I usually want to limit my styling to just one element. For all the rest I go back to css but I wrote very little css because I usually just want to get the whitespace right.

jitl

I think that is exactly why tailwind is good and nice. Although I also like that it makes “how do I do X?” a quick doc search instead of a 30 minute research project

twelve40

> real value of tailwind is being able to read all the styles that affect a an element in one place

there are helpers for that in the IDE (e.g., "Show Applied Styles for Tag" in Intellij) or even in chrome dev tools that show all this in a readable way. Tailwind snippets mentioned in this HN topic look kind of scary in comparison.

asimpletune

The difference is with tailwind that information is stored as text in source control. So you can parse it with nothing but your eyes in GitHub or by looking at a diff, without relying on any extra tooling.

topicseed

I kind of agree but the same problem exists. If you add text-xl to a div and have nested divs and spans, they'll all be inheriting text-xl so for these nested elements, you also have to look up the element's lineage to find what's causing the text-xl.

But overall it's a bit easier yes.

javier123454321

That's the css cascade, not a tailwind issue.

rglullis

"Build times reduced", "no more @tailwind directives", "No more js configuration", "Designed for the modern web".

To me, this screams "CSS now can do everything we used to do ourselves, but let's keep pretending that we are still needed somehow"

crowcroft

If you going to hate on it, at least try understand what it is and why people use it.

rglullis

It's not "hate". It's just that I don't see the value that it brings today.

ervine

Whether you enjoy utility classes isn't really related at all to what css supports.

crowcroft

What value does Rails provide to Ruby?

crooked-v

"Basically just inline CSS, but less fiddly and much more optimizable than the style attribute" was always the selling point of Tailwind in the first place.

Sateeshm

But it's not just inline css though. The length of inline css string would almost always be 3 times longer than tailwind classes string.

Also inline css doesn't allow media queries, pseudo classes, etc., which is a big deal.

rglullis

Then, yes. But nowadays CSS is a lot more powerful and has caught up. So why bother with Tailwind?

jitl

CSS has become more confusing over time, not less confusing, so the upside of a utility class approach like Tailwind is also improving over time rather than decreasing.

Tailwind solves css confusion by presenting a “paved road” for many tasks. Want to do “thing”? Just look up “thing” in the tailwind docs, add “thing-2” to your class, done in 2 minutes. Rather than look up “thing” on google, skim several articles, then write 4-10 lines of CSS, done in 30 minutes.

As CSS has gotten more complexity from new capabilities, solving various tasks with it feels more and more like a research project. Like centering a div vertically and horizontally - there’s now 3-4 generations of solutions for this task:

1. Hacky stuff with position: absolute or floats

2. Flexbox approach. Hope you remember the 6 different attributes you need to set! Oh, there’s a new shorthand for flex now? Cool! More stuff to learn.

3. Grid approach. There are a bunch of different ways to structure a grid centering approach. Hope you remember how grid templates work!

With tailwind, just add 2 classes, done.

listenallyall

A concrete example that seems like a no-brainer to me: let's add a little padding to the top and bottom of an element. "py-2" Done. In CSS, specifying padding (or margins) is 4 values... except I forget which is the first one. And what units should I use... px, pt, rem, em. Inline, same-page style, or an external .css file? If not inline, what should I name the class? Vanilla CSS literally requires 10x more time and mental attention.

BeetleB

Do you have any links describing what you mean? I'm not a CSS guru, and perhaps I know only the "old" CSS. I did recently learn Tailwind and it's way nicer than the "old" CSS.

If modern CSS makes styling as easy as Tailwind does, I'd love to read about it.

Sateeshm

Because of multitude of reasons. One of the big ones being never having to search through a style tag or finding a CSS file. 100% of the element styling is described in the element markup.

Tailwind was never about filling gaps in CSS.

buzzerbetrayed

Why do you keep saying CSS has “caught up”? Tailwind has always just mapped to CSS, so you’ve always been able to do anything in CSS that you could do in tailwind. What has CSS done that makes you see no value in Tailwind today where you used to see value?

crummy

What did you need Tailwind for before that you couldn't do in normal CSS? Doesn't Tailwind map pretty much 1:1 to CSS?

rayrrr

Every programming language maps 1:1 to CPU instruction sets, but very few humans want to speak CPU language directly…hope that helps.

xigoi

Programming languages are more human-readable than CPU instructions, as opposed to Tailwind, which is less human-readable than CSS.

BeetleB

> Doesn't Tailwind map pretty much 1:1 to CSS?

Much of it does, but not all of it.

_heimdall

Do you have an example that Tailwind can do that can't be done in CSS?

dankobgd

It's a horrible way to do what css can do but in a dumber way with added tooling. It is used by people that don't know css and this is where the problems start

jitl

I’ve been writing css/scss/stylus/linaria/whatever styling stuff for 18 years and I think tailwind improves life much more for css knowers than for css noobs. I prefer it over raw css for sure - I’ve written the same shit enough times that I’m happy to take some shortcuts and more than willing to pay for some tooling to do so. Tailwind hands out less abstraction rope compared to vanilla css and sass and all the rest, so much lower chance I open up a file and find some convoluted special little kingdom of abstractions that need to be handled carefully. Reduced cognitive load in the long run for a small up front learning/setup cost.

ervine

Yes.

bitpush

Really!? Is that really what you got out of it?

I understand you're not a fan of Tailwind, so perhaps say what you dont like about Tailwind instead of creating a strawman and attacking it.

Also, shame on you for poo-pooing on someone else's open source project and people find useful.

rglullis

"What I don't like about Tailwind" has less to do with Tailwind itself and more about the violation of separation of content and presentation that they push so hard.

> poo-pooing on someone else's open source project

This is not some young kid doing free software out of kindness. This is a company making millions of dollars in revenue in a closed source product (tailwind UI), which is built on a foundation (tailwindCSS) that is becoming less and less needed.

BeetleB

> and more about the violation of separation of content and presentation that they push so hard.

As someone who's done it both ways with web sites, that separation sucked. Having to figure out which style in my CSS file was messing things up was always a pain. And Tailwind tends to be "local" by default, limiting the damage done to other elements when I style an element.

In my larger experience (not just with web sites), whether separating content and presentation is a good idea varies widely from use case to use case.

yCombLinks

Often content and presentation are part of the same package. In these cases, separating them makes maintenance of sites harder.

mc3301

Yeah, I tried (not so hard) to like and use tailwind, but I've been using bootstrap for so long, and for my very simple needs, bootstrap was a better choice. But I wouldn't go around saying, "tailwind is unnecessary for everyone."

notjoemama

I'm with you. Tailwind would be great if it could be SASS'd but Tailwind is a post processor and it would be silly to build a post-post processor just to make tailwind reusable. It simply isn't a good tool for large enterprise applications. Toys, home projects, sure. But then, why learn CSS twice for occasional use? Until they solve the post processor problem, I'll stick with bootstrap. But if they do, I would definitely switch. That would be the best of both worlds.

davidw

Question for people who are good at CSS stuff. I am not.

I'm upgrading a personal Phoenix project to 1.7, and Phoenix now uses Tailwind by default. So I thought I'd try and update my one page thing to use it instead of Bootstrap.

So far, it looks like crap whereas the Bootstrap one looked 'good enough'.

What's the easiest way to get something that looks kinda sorta decent, with some nice defaults, without trying to become a designer?

Or should I just reinstall Bootstrap and be done with this.

jmull

> Or should I just reinstall Bootstrap and be done with this.

That one.

Tailwind gives you tools when you want to control the design, but you’ve got to control the design.

When you just want something that looks good and don’t mind that bootstrap-y feel, bootstrap is the way to go.

(There are projects that essentially recreate bootstrap on top of tailwind, which, in theory, might give you something like bootstrap as a starting point with the power of tailwind, but I haven’t seen it work better in practice than just using bootstrap.)

ricw

Disagree.

Just get one of the tailwind UX kits and use their classes as your standard style guide. I personally use flowise as it’s free with paid more complex components if needed, but there are a bunch of others out there that fill the same space.

_heimdall

On a new project, sure maybe going with tailwind + a theme/kit is a bit more up to date than using bootstrap. But on an existing page that already looked fine with bootstrap, why bother with the extra work?

addandsubtract

The same can be said about Bootstrap, though. Just get a theme to make it look less bootstrapy. I think both viable ways to go, and it just boils down to personal preference (especially for hobby projects).

jmull

That's fine (I've done it). It's just that bootstrap is better at it.

skeletal88

Can you suggest which of these kits are good?

floydnoel

I use DaisyUI to accomplish that goal, here is my demo site for an example: https://nwk-landing-kit.netlify.app

and here are the docs for DasiyUI: https://daisyui.com

davidw

The DaisyUI description of the Tailwind button made me laugh:

"bg-indigo-600 px-4 py-3 text-center text-sm font-semibold inline-block text-white cursor-pointer uppercase transition duration-200 ease-in-out rounded-md hover:bg-indigo-700 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-indigo-600 focus-visible:ring-offset-2 active:scale-95"

Yeah, that's not making my life easier is it. Also some of those class names are super cryptic.

loxs

They are cryptic but the learning curve is not that steep. Once you get the idea, it becomes much easier (and quite pleasant for a CSS hater like me). For example px-3 means "padding on the x axis 3 (spacing values)" and gives you padding on both left and right. There is a (rather simple) language that you need to learn and at least for me it made things much, much better. You can probably get the feel for it in several hours of building a basic website with Tailwind (and DaisyUI I would recommend).

moojacob

If your looking for components like bootstrap try https://flowbite.com/ for free. Tailwind also has paid components. You just copy and paste. The cool part is once you get more comfortable you can start to tweak the flowbite components.

kyleee

I’d say it depends on who is paying you. If you have job security and want to tinker, then play with tailwind if you want (most trendy / loud people seem to like tailwind). If however you are working on your own project / are self funded / or have a deadline just stick with bootstrap that you know, and focus on getting your work done instead of bike shedding on the UI

bushido

Tailwind and Bootstrap and are kinda apple vs apple pie. Tailwind provides classes that still need to be stacked to build components.

It'd be easier if you were using some source for UI components, I've used TailwindUI in the past, but that's paid. I'm sure there are good free alternatives.

bebop

A friend of mine who is good at these things recommended https://mantine.dev/

darkhorse13

You can check out Halfmoon too instead of Bootstrap: https://www.gethalfmoon.com/

bitshaker

Put your HEEx into a LLM. They understand both Bootstrap and Tailwind very well. It will probably not be too hard.

newusertoday

reinstall bootstrap and be done with it. You can look at daisyui it is closest to bootstrap. There is also shadcn ui, ui looks good but it would take you effort to port styles to your phoenix project.

0xblinq

There's a clear pattern in every "Tailwind or not tailwind" conversation (which happens everytime Tailwind is mentioned).

There's those that never used it for more than 30 minutes, that just tried it out or just skimmed through the docs. Those are the people that hate it and prefer "vanilla CSS" or similar.

Then there's the people that actually used it for a real project, within a team with more than 1 single person. Those are the people that understand its value, accept its trade offs and love it.

I've seen a lot of people jump from the first group to the second group. I've seen almost none jump from the second to the first.

That's why Tailwind is so successful.

It might not be beautiful in the eye of the purist, but it's absolutely fantastic in the eye of the builder and pragmatic.

Francute

I think I don't fit in either of your groups.

I’m not against Tailwind, but I didn't used it yet because I struggle to see why it's a better approach compared to other options like Web Components or React Styled Components.

The biggest issue I have with Tailwind is how it clutters the HTML with a ton of utility classes making the HTML harder to read and maintain. Of course I see Tailwind being better than using large global CSS files with the classic CSS approach of naming html tags. But we do have ways where the CSS is scoped to a component without polluting the global namespace. Like Web Components and Styled Components. Both keep styles tied directly to the component (or more general, a specific group of html tags), making it easy to see which styles apply where.

And yes, with them there’s no need for global class names, without having to worry about unwanted side effects or clashes. If I remove a component, I also remove its associated styles without worrying about unused CSS being left behind since both are tied together. Plus, there’s no risk of one component's styles unintentionally affecting another (thanks to shadow DOMs).

I really value keeping HTML very short and readable by not mixing presentational styles directly in the markup. Tailwind’s approach, where the styling is all in the class attributes, makes the HTML feel cluttered, especially when you have long class lists on a single line, and GOD forbid you have actual class names to use there. It’s harder to understand what styles are applied at a glance since you cant even have it well indented, and it clearly reminds many reasons why we moved away from the inline style attribute in HTML in the first place. (Yes, we didn't left it for its limitations like pseudo classes and @media queries, they didn't even exist, we didn't add those new features because no one wanted to get back to those inline styling)

So, while I don’t hate Tailwind, I just don’t see the clear advantages over Web Components or Styled Components in terms of readability, maintainability, and separation of concerns, while I do have important unanswered important concerns about using it...

Yes, I've read the docs but never tried it out, I don't hate it, but I can't understand why I would choose it over other options. The fact of having a million classes in the middle of plain HTML makes them both unreadable for me.

And No, I don't like huge CSS files either, or the classic approach of using them. But it is hard for me to see why tailwind is a better approach than working with Web Components, or React with Styled components.

These two approaches allows me to not have to read presentational things in the middle of my html, and allow my html to be more clear and readable. I don't have to use CSS class names, it's easy to identify which CSS applies where, so, if you remove the component, you remove the CSS too, you don't end serving unused CSS rules. Each can have CSS not leaking to the global scope, and there is no risk on changing styles of another element...

So, there is no hate for me, but it is very hard for me to see the benefits of tailwind over these two approaches, and I really dislike the idea of having to read html elements with huge styling rules cluttering my html files, and worse, having all of them in a single line makin it hard to understand all the applied styling.

We left using style tag from HTML mostly for that reason, and not because of its current limitations (like not being able to use pseudo classes, media, etc)

0xblinq

> I’m not against Tailwind, but I didn't used it yet because I struggle to see why it's a better approach compared to other options like Web Components or React Styled Components.

> The biggest issue I have with Tailwind is how it clutters the HTML

You're 100% clearly in the first group. Maybe I shouldn't have said "hate" in that group, just people that don't like it or see its benefits.

> Like Web Components

That's a nice solution, but in practice as of today and relatively speaking: nobody is using them.

> and Styled Components

Except the performance is a lot worse. And you still have to come up with names for every single div that needs a minimal one line style.

And both of these solutions end up with huge CSS files. Huge CSS files are worse than having larger HTML markup, because CSS is a blocking resource and HTML is not.

> I really value keeping HTML very short and readable by not mixing presentational styles directly in the markup

People used to say this about React, they preferred their HTML separate from their JavaScript, all nice and clean. I'm now 150% sure you're in the first group.

> Yes, I've read the docs but never tried it out, I don't hate it, but I can't understand why I would choose it over other options. The fact of having a million classes in the middle of plain HTML makes them both unreadable for me.

Alright, now you've recognized it.

> These two approaches allows me to not have to read presentational things in the middle of my html, and allow my html to be more clear and readable.

That's a non issue. There are extensions that will just hide classnames. You're just blending your mind looking for reasosn to justify your "I don't like it".

I promise the day you use it in a real life project where you're working with > 3 other people you will understand it's benefits, and how having "large class lists" is a non-issue and a totally acceptable trade off over the practical benefits it provides. Both on performance of the resulting CSS and maintainability over a large period of time. And think in the insane amount of discussions you'll avoid regarding if we're calling this div "styledDivWrapper" or "WraperContent" or "CardWrapper" or ".card__item--dark". Not an issue if you work alone, but when working with others this becomes a real annoyance that tailwind completely removes.

Tailwind is not for your, don't use it.

Tailwind is not for purists and architecture philosophers.

Tailwind is for pragmatic people, working on real life projects within teams where they have to ship and spend less time philosophizing on the purity and beauty of things.

pupppet

I appreciate there are people who find Tailwind useful and are productive with it, but it has this clean yet generic look that I now see everywhere, because Tailwind is now everywhere.

gkoberger

This is conflating Tailwind and TailwindUI/shadcn/etc.

For the most part, Tailwind offers no more influence over style than normal CSS (okay, there's some exceptions... things like shadows are a bit more standardized, and indigo has gotten outside influence on color palettes as of late).

Sateeshm

Tailwind gives you sensible defaults, but doesn't really influence your design too much. People just tend to design the sites a certain way. Especially, with ShadCn.

sadmanca

I feel like that's a good thing, because Tailwind's options are well-thought and work well.

I like to think of it in the same way as Inter being the new Helvetica when it comes to choosing a font for a website: lots of people do it, and it looks great, so why not?

harrall

I heard this comment about Bootstrap back this in the day but none of my Bootstrap sites looked like each other. Bootstrap saved me a lot of time because it had a lot of utility classes (like Tailwind way before Tailwind) and it never enforced a certain look.

You just loaded the classes that you wanted (unless you didn’t download the source Sass files, but that would have been silly).

cloverich

My take on this problem is, good UI frameworks (i.e. tailwind + components) are still rare. So the vast majority of projects use a very small number of them. If 4-5 new quality UI projects popped up, especially if they departed more in their styling, we'd see more diversity.

I've come to realize with design, like much creative work, the trends really do seem to be set by a shockingly small number of people. I wish more people realized this, because I feel there are talented individuals out there not making their own, thinking they'll never be heard. But I suspect some of those people would be unlocking new UI's for a large chunk of the web if they would give it a go.

Zanfa

The same way everything looked like Bootstrap a decade ago.

gr__or

Tailwind is a testament to the greatness of inline styles (styling a thing without naming it), the universality of strings and also the limits of strings.

I am excited for what comes after it, until then I'll use Tailwind (reluctantly)

mythz

Was it really necessary to break all existing apps using `npx @tailwindcss`?

It's an easy enough change to `npx @tailwindcss/cli` but we now have to go back and update all Apps and templates and since it uses v4 we now have to test every App to see if anything's broken with a v4 major release.

Given its massive install base, surprised they wouldn't maintain backward compatibility with v3 and have an explicit opt-in upgrade path to v4.

Edit:

v4 did actually break all our Tailwind Apps which doesn't support `@import "tailwindcss"`, likely because we use `npx tailwindcss` without any local npm dependencies. Trying to use the existing v3 `@tailwind components` renders a useless app.css. Only solution atm is to explicitly use v3 and change all our build scripts to use `npx tailwindcss@v3`.

jitl

You’re doing something silly living without a lock file to use a tool as part of your build process. Why don’t you actually include the version of the tool you want in your dev dependencies + lock file? That way, you don’t get broken. We’ve had the solution to this problem - lock files - for 15ish years, since Ruby’s `bundle` introduced it.

mythz

Not everything is a node App. We don't have a lock file because we don't have any local npm dependencies (as already mentioned). We're using `npx tailwindcss` as-is.

jitl

You clearly have a dependency on tailwindcss (if it can break you, you depend on it), and are using npm to fetch it (npx uses npm internally, they are installed together) so you can easily solve your problem by adding a couple json files with some version numbers in them. npx will pick up and use the version from your package.json, so no workflow change other than running `npm install …` once to generate package.json for your preferred semver specifier, and package-lock.json to guarantee your builds use a known-good version from now on.

nejsjsjsbsb

Shove an @ version in it

GrzegorzWidla

So why not npx tailwindcss@^3.0.0 (or whatever version was there when you started)?

aembleton

> Given its massive install base, surprised they wouldn't maintain backward compatibility with v3 and have an explicit opt-in upgrade path to v4.

Given it's a major version change, I'd expect it to create breaking changes, otherwise it would be a minor version change.

tlrobinson

Tailwind’s abuse of CSS classes as a DSL has always felt like a hack to me.

You shouldn’t need a special editor extension to get highlighting/autocomplete/etc, just use TypeScript and a CSS-in-TS solution.

darkhorse13

> just use TypeScript and a CSS-in-TS solution

THIS is the definition of a hack to me, so yeah.

dbbk

May be a hack but it just works.