Tailwind is the second best thing ever happend to frontend, only Vue 3 tops it.
Not having to come up with names for CSS classes, no duplicated CSS code, no fighting conflicting classes, everything in one file, being able to visualize a component just by reading the code... it's a godsend. I'll never go back to SCSS unless work obliges me.
Vue 3 with <script setup lang="ts">, TailwindCSS and Vite. The way God intended.
The first time I saw tailwind I almost threw up in my mouth because it broke so much I hold dear about CSS. A few weeks later I went to their site being all wtf is going on here, and I saw this quote on the front page from its creator:
> If you can suppress the urge to retch long enough to give it a chance, I really think you’ll wonder how you ever worked with CSS any other way.
Please do try it, it really does speed things up if you care enough to learn it. IDE integration is a must. A lot of people seem to try it for five minutes, then conclude with absolute certainty that “this sucks” which is very annoying. If you like building good web views fast but don’t care enough to learn the massive core of css (or some hot new js-to-css-or-whatever tool) then tailwindcss is perfect. I build web views every now and then, but it’s not interesting to me, I want to rabbit hole on the real issues, which usually reside elsewhere. Also, I learned it years ago, and that knowledge is still useful, can’t say that about most web tech :)
Bootstrap gives you a pre-made look and feel that you can use despite knowing CSS or not and maybe you can customize a bit, make a theme, etc. Bootstrap is more like "Tailwind UI" which is different thing from Tailwind (the tool).
To use plain Tailwind (without Tailwind UI) you do need to know CSS. It's just like a "CSS-in-JS" tool, except it's "CSS-in-HTML" this time.
I was one of those who resisted. Now I won't not use tailwind if I have a choice. The best thing about it is I feel like I'm still writing vanilla CSS, just in a different way.
It goes against semantic web, the old css zen garden etc, with good markup I can style a page however I want.
However using tailwind, it’s the get shit done tool. It is ugly, it goes against good web design and everything I believe makes good web design but it works fantastically well in practice.
I dislike using tailwind, at the same time I will choose to use tailwind without hesitation as it makes up process a lot less friction and avoids selector conflicts.
> Not having to come up with names for CSS classes
As soon as you want theming you'll need to start naming stuff. And if you want that theming to support third-party CSS overrides, or need good CSS selector support, you're going to be back to needing to name classes again.
Not everyone needs that, and that's fine. But there are plenty of people working on products and in environments where the Tailwind way is not going to be the path of least friction.
I would actually say StoryBook, or the StoryBook pattern at least, has been a much greater boon on FE development over the last decade.
A nice thing about tw is you can set your colors, paddings, etc, to resolve to CSS variables. That + some tweaks to the tailwind config, you get a nice themeable setup that doesn’t deviate too far from vanilla tailwind, imo.
Somewhat - but when your theme change does things like "buttons are now green outlined rectangles instead of blue filled rounded corners", Tailwind shows its weaknesses.
DaisyUI on top of Tailwind helps, but then you may as well use Bootstrap and get better component support.
Coming up with css class names is not hard. And if you're that creatively inhibited to not come up with the class name 'pricing-card' for cards in the pricing table, there's crutches like BEM ( https://getbem.com/introduction/ )
BEM was great, for the early to mid 2010s. Utility classes have still been a big productivity win for me.
Working on an app with a great deal of technical debt last year, moving to Tailwind made a world of difference in being able to restyle components without also breaking styles on distant parts of the app that nobody on the team realized were relying on the same styles.
You can still name things when it makes sense, I just like that in tailwind I don't have to name ALL of the things. It's nice to be able to easily add some margin, or padding, or a few style properties to an element, instead of coming up with a name AND adding those properties in a separate file.
And in practical real life terms (where teams and long term projects and people coming and leaving the team over years and different skill levels, etc) is how CSS becomes a write-only mess.
Tailwind is primarily a way to do "css-in-js", except it's "css-in-html". It might not look nice on the eye but it's fucking easier to maintain, safer to remove, etc. As long as you have a way to create "components" you're fine.
> Coming up with css class names is not hard.
Yes, unless you work alone on your tiny 2 weeks old side project, it's fucking hard.
It's slightly more convenient, but Vue3 is already great. I like to support an ecosystem and I want a framework to keep existing, making sure I can maintain my projects in the future. That is why I don't jump ship.
I have, it's just as good if not a tad better, but I'm so comfortable and productive with Vue and they're so similar that it's just not worth switching. I'm also very familiar with the Vue ecosystem, so anytime I need a library or plugin I know exactly what to pull.
Svelte pops up out of nowhere because people tend to really love it. Not sure how it's the "React of frontend tech" since React is a competing frontend framework (which is now moving to adopt a Svelte-like compiled approach).
I haven't used Vue (any version) so this wouldn't be the place I'd normally chime in about Svelte. People seem to love Vue as well.
> React is a competing frontend framework (which is now moving to adopt a Svelte-like compiled approach)
React has been moving in the direction of a compiled approach for over seven years now[1], predating Svelte’s first release. The introduction of hooks in 2018 grew out of early efforts on an optimizing compiler. Those earlier efforts were hampered by class semantics making things like constant folding across components difficult. React Forget seems like a predictable progression from there.
Interesting take. I get why people writing a certain class of programs love Rust, but I can assure you Svelte doesn't do much to ensure correctness of the front-end app. It's just way more ergonomic than React for the vast majority of small to mid-size projects, and probably large projects too.
Rust is also about 100X as difficult to learn as Svelte (assuming you have basic familiarity with front-end dev), and easier to learn than React as well. Speaking from personal experience.
Too bad the buttons come out with transparent background. I gave up and used boostrap 5, since I had to actually get work done instead of reading github issues.
What? It doesn’t sound like you actually looked at the premise of Tailwind in the first place. It does not come with pre-canned components. This is clearly user error.
Maybe we should start to treat this like the yearly hardware releases? Buy one generation, skip the next, buy the next...
So if you're on the vue-wagon, skip svelte and wait until the next "The way God intended". If you're on svelte now, skip the next "The way God intended" and then after that, jump on the new wagon.
I was heavily into full-stack SSR frameworks + jQuery, then Angular and React came along and I was like "oh heaven, is this were we headed?", ignored both of those for years and finally found peace in the sacred words of Evan You.
TypeScript is my "skip X" phase, I'll wait for the next compile-to-js language which better be a dynamic one again. Hopefully something in the lisp direction instead of the opposite like TypeScript. JavaScript deserves to be free of its shackles.
As a forceful critic of Tailwind over many years now, I must say all of the announcements under the CSS-first configuration are extremely welcome. This makes it possible to take advantage of all of Tailwind's design tokens, reset, etc.—and even even customize them via real CSS—and then use tokens in honest-to-goodness CSS via native variables. This opens up a new world of "light" usage of Tailwind for its theming and utilities, *without* throwing away all of the awesomeness of modern CSS architecture, the cascade, and even shadow DOM in web components.
I'm a huge fan of this major improvement to the framework.
1. When you're working with this code, it's far easier to read with proper formatting and syntax highlighting. I know people take issue with the verbosity of tailwind, but anything will look awful if you remove formatting.
2. This is lacking an equivalent non-tailwind approach. If you can share the equivalent vanilla HTML/CSS (or pick your preferred framework), and then paste it here as an unformatted text blob, this might be a bit more fair.
3. I don't think it's fair to describe this as just a "box with rounded corners and a top and bottom section". That can be done with tailwind with less complexity/syntax, if that's truly all you want.
Again, show me the equivalent widget implemented some other way and we can have a useful discussion.
Having spent a little time experimenting with tailwind for prototypes in the past, I can understand what that snippet is doing pretty easily. Having spent a lot more time writing vanilla HTML/CSS, I can immediately imagine all of the ways the vanilla version would be a nightmare, or at least take far longer to build “properly”.
Tailwind is a fascinating project because it seems to either make sense to people or it seems to deeply offend them. For whatever reason, I’m able to build things with tailwind after just a few hours of use that I could never accomplish from scratch (or with some popular CSS frameworks for that matter) after years of hacking on HTML/CSS.
15 minutes getting familiar with the class naming conventions makes all of this seem far less scary.
And it’s worth considering the variety of use cases a framework like this is useful for. Maintainability means very different things depending on context, team, and what kind of thing you’re building.
I can't wait to see what happens in 5 years when all of this unmaintainable mess still needs maintaining. I suspect it'll be just as fun as maintaining old bootstrap or any other short-lived frameworks of yester years.
Inline styles and abusing divs. I suspect the next hotness will be nested tables again.
This is only 20 max CSS classes. Yah, you haven't been a REAL tailwind maintainer if you haven't worked on a website that uses 50+ CSS classes for elements - some with minor variants! I had to do so and deeply regret the experience.
It was like extreme eye exercise with eyeballs popping out at the end of the work day.
Tailwind CSS is a write-only CSS cult at the moment. Cults take some time to die. After a decade, one will have dozens of "Why I quit using Tailwind" posts on HN. Back to vanilla CSS!
Now, if one wants to use a sane implementation of Atomic CSS, look at: https://open-props.style/. Jeez that is so much more readable and maintainable.
Yes. Much more than doing this via a number of detached and separate CSS classes defined in different files, with colliding rules and all the fun that goes with this. Or better yet, inventing enough small composable utility functions to work around these issues until you might have well have used tailwind.
When you say “does this look maintainable”, what you should be saying is “does this look maintainable compared to this other thing”.
And this, to me, is why Tailwind is so popular and why I find it valuable. Despite looking a bit verbose at first, it’s pretty easy to pull together some pretty advanced pages without having to invest much time at all.
And the time saved only increases with more proficiency/familiarity with the available classes.
Things very quickly “just work”, and the conventions apply pretty uniformly.
It would probably take me 20 minutes or so, and would be very maintainable and not make anyone's eyes bleed. I'm not willing to put that 20 mins in to prove my point, but I am certain that the unmaintainable code vomit which they have as an example on their website took much longer than that.
I use raw CSS. I just scope it to the component level and I've never had a problem on any of the projects I've worked on. I do tend to avoid absolutely massive projects but I've worked on plenty of fairly big codebases and there is no problem as long as the CSS is scoped well using CSS modules. Inline styles are awful for maintainability and readability of the html, which is an important semantic description of your content.
I host a secret dislike for it but was really turned off by you including in-lined SVG files, shifted me more towards "maybe it isn't bad relative to peers"
...or maybe the build-output isn't a great indicator for maintainability. If you write your html directly like you posted above, it won't be maintainable regardless of how you structure your css.
Okay, if that's how they're selling Tailwind, I can understand why some developers are confused.
I assume they do it because they don't want to promote a specific framework on their homepage.
Go to the section "Worried about duplication? Don’t be." Does the code there look more maintainable to you? Because that's how you should be writing any moderately complex html anyways.
If you have to use grep to find a CSS class, you're doing it very wrong. Not having any discipline or organizational skills leads to needing grep to find CSS, it is not something inherent to CSS itself.
In my front end, for example, I have registration-page.jsx and registration-page.less, and there is really zero mystery where the styles are for the registration-page. It uses components like password-input.jsx, and guess what? the CSS for that is in password-input.less. There's no grepping, there's no difficulty finding the classes that are specified. Everything is very orderly and easy to find.
Even if your styles aren't colocated you can use sourcemapping alongside established patterns on how to structure out your scss/less. Just inspect the element and click on the filename next to your selector and it opens in your editor.
And what about projects that don’t exist in a paradigm where css can be collocated with templates/components? Legacy projects? Large contributor teams?
Until you discover that one feature in production that is built with dynamically concatenated class names and the SCSS file is deeply nested to hell and back so your search didn’t find `card__${cardType}__inner—-${userPrefColor}-background`
I'll take this version over tailwind anytime. It's one auto-formatting step from being perfectly readable for someone who knows css and styles tell me how it looks like and css classes tells me WHAT IT IS. And information (nearly?) completely missing from tailwind counterpart. I can also easily see what structure the DOM has.
yeah it just looks like that to everyone else, so you're avoiding the pain yourself while inflicting it upon anyone interested in inspecting the compiled output
I'm not a fan of tailwind, but this isn't what I optimise for when building websites.
Besides, I suspect (but not know, because my experience with tailwind is very minimal) that that output is readable and understandable by those experienced and developing with tailwind. On top of all the other affordances modern dev tools gives to understand styling on elements (esp. the computed pane)
When you build websites you are creating code for others to read as much as you're creating an "app" or document.
It's the very essence of what's good and special about the web. If the companies that are trying to do away with this succeed, we will have lost something important.
The web is and should remain de facto open source.
> When you build websites you are creating code for others to read as much as you're creating an "app" or document.
I couldn't disagree any more with this. When the overwhelming majority of your users would never actually be impacted by this, I believe you have more of a responsibility to the bulk of your users, rather than a fraction of a percentage.
I say this as an open-source developer, who ships source maps to production. I would much rather us increase our development veloticity and build higher quality products rather than satisfy one nerd who might want to occasionally view source.
> When you build websites you are creating code for others to read as much as you're creating an "app" or document.
That's an approach people are certainly welcome to take, and I'm glad that some people do, but I disagree that this is what the act of building a website entails.
This feels a bit like romanticizing the early days of the web, when the primary form of learning involved reading other people's source code. The depth and breadth of ways to learn in 2024 looks nothing like those early days.
If I choose to build something to solve a particular need or to communicate something I care about, it's my choice as to how I do that.
> It's the very essence of what's good and special about the web.
The very essence of what's good and special about the web is the diversity of solutions, the myriad of entry points to becoming a web developer, the existence of tools ranging from vanilla HTML/CSS all the way up to complex frameworks like Tailwind, and your freedom to pick your path.
Tailwind's existence does not threaten the layers underneath it.
Your use case is fairly specific. Tailwind is a tool, if it doesn't make sense to you and your use case, it's okay to not use it. That said, it's not okay to misrepresent what Tailwind actually is like the original commenter did.
I'm so glad this wasn't the prevailing opinion when they first came up with the web. "Inspect source" is how I learned how to build my first website in the newly released browser called "Firefox 1.0".
I learned how to build websites in the late 90's similarly. Then progressed by reading blogs of other developers who shared their source in their posts.
It made sense back then because it was all we had to learn. Today there's tons of code to learn from both in open source and resources.
Lets get rid of this false dichotomy that the only way to learn is by viewing the source of websites, in the year 2024.
It's because of the mentality that things should be open and inspectable that we have things like browser devtools (thanks Firebug!), that is something we still use today to learn and troubleshoot. Sometimes it makes it harder when people use various compile-to-js/css languages, but also sometimes people ship their sourcemaps and again we can learn from examples. Or we try to reverse-engineer it, which is another valuable skill.
I didn't mean to say this is the only way of learning, but I stand firm on that it's still a great way to learn, to look at how cool stuff was done when you come across it on real websites, not just from blog posts describing something. In addition to reading fundamentals, practicing small projects and so on, of course.
It wasn’t an opinion, but I think you gave me the answer anyway, which seems to be “students learning CSS”. I never learned CSS like this, so I wouldn't think of it.
I started learning CSS only about 6 years ago. So I had Stack Overflow and MDN web docs for it.
The answer, as with all code, is "you, six months from now".
Anything that makes your code less readable is a fail. I understand that people want to treat CSS and HTML as assembly, but that's a leaky metaphor, and only works insofar as you never have to debug an actual webpage.
Every place I've ever seen with tailwind has struggled with front end work, because the end result is so horribly abstracted from the code.
Yes, I know. Tailwind emits this kind of gibberish as a compilation step, which makes it much harder to figure out what's breaking when you're using a browser inspector or something. Which of the 83 different classes is the problem? Good luck!
You have to have a certain level of discipline to write clean CSS, but it really isn't that hard. It shouldn't take a 300-character inline style to make a button, when you can use CSS as intended, and have a class named "button".
Much prefer reading this and making a change in place, than to go through a bunch of overloaded class names (e.g., 'container') in dozens of .css files just to adjust something like a margin on it.
I don't think this is a very good example, because it's not just "a box with rounded corners and a top and bottom section". It's a fully styled box containing formatted code (leading to a lot of spans and classes for individual chars in this code).
> Standalone CLI — we haven’t worked on a standalone CLI for the new engine yet, but will absolutely have it before the v4.0 release.
This part is the most exciting to me. Given the rest of the release announcement, I'm assuming this means that it'll be built in Rust rather than embed Node. While I'm not a Rust zealot of anything, I'm very partial to not embedding Node. Particularly when it depends on using Vercel's now-abandoned pkg[1] tool.
It'll likely embed Node I'm afraid — the vast majority of Tailwind is written in JS so we'd have to rewrite all of that in Rust just for the standalone CLI, and migrating the entire project to Rust is impractical because we'd have no JS plugin story like we do now.
The current standalone tailwind CLI does not support external plugins like DaisyUI. It would be great if external plugins could be supported in the next CLI version, it will reduce the need to use npm for some projects.
Thanks, that looks like what I was looking for, did not find that when I looked few months back. I tried it now and had some issues with SIP check on macOS, started a discussion in the repo.
Don't you need to use npm to install DaisyUI though? If you have to install third party plugins using node already to me the solution is to use our actual node CLI instead of the standalone one.
The way I was thinking this would work is that the standalone CLI could be configured to pick up plugins from a specified location. That way as long as the plugins are setup locally in the required format, the standalone CLI would be able to load them. The setup process need not require npm.
There is a sibling comment which mentioned a project which is trying to bundle DaisyUI specifically with the standalone CLI. That would solve my use case but will not be a generic solution for other plugins.
I'm feeling a similar disappointment here, although I'm sure this was carefully considered by the Tailwind team.
I've been working with a fully Rust-based web stack, and it's been such a joy. Tailwind compilation causes me to still deal with Node. I'd love to see that go away.
My friends: do we need tailwind as soon as Safari 17.4 is out?
Chrome has @scope already available and safari soon.
With @scope we don’t need utility frameworks at all and can make use of scoped css with css variables for unification. What do you think?
It took years to just convince them of the need for it. And I'm not sure anyone got convinced vs Chrome had already shipped it and Safari has it planned so they caved in. The most recent update I'm aware of is that it's "worth prototyping".
Hard to believe FireFox used to be a leader of the modern web.
I mean, there are the millions upon millions of devices that don’t run up to date safari versions. While @scope is awesome, the reality is that preprocessed nesting is super easy to use now and to rip out later. You’re only hurting users (likely poorer, less tech savvy ones) by jumping ship immediately.
In 2026, sure! Go nuts and rip it all out, but give people a bit to update first unless your target market is SF tech influencers.
I am not a front end developer, but I do maintain a few websites and I have used Tailwind for all of them.
My general take of the overall quality is that the maintainers of Tailwind have really good intuition in terms of what to prioritize, as well as excellent design taste. Tailwind is one of those tools where it only makes sense once you start to use it, but each version they've announced brings a continuously more polished product.
If you don't like Tailwind or you don't understand it or if anything I'm saying makes you mad, try first building something big with it. It's pretty maintainable, easy to read and write, and, most of all, is very portable. (I mean that in the sense that something you write in one place can be copy and pasted somewhere else and it will more than likely work exactly the same.)
As far as this version is concerned, it looks like not a whole lot has changed from a compatibility perspective, but I think when version 4 becomes official it might have more breaking changes. In any case, the prospect of a new engine is very cool, as faster builds are always welcome.
Congratulations to the team! I may not be a front end engineer, but with Tailwind I don't really have to be to make what I want.
The copy and paste statement related to portability, and that's how I was defining it in this context. It was not intended to speak to Tailwind's maintainability.
However, a traditional class-based, modular approach to CSS can not guarantee portability in the same way. So if you can not predict what effect the same classes, or even the exact same HTML, will have, then it's neither portable nor is it very maintainable either.
Out of curiosity, does anyone out there use tailwindcss with htmx (or other hateoas approach)? You obviously don’t want to have your hypertext representative of application state to have anything to do with styling, but something like tailwind can be odds with that. Cascading style sheets and hateoas obviously go together perfectly, as it’s markup and styling decoupled as god intended, but with something like tailwindcss, what are people doing?
I don’t have much insight into htmx + Tailwind, since the last time I worked with Tailwind was like 8 months ago at my prior job - and even then I did very little styling work. With that said, it’s not really clear to me what the connection is between HATEOAS and Tailwind.
FWIW, for the app I’m working on currently, I’m outsourcing most of my styles to Bootstrap, while pushing hard for progressive enhancement via CSS hacks (for effects like expanding/collapsing menus and switching tabs). I’m using htmx when JS is enabled, and regular HTTP for when it’s disabled (the Django back-end renders partial or full pages based on request type). Bootstrap and htmx don’t really step on each other’s toes, and I don’t see why htmx + Tailwind to be different.
I use Tailwind at work daily and I still believe it is a crutch for a bad design system. I see pros and cons. If you keep your class count relatively small, you can "see" how the element is going to look if you are good with CSS, and it is incredibly intuitive. On the other hand, when you see blocks with 20+ classes, just like some examples posted here, they are hideous and all the readability goes down the drain, I take this should be made up for with the use of components and limiting copy pasting.
Also I don't think you have to use either Tailwind or more classical approaches, in fact I like mixing both. During a rush a couple of years ago my team had to give a more up to date look to mane features in our app and, provided you have a strong component system, those touch ups were mostly related to positioning and sizing, and that represents 99% of our usage of Tailwind.
Looks like a lot of great improvements, but wanted to put in one vote in favor of keeping the capability of having a JavaScript-forward configuration/usage approach, rather than requiring a CSS-forward approach.
For us, one big benefit of using Tailwind has been that we can avoid spending a lot of time thinking about CSS and CSS tooling, and being able to configure everything via JS has helped in that regard.
That's exactly why critics of Tailwind (like myself) have been so frustrated…Tailwind shouldn't mean you avoid spending time "thinking about CSS". CSS should be a principal and respected pillar of a website's architecture, every bit as vitally important to reason about and understand as anything JS-related. Tailwind v4 promoting CSS-first configuration and customization, and allowing design token usage in vanilla CSS, knocks down a major complaint we've had regarding the framework.
I was excited to use this in my Demo project, but `import from "node:@tailwindcss/postcss@latest"` throws error about the `exports` field in package.json.
With that aside, the blog post mentions not having to use `postcss-import` but it seems to include that as dependency. So we're still using `postcss-import`.
The docs are great and they also happen to be a kind of "CSS: The Good Parts." What sort of questions do you need answered? For the most part you just make components and put styles on them.
Right now I have the feeling when using tailwind the html code becomes unreadable cluttered with classes. So abstraction of components is king? Maybe I'm just overthinking it.
Yeah, I would say using components (rather than classes with @apply, as another commenter said) is the main thing. The class clutter is then contained to that component. You make some components and then in most of your code there are only a few classes here and there.
I thought styled components solved this issue pretty well. Your markup (JSX) is composable, and so is its styling (styled components with raw CSS or object syntax).
Unfortunately, many developers using styled components don't realize the power of their composability, and end up just writing one level deep for each component. But in fact you can wrap styled components and compose them together...
Styled components are no different than Tailwind in this regard, and this is precisely how Tailwind is meant to be used. You define a component and use that.
If an org can't organise its workflow (name things) and adopt external organisation (magic bullet frameworks), the org will always have poor organisation in the long term.
I honestly can't tell whether this is meant to be for or against Tailwind. Is Tailwind a utility for organizing your workflow or a magic bullet framework?
We considered it but it felt too magical to make any CSS variable under `:root` automatically drive the existence of utility classes. Putting things under a custom at-rule like `@theme` makes that opt-in, because we know anything you put there is actually intended to drive your utility classes.
I find it's often easier/cleaner to just pop a CSS file in for some of these foundational components that have tons of variations. Can use nested CSS now, and the selectors are easier to to work with IMHO and take care of specificity.
You could use the !important variants for overrides instead of merge. In v4, the tailwind team has already said they want to introduce a solution to solve this problem without tools like tw-merge. I’m guessing it will be some sort of modifier that is placed at a lower specificity if you know that you are authoring something that will be overridden later.
This is not a complaint. But as someone who uses AI heavily for tailwind, I found that GPT-4 couldn't update the syntax even after the cutoff is updated. Likely it gives equal weightage to documents regardless of the date. And even with 2023 cutoff it just can't work with new syntax of many libraries I tried.
I had hopes with google in this as they already likely have things like official docs, updation etc labelled so they can give different weights to every document. But then there is Gemini.
Not having to come up with names for CSS classes, no duplicated CSS code, no fighting conflicting classes, everything in one file, being able to visualize a component just by reading the code... it's a godsend. I'll never go back to SCSS unless work obliges me.
Vue 3 with <script setup lang="ts">, TailwindCSS and Vite. The way God intended.