Let's say things how they are: Tailwind is a small catastrophe from an implementation, performance and maintenance point of views.
It got few things quite well in being a more modern bootstrap, had a stellar marketing and it's color palettes are really well done and leagues above the default material ones.
...that being said...
Tailwind's biggest pro is that it allows people that _don't_ know css that much to style stuff more consistently and easily. But that's where it ends.
Sadly there's a lot of issues when it comes to maintenance. Any small update in tailwind will break your application. !important s are shoved pretty everywhere, they will unavoidably clash, prompt you to override even more styles.
There's yet another complication with tailwind: the moment you want to do something more complex with tailwind or that it clashes with its own styles/rules you're in a bad corner where you need to know bot advanced css AND tailwind.
I know CSS very well and Tailwind is probably the largest productivity boost I’ve encountered since, I don’t know, learning vim? It’s way faster than SASS/SCSS which is itself way faster than raw CSS.
It also yields far more self-contained and more readily composable components than any other styling mechanism.
Your comment doesn’t resonate with my experience at all.
What is the value of reimplementing a bunch of this if it already exists? What's the value of having every developer learn some poorly-documented in-house system when we can use one that's already out there with full documentation, examples, references on StackOverflow, etc?
And to top it off, nothing guarantees your colleagues are actually going to use those instead of creating their own ad hoc “semantic CSS” or whatever their preference is.
If you decide you’re a utility-only frontend, then… there’s a great tool for that!
So now why on earth are you still plugging away at that utils.css?
I've been doing web dev since I was a kid in mid 2000's and I think tailwind is phenomenal in enforcing style, portability, speed, etc. I recently started to writing a single .html file proof of concept for something and it was shocking how poor the experience is of `style="..."` is in comparison, or making up classes as you go.
Tailwind finally throws in the towel on all of that and just brings the full functionality of CSS to inline styles and leaves reusability up to whatever framework and templating you're using on top of HTML/CSS.
When I walk into a project using Tailwind I spend way more time actually working on _the project_ and way less time looking at the browser devtools trying to disentangle and chase down the complex web of interacting styles that are somehow working on the markup. Everything I need to know is already in front of my face directly attached to whatever element it's related to.
It is another thing to learn but it's pretty darn straightforward and well documented. Coming from a solid CSS background it took in the manner of hours before it clicked in my head and I was productive. And that largely translates to whatever project I'm digging in to instead of having to spend a bunch of time learning each project's bespoke styling system.
Tailwind is way less technically elegant than CSS, but the technical elegance of CSS has always seemed more lofty and academic than anything.
If you understand CSS well and you’re using TW, you will ~never have to go chase down some crazy style cascade via the inspector.
No amount of understanding CSS can save you from that in a complex CSS/SCSS codebase, because it’s how CSS is meant to be used.
Maybe I just suck at CSS. I mean, I've been using it for decades, but maybe I'm too stupid to actually understand it. And maybe it's the same story for everyone else I've ever worked with and that's why my experience with it has never lived up to the ideals.
... but if that's the case then at this stage of my career, with vast and varied accomplishments behind me, I think that says more about CSS than about me.
I find tailwind just makes my life easier. Sure, it's not perfect, but I really don't enjoy giving every div and container it's own unique name and hoping none of the names ever clash with my colleagues unique names etc.
Also, I came to realise that websites never strictly follow the same design rules throughout. There are always exceptions. So you are constantly creating new style classes that are slight modifications of others. And keeping this all in your head is not easy.
I know a lot of people disagree and feel like tailwind is a problem, but for me I can just concentrate on making a great site rather than worrying about how a slight change to the styles inside .container might break some obscure part of my website.
Are tons of divs and containers needed? When I find myself needing containers I usually find out I've not been thinking about arrangement very well.
If for example Figma offered first-class support for Tailwind-like utility classes in the form of a modernised "styles" or "composite tokens" feature, then mapping from a design system to Tailwind-based code could be pretty simple.
But right now, it's anything but. In my experience, designers simply aren't aware of the Tailwind structure, and it's hell trying to map their mental model onto Tailwind. Figma is built to design things that map easily to CSS at the attribute level, not the class level.
"How is any of that unique to burgers? You should be eating tacos which are also delicious and greasy and salty."
Ummm okay...?
Elsewhere in the thread you're basically advocating for copy/pasting parts of Tailwind to get the benefits you care about in the moment, then I suppose copy/paste more of it when you run into another case it'd be useful for. One easy way to save time with that strategy is just to copy/paste all of Tailwind. Then if you're doing that, an easy way to save time is just run `yarn add tailwindcss`.
The biggest pro for Tailwind is that it is exceptionally well designed. Aside from adding one single custom style to the Tailwind configuration, I have not needed to venture outside of the system it provides despite writing many bespoke components.
But i sincerely do not understand the performance one. If anything tailwind approach is mostly really good for performance, as rendering utility class directly on the element is still the fastest, by far, technique.
The only slight call here could be shadow dom scoped but that necessitate declarative shadow dom and create a lot of problem for performance until we get a fetch maps equivalent to import maps.
What have I missed?
1. Tailwind allows you to not learn CSS (not even remotely true)
2. Tailwind is hard to move away from (what?!)
3. Tailwind has performance issues (lol)I'm considering advocating for a move to TW at work. Most of the devs _don't_ know CSS well enough to style stuff consistently and easily. We have very complicated cascades, and sibling style imports, and "semantic" class names.
Sure, maybe the answer is "level up your teams' CSS expertise." But I'm looking for something more pragmatic than that. I don't know if TW is ultimately the right tool I'm looking for, but the underlying ideas it uses are very appealing for this use case.
I have never understood this claim. You need a good understanding of CSS to use Tailwind effectively because it is CSS.
It’s not an alternative technology, it’s essentially just an alternative syntax—one that naturally leads away from footguns that many teams end up battling, like fragile CSS that everyone is scared to change.
You could just as easily define the utility classes yourself every time you need one, it’d just be a lot more work.
You don't need it. Do devs these days even know about Web Components and shadow DOM? You can define per-component styles now with CSS selectors to target any child elements within the component and you can do it in such a way that the styles are contained within the component... And for cases where you want to inherit styles, you can just use the regular light DOM.
All these frameworks are re-inventing the wheel and making it worse. Or it's like attaching a horse to pull a perfectly good car.
I think unless there are massive improvements to the developer experience the best hope for web components is as an implementation detail for a higher-level framework.
For me, I've been bitten and I would pick web components over a fixed framework for a clean sheet project. I don't think many devs have really tried to work with web components or they might get the bug, too!
PS: I wrote an intro series on this topic on Medium[0].
[0] https://medium.com/gitconnected/getting-started-with-web-com...
That said, having taught some introductory web development courses in the past few years, I sense that new devs entering the industry are interested in simpler solutions and not particularly keen to get into React. The React learning curve is much steeper than it once was now that it has so meany features and the benefits are not so clear to someone who is starting from scratch.
You all fight, but nobody says what exactly they develop. A webpage and Tailwind is absolutely fun. An app with reusable complex components, Tailwind is a pain. Themes, dynamic tailwind is a pain, static, tailwind is ok.
There are endless possibilities. The problem is, that some people think you can use Tailwind for everything and then they made simple things unnecessary complicated.
For static webpages (unless it is assembled by a static blog engine or something), I don't particularly enjoy it, because of the repetition.
With components+Tailwind you have as much duplication as you'd have with pure BEM.
All personal experience and opinion, of course.
I remember this being endorsed approached by Tailwind creator.
No complaints.
Thank you.
Slash
Ess
Am I more clear now?
The sad part is i don't even feel guilty for assuming, because this area of programming has a well deserved reputation.
Even if this thing doesn't use javascript, can you guarantee the generated CSS doesn't put the browser's layout engine in an infinite loop or something? Especially without knowing CSS, like the OP suggested it's normal?
Nope
the way TW aproximatively works is to collect a set of used class names from your code (e.g. flex, min-h-screen, bg-[url(/img/grid.svg)], absolute, etc.) and produce the CSS for those classes.
For the random 5 classes above it would produce:
.absolute{
position: absolute
}
.flex{
display: flex
}
.min-h-screen{
min-height: 100vh
}
.bg-\[url\(\/img\/grid\.svg\)\]{
background-image: url(/img/grid.svg)
}
By default TW also includes a CSS reset preamble and defines internal variables.Sometimes the generated css contains complex selectors but as far as I know it is not a common occurrence
.space-y-4 > :not([hidden]) ~ :not([hidden]){
--tw-space-y-reverse: 0;
margin-top: calc(1rem * calc(1 - var(--tw-space-y-reverse)));
margin-bottom: calc(1rem * var(--tw-space-y-reverse))
}
In other cases more css variables (custom properties defined in the preamble) are used .-translate-y-1\/2{
--tw-translate-y: -50%;
transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))
}
.shadow-xl{
--tw-shadow: 0 20px 25px -5px rgb(0 0 0 / 0.1), 0 8px 10px -6px rgb(0 0 0 / 0.1);
--tw-shadow-colored: 0 20px 25px -5px var(--tw-shadow-color), 0 8px 10px -6px var(--tw-shadow-color);
box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow)
}
I believe that CSS performance is mostly dominated by size in bytes of the stylesheet, number of properties, complexity of selectors, and frequency of updates. I suspect that TW improves most of these metrics in exchange of bigger html class attributes.Edit for the downvoters who don’t know how it works: there’s zero js being run at runtime, it’s a pure css framework that generates as-minimal-as-possible css files. And it’s not class lookups that cause whatever issues parent comment is talking about.
In that regard it is pretty similar to Sass.
The main effect on performance likely are bigger html documents (which can be optimized) and simpler CSS selectors.
In real world usage I would honestly guess that using simpler css selector (with far fewer propagating updates) is a net performance win.
(It was one of the showstopper for the :has pseudoclass, for a long time nobody knew of a way to implement it efficiently)
ultimately what is cheap and fast wins. the future is someone else's problem.
i think that's a good description for javascript too.
Tailwind maps onto CSS in a very straightforward way. I think you'd have to go out of your way to "learn Tailwind" without also improving your knowledge of CSS.
I think I understand tailwind, but like the parent poster I'm really not a fan, because while CSS can be a footgun, it can also be quite clean when you use a sane DOM structure, CSS variables, and well thought out CSS selectors.
This fall apart pretty quickly as soon as more developers join the project. Keeping consistency between multiple team members is hard without a reference point, which is what a framework like Tailwind provides.
In practice, they don't end up "quite clean" outside small personal projects.
i’ve yet to witness a project without “!important” scattered throughout the codebase.
Simplicity is a skill and it's hard to do. There's a reason most people are not minimalists despite the almost universal western desire to "have less stuff".
Since I graduated university, I haven't worked with anyone who I would trust to achieve one of these three things, let alone all 3. I don't think any of my ~10 coworkers even know what a CSS selector is (they may know how to use the basic three but don't know them as CSS selectors).
I've yet to see a single project that doesn't fail on all three.
Truth is I've been spoiled on that front because I had the luck to work for many year in a company where the CTO was a very talented dude who lived and breathed HTML/CSS since the mid-2000's, and who was quite thoughtful about that kind of stuff, so I had a first-hand experience of a good codebase, mostly by avoiding external dependencies, using the standard browser behavior, and frequently consulting the MDN.
This is why it's a bit disheartening to see so many front-end framework working against the plateform, even even marketing against it, while CSS and browser tooling his so much more enjoyable and powerful than before.
Technology that makes it easier to make bad decisions than good decisions is not a good technology.
> This is why it's a bit disheartening to see so many front-end framework working against the plateform, even even marketing against it
None of the frameworks I know of do that.
I believe it's mostly due to the fact that CSS, just like SQL, is one of those technology approachable enough to fiddle with it and get somewhat far, while not really learning it, and thus overlooking the fundamentals.
> None of the frameworks I know of do that.
I would squarely put into this category all the CSS-in-JS frameworks, such as 'styled components'. Also everything that markets the 'cascading' part of CSS as being a mistake.
Also, all the frameworks that compiles CSS without generating the CSS sourcemaps, making the debugging experience way less efficient since all the applied CSS rules shows under '<style>' (eg: 'styled-components' again, who discarded it as being 'cosmetic' in the related Github issue).
Tailwind creates "stylesets", and is absolutely powerless to apply them. Quite like WYSIWYG text editors. So, yeah, anybody claiming you are learning CSS by using it doesn't really know CSS. But I disagree, that kind of thing can be useful on certain contexts.
1. You need to know CSS to use Tailwind
2. I learned and understood quite a few of things I rarely use thanks to Tailwind's amazing docs. Docs that are non-existent for CSS
3. I'm reasonably good with CSS, but I could never come up with a consistent and minimal design system that Tailwind offers
That said, to things everyone should read to up their CSS game is Every Layout https://every-layout.dev/ and Inclusive Components https://book.inclusive-components.design/
This argument boils down to: “But you don’t need Tailwind for that. You can do more work for a (almost certainly) worse result with a designsystem.css!” Sure you can! Why?
If you really want to, you can even use Tailwind's naming for you language file. The thing is, you add complexity to do a job that could be done in the same way without adding complexity and dependencies.
Shouldn't we try to justify added complexity through added value?
Because most frontend engineers cannot make something as visually appealing as Tailwind’s defaults and most designers cannot make frontend abstractions as ergonomic as Tailwind’s.
Now it seems like you’re suggesting just reimplementing Tailwind? Or yes you can have one of your FE engineers and one designer try to dream up your own Tailwind but again: why? Now you’re consuming two people for something that can be achieved by literally zero people and “yarn add tailwind.”
It is not at all my objective to “reduce complexity” that sits behind good abstractions. My goal is to ship product and to put as much complexity as possible behind good abstractions and ideally out of my team’s maintenance burden and Tailwind helps achieve all of those.
Sure, if Tailwind provided literally zero value I would say you shouldn’t add it to the codebase. But it provides a huge amount of time-value (the best kind!) in my experience, so “there’s a package from the internet” is hardly a consideration whatsoever.
Side benefits include that there is then no need to update any dependencies or library, no need to run a JIT server, no need for a new syntax, no need to wait for implementation of new CSS features, better performance possibilities, etc.
Or are you saying take their design system and use your own syntax for it (so it’s less complete than TW, less well-documented, and less transferable to/from the vast resources of the internet centered around TW)?
"blue-500" becomes --blue-500. That's it.
This is a far cry from using Tailwind as a whole while keeping the good-looking aesthetics.
Of course it's not "it".
Now in every class that needs it, you also need to add
{
... other styles...
background-color: var(--blue-500);
}
And then you need to apply that classAs for the class, it's the name of the component, the same name you give to the component file. Does it really add that much work?
Correct me if I'm wrong but as I see it, that's literally a couple of seconds of "work".
Or just use the extremely complete, well-considered, well-defaulted, well-documented, well-supported, always-improving set of classes that took you zero hours of initial setup and will cost you zero hours of maintenance outside of your own use/application until the end of time. And it has a name so when a new engineer joins your team, you can say "we use Tailwind, go to tailwindcss.com" and they are fully read into your setup in about 15 seconds.
And the IDE will help you autocomplete it all. The same is true for all the other properties you enumerated. If it's a Tailwind design token, it can be a pure CSS design token. No "whack-a-mole" needed here.
Still, you're right about having documentation. And there has been a loooot of these kinds of doc (BEM, SMACSS, ITCSS, etc.) in the last 15 years. Nonetheless, a more modern-oriented one is indeed needed. And that's why I'm working on something like this.
As for the "15 seconds", I mean, really? If so, I beg to disagree. There is a lot to take in. And that is why numerous colleagues still have to open the Tailwind docs to know how to write a class that's not 1:1 CSS.
And lucky you if you haven't had any update and dependency issues in the medium to long term. But I know we had.
> Or just use the extremely complete, well-considered, well-defaulted, well-documented, well-supported, always-improving set "of CSS features".
The sentence above is every bit as true as yours. Add a beautiful design language and you are in business.
not 20 minutes, more. Plus all the boilerplate around @media rules
> no need to wait for implementation of new CSS features
What CSS features are you waiting for with Tailwind?
> better performance possibilities
It's very hard to beat Tailwind's performance since it's a fixed set of css classes (and a very small set in production, since it only includes classes you actually use".
Any IDE can autocomplete 90% of any media query. And, on a sidenote, I was only talking about using Tailwind's default aesthetics in pure CSS, here. That's what the 20 minutes refers to. And I think it was a conservative estimate.
As for features, it took months before grid was included in Tailwind. New powerful and useful selectors aren't there. It took years for Tailwind to support "group hovers". And I can give even more examples if you're still not convinced. Or you can have a look at the changelog.
As for performance, can Tailwind split its compiled CSS so that only rules used in the displayed components are loaded? And that's not even considering the weight difference between the "tailwinded" HTML and the one needed to support pure CSS. These things matter if performance is a goal (as it should be).
If I'm missing something, go ahead and tell me, I'll be reading with great interest!
And, as I'm sure you know, milliseconds are important in our craft. You can easily shave or add hundreds of milliseconds with HTML or CSS.
And to be honest, I find your general line of inquiry here to be quite agressive and dismissive. I think, respectfully, a little more good faith could further our understanding of each other.
Outside of consumer apps I am struggling to imagine a case where the HTML/CSS perf delta would be more important to capture than faster development time. I suppose part of why that doesn't seem like a good faith question is because you don't believe Tailwind dev time to be faster, so the tradeoff that I'm trying to evaluate is totally inane.
As for the case in point, in fact, I think CSS can be as fast if not faster. But that's totally for me to prove. Hehe.
That's why I'm working on a set of simple rules for efficient styling with CSS. A website with documentation, examples and tools is in the works. If you're interested, I can give you a heads up when it's online.
Feedback from Tailwind users is important and would absolutely be welcomed!
PS: thank you for the explanation.
:root {
--gap-default: 2rem;
--gap-large: 4rem;
... 30-40 more vars ...
}
.component1 {
margin: var(--gap-default);
padding: 0 var(--gap-large);
... more styles like this ...
}
@media (min-width: 640px) {
.component1 {
padding: 0 var(--gap-default);
}
}
@media (min-width: 768px) {
.component1 {
... other overrides
}
}
/* potentially repeat for other breakpoints ...*/
/* repeat for all components */
/* repeat for some internals of some components */
There's a also a good (if contrived) example directly at Tailwind: https://tailwindcss.com/docs/utility-first> As for features, it took months before grid was included in Tailwind. New powerful and useful selectors aren't there.
No one stops you from using whatever CSS you need alongside with Tailwind. I do that for the excellent layout breakout I found here: https://ryanmulligan.dev/blog/layout-breakouts/
Can't see how this makes Tailwind "ant-CSS".
> As for performance, can Tailwind split its compiled CSS so that only rules used in the displayed components are loaded?
Tradeoffs.
Most existing solutions can't even detect duplicated CSS. So if your existing component already has `width: var(--some-var)`, and you load a different component with the same style... You will still load that style hidden in a different (often auto-generated unique) class name.
Meanwhile with Tailwind has a fixed number of classes that apply to all components equally.
So, if you have a complex app with multiple component variations, of course you'll need to split your CSS and only load relevant CSS for displayed components. Because your CSS grows with the amount of variations, and each of those variations becomes its own unique class.
For Tailwind though that growth slows almost immediately because... it's just a fixed set of classes.
Here are my thoughts:
In your code example, all that is in :root should be used from project to project. As it is Tailwind. Only values should change. Again, same as Tailwind. So I don't really see a problem.
For .component1, you would do the same in Tailwind albeit with fewer characters but as I said, your IDE should pick up the slack here.
mb<tab> --gap<tab> and it is done.
As for your duplicate width problem, it can be solved easily with a linter that prevents styling across files. I'll give you an example if you're interested. At the same time, you would be repeating "width" across components in Tailwind too.
So the duplication still exists, if I understand correctly. Same with the growth of CSS... In Tailwind you grow the HTML instead. Fixed clases or not. I don't see how it is better but, again, maybe I'm missing something.
As for the media queries, same as above: your IDE should pick up the slack.
BUT!
The thing is that by writing modern CSS, you would not need most of these media queries! Do you know "clamp()[1]"? It's magical
And unfortunately not supported in Tailwind at the moment
.component1 { clamp(var(--gap-default), 1vw, var(--gap-large)) }
the above will do what you want without media queries! clamp() solves a loooot of these use cases. Honestly I don't write much media queries anymore and yes, that's great.
And if I may, I think Tailwind here prevents you from thinking about better and simpler solutions like this one. If it ain't included in what you're using, it's normal to not think about it. But really, this is a game changer. And it's been available for certainly three years. That's a lot.
And in the end, I'd say using real CSS with Tailwind kind of defeats the purpose. You end up with different styling methods for different components. I don't think that's good. More like a "hack".
But really, your example above is right on point: by excluding new approaches, Tailwind disincentivize you from using them when they would solve many of your problems elegantly and simply.
[1] https://developer.mozilla.org/en-US/docs/Web/CSS/clamp
edit: the Tailwind example provided is bad CSS. As were the ones given in the first fundamental post by Mr Wathan. These are strawmen. If you're interested, I'll give you an example of good CSS producing the same output.
By the 30th variable I stopped. The fact that I had to write significantly more boilerplate in CSS classes on top of that, helped me stop, too
Meanwhile in Tailwind everything is grouped together, can be searched quickly and acts both as quick docs [1] and as quick reference [2].
I personally have become proficient with flexbox by playing with Tailwind classes.
[1] E.g. layouts https://tailwindcss.com/docs/display
[2] E.g. all the justify-content values https://tailwindcss.com/docs/justify-content
I thought a person had to be rational to become a developer but oh my, how wrong I was.
This is the paradox of popularity. The theory goes that if you have a large pool of X to select from, then you can select the best of the best, and the quality of your selection will be amazing.
But it's exactly the opposite. Small groups are self-selecting for quality and big groups are self-selecting for quantity. O_O
English, the universal international language. The one we're speaking here, right now. The worst translators in the world are English translators. Everyone feels qualified to speak it and translate it. Finding a good English translator is like looking for a needle in a haystack.
The more "easy languages" and "frameworks" we have, the more "programmers" we also have, and 99.999% of them have the faintest clue what they're doing, but they just keep hitting their keyboard with a hammer, and it compiles and produces interesting results, so they keep doing it.
This is also why social networks have an amazing set of interactions when they're new, and in an old social network you have hundreds of millions of users, but no one writes anything interesting, anyone barely reads, and it's full of scams, bots, clickbait and garbage.
There's safety in numbers, the saying goes. Not at all. If something is universally popular, and you choose to enter it, get ready for a shitstorm.
P.S.: Tailwind is garbage.
I apologize.
I saw a video a few months back featuring a VScode plugin to hide tailwind styles.
If you have to use a plugin to manage your nuclear waste code by hiding most of it something is wrong.
https://marketplace.visualstudio.com/items?itemName=stivo.ta...
In one sense, it was always worse to use Tailwind because if you don't learn "real" CSS you won't be able to fix anything that's broken -- and with CSS, there's always a lot that's broken.
You can't use Tailwind without knowing (quite a lot of) CSS. There's nothing in Tailwind that makes CSS easier or that obfuscates the technical understanding you need to make things with CSS. If you want to make a horizontal flexbox layout knowing "display: flex; flex-direction: row; flex-wrap: wrap;" or "flex flex-row flex-wrap" are functionally identical. You need to know what either the CSS or the Tailwind classes are doing to use them, and there's a one-to-one mapping between them. If you learn one then you know both. It's literally just a shorthand notation, or in a few places the equivalent of a macro.
I don't imagine Tailwind is going to last another 20 years, but I do believe that people will use 'utility first' CSS libraries like it from now on. No one is going back to writing plain CSS unless they have no choice. CSS is becoming increasingly capable, and with that increasing complicated. People choose Tailwind because it affords you all the power of CSS with a somewhat less arcane syntax. Why would anyone stop using that?
I do have a caveat though: I actually think Tailwind is the CSS equivalent of jQuery. In 5 years or so a browser is going to add a Tailwind style notation to its engine, and people will be able to use it without needing an external library. In that sense, yes, Tailwind will die, because browser developers will see the benefit is so significant that they'll adopt it as well.
Today's CSS - if anyone would take the time to actually learn it as they do JavaScript - doesn't need something like Tailwind to make it powerful, scalable and manageable.
I write plain CSS today, which is then scoped to components or bundles of interactivity, and all of those point to major, top-level control sheets that help determine the mode (light/dark/high contrast) and the theme. We tweak small changes up high to effect large platform changes throughout, saving time, energy and headache of the hunt/peck exercise.
I don't understand the statement "no one is going back to writing plain CSS" because plain CSS today _is complex_. It is a beast. But it is still "plain" CSS. Yes, it has evolved, it has grown, and it meets today's modern needs with excellent results.
CSS nesting is coming up soon: https://caniuse.com/css-nesting That will more than likely allow me to migrate any projects I have with Sass still in play, to remove Sass. One more dependency removed. Done.
So there's really no need for Tailwind if you know how to build with modern CSS - with the one caveat that if a project _already_ has Tailwind in it, it is a bear to work with/alongside.
That to me is the biggest con with Tailwind: it gets in your way when you don't need it.
I do similar things with Tailwind, making global changes by updating a config file instead of a base CSS file. It's not hard and it works well. To be honest, it's not something that really comes up very often. I don't see this as a particular advantage of Tailwind or CSS. I care much more about the day-to-day dev experience.
Prior to using Tailwind I spent about 20 years trying every system you can imagine to manage styles across large websites/apps. I still use the skills I learned when Tailwind doesn't cover an edge case I need. It's fine. Before that I spent about 5 years doing the same with tables and font tags (Adobe Pagemill was awesome). Of all the systems I've used, Tailwind is the easiest to keep neat and tidy. Maybe I'm a terrible dev and other people find CSS really easy to manage, but having spent two decades talking about it with other frontend engineers I'm reasonably certain that's not a common skill. Tailwind makes life much easier for most people.
The cascade is where the value of CSS comes from! It’s an incredibly powerful concept.
I use and love the Inverted Triangle CSS (ITCSS) approach and write a fraction of the CSS code I used to.
Having a few utility classes, using variables for project-specific colors, breakpoints, spacing, using fluid typography, grid, and flexbox, make writing well-structured minimal CSS code a pleasure.
https://www.xfive.co/blog/itcss-scalable-maintainable-css-ar...
Tailwind styles cascade just like any other CSS rules. No one is ignoring it. The reason it might appear not to is because Tailwind uses layers (https://developer.mozilla.org/en-US/docs/Web/CSS/@layer). Technically it's a polyfill at the moment, but v4 will use the native @layer syntax.
If anything Tailwind is actually better at using the cascade than most plain CSS approaches.
And if you don’t think it’s reusable then you at least need to bring an argument for why that’s so because the docs, personal anecdote, and the opinion of LOTS of people is completely opposite.
So: - You ARE learning CSS, you’re just putting it where it belongs: on the element it affects - It’s modernity doesn’t matter at all - It’s literally as reusable as raw CSS
I can’t downvote you, but you’re definitely wrong.
So you’re not learning CSS. You’re learning Tailwind specific classnames that expand to non-cascading style rules.
That said, ignoring the cascade is a strength, because the first step in the cascade (css selector specificity) is remarkably complex [0], and can be a source of errors.
[0] https://developer.mozilla.org/en-US/docs/Web/CSS/Specificity
Can you expand? I haven't used Tailwind, but from looking at the docs, it looks like a short-hand syntax for writing inline styles. Not exactly the same since it can take advantage of media queries and other things that you can't do with inline styles, but close enough conceptually.
Where is the cascade with Tailwind? Perhaps I completely misunderstood how it works, but I would say that it feels like it's purposefully trying kill cascading.
One is CSS style inheritance. So if I do this:
<div class="text-blue-500">
<i>hello</i>
<b>world</b>
<div>
The `text-blue-500` style is going to cascade down to the descendent elements. That's just how CSS works and there's no getting around it.The other usage of the term applies to a style of writing CSS that makes use of this cascade. So something like this:
.card {
color: darkgray;
}
.card .header {
font-size: 20px;
}
I think what people are referring to in this thread is the latter, which is not the cascade, but a particular approach to CSS.Cascading refers to the order stylesheets have priority when loaded by the browser. Going to have to update my definitions for the future. I always thought cascading referred to how specificity worked.
Edit: no wait, specificity is part of cascading, cascading refers to the entire process of determining which style applies, including specificity. Inheritance on the other hand is not part of cascading. My definitions were right, don't need to relearn anything.
[0] https://developer.mozilla.org/en-US/docs/Web/CSS/Cascade
The order in which stylesheets are loaded and it's origin is just part of the cascading algorithm. See the "Cascading order" section https://developer.mozilla.org/en-US/docs/Web/CSS/Cascade#cas...
IMHO the only important application of the cascade is in its original purpose: custom user defined stylesheets (today often via browser extension or adblockers), but you can add proper descriptive attributes to your markup for them.
https://developer.mozilla.org/en-US/docs/Web/CSS/Cascade
https://developer.mozilla.org/en-US/docs/Learn/CSS/Building_...
Custom properties are by default inherited by all descendant nodes (they also interact with the cascade, but it is less relevant) and this can be used with tailwind in a couple of different ways: https://stackoverflow.com/questions/64872861/how-to-use-css-...
So the cascade still happens, just in a different way.
All my "hard opinions" aside, I have anecdote that no amount of facts can change—I build things faster, more maintainably, that look BETTER than anything I did before Tailwind. Until those pillars stop being true—Tailwind will have my heart.
The amount of cargo culting going on right now is at an all time high. People do stuff all the time that makes no goddamned sense and is defended by, “well Google is doing it!” You are not Google and you never will be.
In fairness, CSS is such a mishmash of things that it lends itself to cargo-culting.
You can fit the number of people who are exclusively CSS experts in a van and still have room for their luggage. Everybody else is going "that's cool, how do I do that?" and then copy/pasting it.
I mean, hell, it was years before you could reliably vertically center stuff with CSS (that we were doing with table-based layouts since the 90s). And considering the number of wonky layouts I've seen in what should be professionally done mobile Web sites, it's clear that it's hardly a Done Thing.
The nerd in me really likes SCSS, because I can more or less wrap my mind around it, but I get the Tailwind way as well. As a developer, CSS is way down my list of things to know intimately. Whatever I have to do to keep things moving, I'm good with it.
CSS was meant to cascade; it's what the damn 'C' stands for, and if you cannot understand the efficiency of the cascade, at scale, you are most definitely missing the entire point of CSS.
I have personally built ui libraries for boutique firms and enterprise (Apple) firms and guess what we did _not_ use in any of those instances? Tailwind. Because it's an utter toddler to manage and very definitely not efficient in its application.
Styles applied by Tailwind classes cascade. The library just makes it (intentionally) difficult to define a class that will easily collide with others.
If you want to cascade all your styles all the way down, by all means go for it. However, I aim for readable / scalable styles rather than dogmatically "cascading" everything just because it's in the name.
TailwindCSS puts a bottom threshold to the low quality - it guarantees a minimal level, regardless of what the rest of the codebase looks like.
This comes at the cost of general (but limited) messiness and guaranteed lack of maintainability.
I don’t use it but if I was on a team where engineers don’t talk to each other I probably would.
In cases like this I get curious and try to understand: why? I do not do CSS enough to arrive at the verdict about Tailwind, but my best understanding aligns pretty well with TFA. That and the fact that people wanted some framework that is popular and can be easily reused for results that look reasonably well. Bootstrap was it for a while, but Tailwind came and looked more modern.
Taylor Swift - still beats me.
There’s no replacement for understanding the underlying technologies of frameworks, that’s true. Compared to some frameworks, tailwind is only a small layer of abstraction, one that does not obfuscate the underlying tech away. It does not prevent you from learning or using CSS. That’s why it’s so good.
I frequently drop tailwind into projects because I know the shipped code footprint is low and it accelerates design.
Tailwind is a pretty good framework for people who want to practice atomic CSS easily, and it is a bad framework for anyone trying to avoid that pattern.
The pros and cons of atomic CSS can then be argued about elsewhere.
https://hn.algolia.com/?dateRange=all&page=0&prefix=false&qu...
This also covers both scoping issue with css: the usual issues with the single global namespace for classes and the unlimited depth of the descendant selector.
That is even with scoped classes if your app has component nesting as <A id=1><B id=2><A id=3></A></B></A> then a selector like .A_box::hover .A_btn will select the class A_btn both in <A id=1> and <A id=3>.
Tailwind solution is to manually or programmatically apply the relevant style in your template.
The whole idea being that the unit of reuse is not the class name but the templating component.
But this idea that all styling should be done in HTML is antithetical to the whole reason CSS came to be in the first place, IMO. I can see why people like it to an extent, but I just don't really get the arguments that switching files to write CSS is "context switching" that makes things harder. If you need to see both your HTML and CSS at the same time then get a bigger monitor (mostly kidding).
I just still see that well crafted HTML and CSS work together, make sense, and especially with all the new tools available in CSS, just isn't that hard to get right. Well structured HTML is the biggest pain point I see for those that struggle against CSS. Learn that, the cascade, learn how to encapsulate styles (there are plenty of good patterns) and it will flow just fine.
It really shines for apps that are changing rapidly and are at risk for generating dead CSS, which has been a problem in pretty much every commercial codebase I’ve ever worked on. Tailwind adds a simple, straightforward, one-way-to-do-things approach that creates a much more maintainable experience in HTML templates that results in zero dead CSS code.
It’s absolutely not for people that need fine-tuned CSS APIs like animations, etc. But for building a product rapidly, it’s become a go-to for me.
I never try to be dogmatic about new things - so I'd try it again. I just haven't seen the benefits yet myself and so default to the cons I expressed earlier.
True, but those usually involve adding some sort of linter to ensure that your style sheets are clean, which is an additional build step, which is an opportunity for a build to fail. Tailwind gives me this out of the box and doesn’t require any sort of manual lifting because it does this automatically.
> Tailwind starts to break down for larger/complex apps also
This hasn’t been the case for us, I’m on a team of about 50 devs contributing to a 2 year old monolith and Tailwind hasn’t once gotten in my way.
For what it's worth, in SvelteKit CSS is per-component and you get warnings for unused CSS selectors.
Style classes are IMO the neatest way to inject styles, having elements get styles based on html structure makes code brittle and hard to reason about. If you need an example of this try playing with bootstrap forms.
<div class="unique-component-name">
<input class="unique-component-name-input" />
<p class="unique-component-name-text">Blah</p>
</div>
<div class="unique-component-name unique-component-name-variant1">
...
.unique-component-name {
...
The cascading in HTML makes the thing that should be easy, creating variants with slight tweaks the most painful thing.And I did not say to base styles on html structure - you are correct, that is brittle and actually one of the things I often ask about in FE interviews as a way of determining skill level. I said that good html structure makes CSS much easier, if your structure is bad, it can significantly compound the amount of CSS needed in order to achieve the desired outcome. So I believe there is a significant distinction in those two statements.
Tailwind is a massive improvement in terms of maintainability across teams and tooling. Thanks to Tailwind my team hasn't had to think about CSS resets and browser shims for over 5 years now, and any bugs where an application looks different in a particular browser can be forwarded to a team who will fix it, instead of us having to maintain an ever-growing pile of special rules feature detection code.
There is, of course, no silver bullet, but for a team building applications from components with React or Vue, Tailwind is a maintainability dream compared to stylesheets, and easier to train new devs on too.
I believe both React and Vue have the capability to scope your CSS along with the components. Modular CSS has been much easier to maintain over years than fixing when Tailwind updates or finding (again) that one !important that happens to conflict with a new released component set.
I save my teams time and money by applying CSS in the manner that it should be; which means not as an inline style mechanic.
While that's true, it also means you need to propagate all of your exceptions for support of old browsers. And you still need a ton of global styles so your application can be re-themed or white-labeled according to your customer specifications. And god forbid someone applies a color directly in a component and you have to grep the codebase looking for the errant code.
After 5 years of tailwind on several complex applications, I can say that it's been easier to maintain, especially as engineers come and go, than any of the applications I worked on before. Frankly, every company I've ever worked for wound up with something like their own bespoke tailwind anyway, but instead of having it well-documented, every new hire had to learn whatever naming system whoever wrote the global design styles decided on.
Any remaining reusability can be handled with templates / components (depends on your framework).
The remaining potentially nice thing about Tailwind is that it more naturally constrains your options/syntax with utilities - when working with designers, this is probably a good thing. As always, the hardest problem of development is finding technology that best establishes the social contract.
I also don't think about it too much and sleep well at night ;)
For most uses, the only thing really wrong with the style attribute is the lack of breakpoints for responsive layouts.
I'm a backend developer, who works mostly in python. I'm probably never going to learn CSS but I can produce a user interface that looks like I'm competent by copy-pasting tailwind divs. In 5 years, I'll hire someone who knows CSS to fix it. It'll be cheap because webflow and squarespace are allowing graphic designers to build websites, which is squeezing the demand for CSS as a skill.
Bootstrap's future is increasingly uncertain, of course, under Twitter/X. Tailwind as the "new bootstrap" makes a decent amount of sense.
These frameworks aren't an excuse to ignore and misunderstand the underlying technology. It's worth understanding CSS, but these abstractions can really speed up development time, especially if your job involves more than "front end development" (which is still true for many of us).
What do you mean? Bootstrap has not been affiliated with Twitter for more than a decade.
I edited that part out, thanks for pointing it out.
You could not pay me enough to learn CSS. Every time I have to debug CSS there go many valuable hours of my life. With an insane amount of trial and error and judicious use of Chrome's dev tools I can usually hack some garbage together, until the next time I have to figure out how to remove the background of a button.
In the literal 90s I was building fully-featured GUI programs by dragging and dropping buttons and text boxes and inputs onto windows with Visual Basic, and the window resized nicely. Thirty years later I have to do the same thing with gazillions of arcane style sheets. It's a disaster. How did it get this way?
Users were enamored by custom drawn UIs, so designers started demanding custom drawn UIs instead of native widgets. Most users don't understand what they lost and now pawing at interfaces to discover how they work is the new norm.
It’s called “progress” apparently, and older gray beards complained about it when we reinvented the mainframe through the same methodology.
For all of the re-use that us computer folks talk about, we surely reinvent the wheel an awful lot. I’m guessing that we have some sort of stubborn creative streak that causes it all. That’s my excuse at least.
I.e. programming is not supposed to be easy. So if one sticks to it, the problem has to be hard at least from the management point of view.
Modern web design is a mess, yes, but it's vastly more sophisticated than what was available in the 90s and I would not choose to go back.
I was skeptical at first too but after building several large and successful sites with tailwind I’ll now choose it every time. It’s the only CSS method I’ve tried that doesn’t turn into a hot mess at scale.
This attitude has become a pretty useful anti signal when considering who I want to work with though.
It's as modern as the style parameter is, and it's as reusable as a moving a dirt pile from one corner to the next.
You're not learning anything valuable by learning Tailwind. Learn CSS, that will stick with you for the next 20 years.
It amuses me when a library is implemented 'with tailwind', which means it's totally useless to the people _not using tailwind_, and excruciating to clean up.
Go ahead, downvote me to hell, I'll see you in 5 years.