An opinionated defence of hand-crafted CSS in a utility-class world
There. I said it. Call me a dinosaur. Call me a purist. Tell me I'm fightin...
For further actions, you may consider blocking this person and/or reporting abuse
Fascinating post, I can’t get it out of my head 🙂 I was going to leave a detailed comment, but I think I might end up writing a whole post about this next week 😄
Respect for both of you keeping it civil and providing your opinion to why you like/dislike Tailwind lol.
Also, @freshcaffeine, thanks for sharing your opinion on Tailwind. Good post :)
I totally agreed your point of view. If someone have time to make a real good hand writed CSS then that is respectfull way.
I feel like I'm always driving in the opposite direction on the highway. I'm the same way with Tailwind. I mean, I started using it right when I started going in a no build, handmade HTML direction, and that meant that the only thing I learned to write down by heart was the Tailwind CDN link. I did this because I use Tailwind for layout design by default. I find it practical because I just look at the code and I can immediately see what layout / responsibility rules the given structure works according to.
E.g. grid gap-2 is the vertical list, flex gap-2 horizontal list. If I really need to make a more complex tailiwind class, I write them not one after the other but one below the other, so that the idea is more readable.
Here's a bad example of using tailwind and a handwritten program:
dev.to/pengeszikra/chuck-norris-to...
However, Tailwind also has its limits (before the 3rd, anyway) because 3D CSS rendering wasn't possible for it at the time. Here's this 3D card game where the 3D engine is actually implemented with CSS, and I think it works quite nicely:
dev.to/pengeszikra/javascript-grea...
That 3D Card game is really neat! Thanks for sharing!
Thx for mention Kevin Powell I was watch a few videos of them and each is very great and imortant like this one:
Highly recommended for every one.
My analogy might be more like, "CSS is making a pumpkin pie from scratch. Tailwind is buying a pie kit that's pumped full of colours and preservatives".
I don't have much of a concern that people are losing the ability to craft CSS. I mean, that's probably happening, but it doesn't matter in the grand scheme. What we want is easily-maintainable, developer- and user-friendly, accessibility- and structure-promoting code. Eventually in the fullness of LLM time, this will probably all become some declarative, "make page brown with pretty sparkly words" anyway, right?
Tailwind reinvents things and makes every single one of those things worse. It just does. Try making a component that will look beautiful in a sidebar or a header without passing that information to it via props to update the HTML, or falling back on a custom class - a practice that Tailwind specifically says to avoid.
Try having an alternate theme for a holiday celebration. Try tracking down a bug while avoiding all the extra magic TW runs at build time. Tear your hair out.
I've been commenting over on I love Tailwind... as well. I agree with both of you for most of the salient points but still end up on, "Tailwind is a massive red flag for me".
Since when was Tailwind an either-or proposition? You use it when it makes sense, which is a lot of the time, especially when working with languages that support template partials/components. When you have something that isn't supported or is so custom it makes sense to, you write custom CSS. Tailwind makes it a breeze to incorporate that customisation into your Tailwind build so that it feels part of it.
To take your analogy on: Tailwind is like having a Michelin-Star chef working in your kitchen. If you want top quality pies, you can have them by the dozen. If you want something a bit different, we'll the chef can accommodate that.
If I had a Michelin-Star chef working in my kitchen, and I was presented a pie made from pre-baked crust. They'd be fired on the spot!
Ah, but did you make the chef milk the cow, so he could make the butter, so he could make the pastry? If not, why not?
Thats a bit far - I would certainly expect the butter to be very high quality, from locally produced grass-fed Jersey cattle.
Assembly libraries existed for years, the biggest are Bootstrap and Foundation.
The difference between those libraries and Tailwind is that they are not seen as a base.
People are treating Tailwind as a base to build other libraries on top of, shadcn/ui is the most known example. Shadcn/ui is more closely related to Bootstrap and Foundation than Tailwind.
The large team argument is a false one. When you don't want ambiguity you build a design system.
Yes there will be discussions, but do you think everyone is using Tailwind the same way?
When people are sure they are right they are going to find a way to break out of the box.
And when people in your company create a design system you can actually talk to them about your ideas. With Tailwind there is more distance because they need to think about the whole world using their library.
I think Tailwind should not be used as a base. Use it how the classes are meant to be used, as a utility. There is nothing wrong with that concept. When you have outliers in your design they shouldn't become part of the base.
When I look through pumpkin pie glasses, Tailwind is not the store bought dough or the pumpkin in a can. It are the replacements of the dough and the pumpkin. You can learn to love the taste of those ingredients, tolerate them up to a certain level, or don't like them.
Writing proper css is way easier than learning tailwind. And if you don’t know about css, how it works behind the curtain how can you use tailwind? What happened to separation of concerns? And your html just turns into a friggin mess, unreadable. Tailwind introduces more problems than it solves imho.
I used to hate CSS, but after fighting with it for years, not understanding why different components never looked right. I have come to love it, and I was easily able to transfer these skills to work with Tailwind and customise components to my liking.
I also highly recommend Kevin's videos, as well as works from Jen Kramer or Josh W. Comeau. They simplified a lot of concepts that never would have clicked before.
I totally agree about the clutter! I actually got so frustrated that I started building my own framework to solve exactly this. Going to be a LONG process, however. My main goal, is instead of having like 50 classes on one element, have less than 5. And not code random things that many will not use often.
The strongest argument here isn't aesthetic — it's that CSS is one of the most stable skills in web dev (selectors I wrote 15 years ago still work) while we've cycled through Bootstrap → BEM → CSS-in-JS → Tailwind in the same window. Every dev whose mental model is the framework instead of the language has had to re-learn fundamentals every cycle. The ones who learned CSS just kept shipping.
It's great for prototypes or internal apps you want quick turnaround on but that markup noise and lack of logical semantics in your UI is a detractor for me.
I totally agree with you. The HTML mess that it produces is enough for me to not use it. I always liked writing CSS(long time ago SCSS) but now vanilla CSS is all you need.
Ahh yes - with CSS Nesting and CSS Variables now passing 95% coverage there is little need for SCSS these days.
Links for the curious...
caniuse.com/css-nesting
caniuse.com/css-variables
@freshcaffeine you might be interested in spicyweb.dev/
The first time I've tried Tailwind, I was excited. It was good.
Until I had to do a very specific thing and just couldn't wrap my head around on how to do it inside this Tailwind spaghetti. After many hours of banging my head against a wall, I've deleted it and started from scratch with own CSS.
I get why Tailwind is everywhere right now - and honestly, I use it in a lot of my projects too. It’s fast, convenient, and for many use cases it just makes sense.
That said, for me personally, nothing really replaces custom CSS. I come from a web design background, and I still prefer working directly with CSS (or SCSS). It simply feels cleaner and more intentional to keep structure (HTML) and styling separated. You end up with code that’s easier to read, reason about, and maintain long-term.
Tailwind absolutely has its place. It speeds things up a lot, especially when you're building layouts or prototyping quickly without constantly jumping between files. That’s a real advantage.
But I do think there’s an important order to things:
First, learn the fundamentals - solid HTML and CSS. Understand how the browser actually renders things, how layout works, how the cascade behaves. Once you have that foundation, tools like Tailwind become much more powerful because you’re not just using them - you understand what they’re doing under the hood.
So yeah - Tailwind is great. But it shouldn’t replace the basics. It should build on them.
This made no sense, tailwindcss allows you to customize everything.
You want to write beautiful hand crafted CSS? you can do that. Tailwindcss made that beautiful CSS maintainable by everyone, no need to visit CSS files to see what you named a class 4 months ago.
Your pumpkin pie analogy is incomplete, because you didn't grow that pumpkin you bought it from a store.
Writing handcrafted CSS is growing a pumpkin not lazily buying one from a store.
No, instead I need to find the component in spider-code of HTML markup that has a utility class incorrectly applied to the wrong element. All you've done is shift the problem to the markup and made the component a lot less reusable. Meanwhile - the 'C' in CSS is almost meaningless.
With tailwindcss, at least I know updating a component class won't affect a component in /settings/user/app/upload/spyware
I was using raw CSS for the better part of 2024, wasted so much time for the reward not to meet up.
Imagine not having to open a separate file for the CSS. Suddenly the tailwind crutch is not so appealing. Just leave React behind.
I was anti tailwindcss until it took me over 3 months to make a website, something I would usually do in under 2 months.
Using raw CSS just waste you and everyone's time.
Your point about Tailwind being "utility classes in HTML" resonates. It trades CSS complexity for HTML verbosity and at scale, those class strings become just as unreadable as the CSS they replaced.
The sweet spot is using it as a foundation for component libraries (DaisyUI, Shadcn), not writing
class="mt-4 px-6 py-2 bg-blue-500 hover:bg-blue-700 text-white font-bold rounded"directly in every template. The abstraction layer matters, same principle as software architecture: build on top of primitives, don't scatter them everywhere.I get your point there’s real value in mastering CSS as a craft, not just assembling utilities. Tailwind is great for speed and consistency, but it can hide the deeper understanding that makes layouts truly flexible and intentional.
At the end of the day, it feels less like “one vs the other” and more about knowing when to use tools and when to rely on pure CSS skill
Okay, I say this as a crusty old developer.. a curmudgeon if you will. covered with barnacles and smelling of old fish. That being said, you cannot bust me down much lower than that without violating some kind of community standards. I have to stand up for the libraries of the developer toolboxes that help us all in our moments of weakness. I agree with you that Tailwind is bad. It is. And it's React library doesn't even have a 'card' component. Why? I don't know. But, I do know this, it will never go away. It's being utilized everywhere, it has a fan base larger than Nickleback. (as much as everyone claims to hate Nickleback, they still sing Photograph when it comes on the radio) It's here to stay, to many peoples dismay. But it has spawned DaisyUI, better extensions of itself.. and it's integrated into AI site development now. The sadness that AI (now with IQs higher than most doctors) must be chained to it, and is now frozen for meaningful improvement is a tragedy. I think Figma uses it... Owned by Adobe now.. (drumbeat php... ugh.. the tragedy. At least if Microsoft bought it, at least it would be killed like the phone was)
But can we be mad at all libraries? I came up through the likes of VB Extras (Miss ya Matt, if you ever read this) So much of the development community has used libraries and components this whole time. The point I am making is that I remember when CSS was not worth it's salt in HTML, and it became something bigger than it should have been. It's a style sheet. I remember when browsers wouldn't agree on which code to use for them, so you needed javascript libraries to figure out how to display it. So standards came out. Then libraries, then best practices, and now Tailwind has the conch because it won the popularity contest.
Now the world has emerging classless frameworks, JavaScript Style Sheets, XSL-FO, ELM-UI, and new alternatives are being birthed as we speak. Style is the new USB-C.. I can only wait for XKCD to do another comic on it. As we sit here right now, a 12 year old child is sitting behind his computer, bewildered at Tailwind and the spaghetti code, and will use AI to invent a new system of layout management, color picking, and text placement.. and it will slowly grow to replace CSS as 90% of developers know it.. and we will be the dinosaurs yet again, like moving from ASP pages...or never giving up on PHP no matter how many times it should have died (I can't believe perl is still relevant). But we got through it all with TailWind, Bootstrap, and any other standard library.
You have to agree, it's a necessary evil, simply because the world is always going to be moving faster than we will learn. I have a 1962 Studebaker that I work on... and old wood working equipment that I build tables and cutting boards with. I love the methodical nature of it, the same as you love hand crafting CSS.. but CSS will continue to get more complex, or it will get replaced with functions and backend automation libraries, or AI will keep track of it all, and eventually be out of your control on the front end. And then what?
You can't hang onto the past, we'll all succumb to automation, libraries and Tailwind or something. The only way to hang onto the past is to mondernize it back into relevancy, which means, no more beautifully crafted masterpieces of single site CSS sheets.. except for the one you keep on a computer in the garage under a blanket, you've never upgraded past the last version of firefox that still supported it, just like my Studebaker that still runs best on leaded gas.
Say it with me. Tailwind is Dead.. Long live Tailwind.
Make sure you tag me on your Tailwind replacement project on Github. Make it fully compatible with all the browsers, and make sure that it has a markdow viewer, next to the layout for phones, desktops, printers, tablets and mobile phones... I think AI will be paying more attention to it than people. It is the way of the future these days.
I've long felt this way. Besides, I want pages to load fast. Adding bulk defeats that. I can do the same stuff with Bootstrap (and I use 4 right now to accommodate older browsers) and some custom CSS in far less bytes than Tailwind. Tailwind creates gobs of HTML class clutter.
And while I'm on this, let's talk about React too. I'm not a fan because it has "code stink" and doesn't follow "separation of concerns". If I can make a single language that mixes CSS, HTML, and Typescript in a single file -- that's nuts. And React isn't SEO-friendly -- it's actually better to use React for internal company apps or for large SaaS systems you login to and use. Instead, I use Bootstrap 4, CSS, and jQuery -- fight me. I can do bada** stuff with it just like React coders can do. Besides, I have "React fatigue" -- aren't you tired of going to a client-side React page and having to wait after the throbbing finishes for the page code to download so that you can actually use the page?? But with Bootstrap 4, CSS, and jQuery -- BAM! The page downloads and I can start using it right away without the throb.
Im sorry to say that you lost me at jQuery. jQuery was great a making a consistent interface for javascript and filling in gaps with css - but that time passed with MS killed off InternetExplorer and Edge adopted chromium.
You can do everything you need to in jQuery with vanilla JavaScript and some very simple css
Agreed. Never have. While I see where it can be valuable, the idea that I have to integrate a build step just for stylesheets in this day and age seems so strange. It always struck me as an intermediate point on the learning curve--I could see folks finding it useful (and good for them!) while they're learning CSS. But I've been doing this for so long the idea of adding another layer of abstraction instead of just coding the classes etc. with the modern rules directly feels like a poor part of the stack to spend your valuable complexity risk.
I always disagreed with the tailwind philosophy. I started before CSS existed, but this is what the CSS people promised and I was sold on... CSS Zen Garden where the HTML is very simple and clear and the CSS makes it come alive on the page... We really never got to this, but it was the grand idea.
I hated Tailwind from the beginning. I find it much more confusing to read 25 utility classes instead of one class and the CSS that comes with it. It's all React's fault, because they weren't able to encapsulate the CSS that belongs to a component properly ...
I believe this article misses a key perspective. While I share a love for CSS, Tailwind’s value in modern development is undeniable.
We use it primarily for component-based development because it solves two major hurdles: speed and maintainability. By keeping styles within the markup, we eliminate the mental context switch and solve the "dead code" problem; when a component is deleted, its styles are gone too, preventing the CSS bloat common in traditional stylesheets.
Regarding your analogy: Tailwind isn't like using canned ingredients; it’s like having a professional, pre-organized kitchen. It provides design constraints that prevent "magic numbers" and ensure visual harmony, but it still requires a deep understanding of CSS to use effectively.
It isn't a replacement for the craft; it's a modern toolset that helps us scale that craft without the maintenance overhead.
Having said that. The "dependency" issue is a real concern. But this is the same problem as using React or any other component-based UI library. We have to be aware of it and always keep an eye on where the industry is moving.
team CSS consistency scales better with utility classes. your beautiful hand-crafted code becomes someone else's unmaintainable mystery in 6 months.