I'll post one of my previous comments here, hoping to get a discussion going...
> The problem with Tailwind for me is that Mr Wathan misrepresented « Good CSS » in his essay. His examples are BAD CSS, not good CSS. He then sets out to correct a problem with CSS that HE created by writing dirt poor CSS.
`.author-bio > div > h2 { color: red } is NOT good CSS. The div part has no reason being there (why would the div change the color of the title ?). After presenting this auto-created problem, he sets out to solve it with BEM, where you need untold numbers of classes for everything. So now, CSS has a naming problem, created to solve a non-existing auto-created CSS problem. And Tailwind now solves this pseudo-problem.
Apart from this, the thing that really bugs me is that every advantage claimed (apart from one) is also non-existing because if you do your CSS right, the same claimed advantages arise in pure CSS. Design tokens ? No need for json, custom properties are all you need. Specificity ? Cascade layers, pseudo-selectors are here for you.
The only "advantage" I see is the possibility of working in one file only rather than a couple of files. And that, for me at least, is not a real advantage but only a justification for being lazy. There's no way the price of all these processes and dependencies complexity are worth the laziness-added value.
Does someone care to "prove" me wrong here ? At least, can someone engage these arguments ?
Maybe one point not raised enough in the eternal discussion between Tailwind vs CSS properly is the cognitive load of naming and organizing things.
To do CSS properly, you need to name classes, you need to come up with CSS cascades that work.
Being programmers we would love to categorize and name things all day long. Ever heard how we over-engineer things because of the DRY principle?
But we would love to name classes and do CSS properly only theoretically. In practice, we run out of time making CSS with nothing to show a week into the task except a CSS kitchen sink demo. By the time we're done, the scope of some component has grown in a way we did not expect and is hard to represent without markup change.
Tailwind on the other hand removes the task of thinking how to name the thing we're making. A appbutton appbutton--state-user-notallowed or a touchbutton touchbutton--disabled? In Tailwind it's just a a blue-600 rounded rectangle. Scope changed? No problem, now it's a green-400 shadow special rectangle, without checking where else it was or will be used or coming up with a new name for this special rectangle.
The naming of every little thing in CSS is what I call a "pseudo-problem" in the original post.
You don't have to name classes for everything inside a component. You only have to name the component, as in Tailwind. Afterwards, tag selection is totally fine. And with all the new CSS pseudo-selectors it is now easier than ever to be styling with low specifity while including markup options.
Yes I have. For a couple of years and my team still uses it.
But Tailwind is sensitive to DOM changes too, since every style is on tag. You wouldn't remove any tag without understanding its usage in a component using Tailwind. Why would you treat a CSS component any other way? If a tag's there, it must be used for something. Again, I may miss something but I see that as normal care and dilligence in both ways.
On a sidenote it's now easy to include, for example, all headings to be styled the same in a component, thereby limiting the need to adjust the CSS in case of a change of tag. There are many ways now to leave markup options opened if need be.
Your belief that you must use classes to apply CSS is false.
CSS is a generalization programming language, with specificity meant to be used for _exceptions_. Therefore, CSS should be used with general statements first, contextual statements next, utilitarian statements following, and then and only then exception-specific declaration in the edge cases they are needed.
Programming with CSS the way it was intended: Cascade, Inheritance, and then specificity, generally produces a quite DRY experience.
The one thing engineers/other programmers seem to have missed, continue to miss and seem intent on missing into the future is this: CSS is a static programming language that must account for being in and rendering dynamic contexts.
When I'm in JavaScript, I _depend_ on having the one thing, be the one thing, whenever I reach for it. I depend on immutability to keep my life sane.
When I'm in CSS, I _must_ account for flexibility, because I cannot predict the future, and I cannot predict all the various contexts in which my declaration might exist. Therefore, each CSS statement I create is based on how I would _like_ my thing to behave based upon a variety of circumstances, and to have static fallbacks when all else fails. My sanity is in producing the most responsive yet stable experience for the unknown.
Tersely, but without apology: Tailwind is for developers who do not want to take the time to learn CSS the same way they took time to learn JavaScript [or insert language of choice].
The problem is that I’m not convinced that “good CSS” even exists. Even the very idea of separating content and style seems problematic to me, and in my experience it simply doesn’t works for anything more complex than a markdown converted to html.
Add to it that for some weird reason web’s style includes layouting, which imo should be a separate thing entirely, and this is the primary reason why any given CSS has to be specifically created for a given HTML template, and why seemingly benign CSS modifications can move that 3rd step of the checkout page, rendering it completely broken.
Restricting CSS to a subset of only cascading some very basic properties (fonts, colors, default font-size), and letting everything else be managed on a per component basis (where close coupling of style and template absolutely makes sense) and simply layouting those components to form the given design makes much more sense to me (and frankly, it was sort of figured out a few decades ago by several desktop GUI framework..). And while you can write vanilla CSS this way, tailwind just restricts you to this subset — the same way there sure exists some safe subset of C, but you need something like Rust to restrict you to that [1]
[1] I know, this is not really how it works, it’s only for the analogy’s sake
> Even the very idea of separating content and style seems problematic to me
When I try to "separate" CSS, I always end up creating utility classes (so kind of like Tailwind).
Currently, I like to use a combination of utility classes (e.g. class="text-bold") and high-level class modifiers (like a ".pricing" wrapper, and then I can modify everything inside the pricing section like spacing, font sizes, colors).
.pricing h2 { color: var(--color-tertiary); }
I think this makes more sense than adding "color-tertiary" class to each h2, because if I want to change the color, I would have to modify it in all the h2 tags.
I would use "text-bold" if there is a one-time instance where I want the text to be emphasized. If there can be a rule extracted (e.g. make every first word bold), I would use CSS selectors/classes to modify all those instances.
I'm far from being even "above average" at CSS, but this approach (as a long time developer, mostly in OO) has made the most sense to me. Little bundles of things in their own contexts that apply to a limited area. I can re-use names as they are appropriate for their contexts and not worry about cross contamination.
But, other people do things differently so maybe it's not the best approach for them; but for my limited needs and experience, it's been fine, if not great.
How would you maintain a reasonable "component-based" approach without something like scss? I'm legitimately curious.
Otherwise, you have to take great pains to ensure styles don't conflict or accidentally apply to things they're not intended for. Or you have to use some other framework/tooling to convert your css selectors and markup so that scoping is enforced
There is also the ::part() selector now which is quite useful for selecting things within a shadow. https://shoelace.style/ uses parts for styling individual parts within custom elements.
In practice, I've found that to be pretty unwieldy and difficult to use.
My general approach is to keep most application level components in the light dom for styling, and only use shadow dom for library-like components, mostly layouts for slotting light dom stuff.
This is in some places a little bit specific to Lit but mostly not and walks you through that shift in mental models from start to finish that tends to trip people up a lot coming to Web Components https://youtu.be/Xt7blcyuw5s
FWIW if you are interested in Web Components I would say Lit is hands down the best entry point I’ve come across. Strong recommendation and nullifies most of the common complaints you tend to hear associated with them.
And here's an experiment I'm working on, where all styles are scoped to components because all static DOM trees become custom elements with their own shadow root: https://github.com/aalin/rdom
Simple linting rules can get you lots of mileage here. First and foremost, you ensure that in any component CSS file, ALL selectors begin with a class that mirrors the filename.
It seems to me that this can prevent the vast majority of conflit or spillover occurences. Don't you think?
> First and foremost, you ensure that in any component CSS file, ALL selectors begin with a class that mirrors the filename.
But then you're adding a convention that isn't as easy to follow. Maybe you follow it, but what about new people. What about people who make a typo? Are you going to make a VS code plugin that points out if someone mistypes the file-based class in the CSS file?
What if the file is renamed, or moved? Do you then have to go update every selector in the CSS file?
This all seems so much more brittle to me than just using tailwind, and the VS code plugin show you the possible class names you can select from when you start to type something, as well as rules for each of those class names. It also catches (and highlights) contradictory rules, when applied to the same element. You can't do that from the CSS (there's no telling what the declaration will be used for, from the css in isolation), and unless you make your own editor integration, this won't happen when editing markup either.
What is the convention? Beginning selectors in a file by the filename only? If I understand correctly, then I'd fallback on the linting.
If the file is renamed, then yes, you change the selectors. That's a simple operation. But I think the same goes for any JS framework where you'd create components. If you change "button" for "secondary-button" you'd have to change it in at least a couple of places I guess? Either way, you should limit these kind of operations to a minimum.
And what if I don't want to use VSCode? Maybe there are Tailwind plugins for every text editor...
But more importantly, that's quite easy to include your CSS files in the autocompletion of, for example, Sublime Text. I'd guess it's the same in VSCode. And again, simple linting should prevent much of these problems I think. You can easily lint contradictory rules in a ruleset. Stylelint would be perfect for that.
And if by mistake you have contradicting rules across rulesets, then a quick look at the devtools will tell you where the problem comes from. On a sidenote, the devtools become real difficult to use in a Tailwind-like paradigm.
> If you change "button" for "secondary-button" you'd have to change it in at least a couple of places I guess?
I'm not sure I understand this argument. If I rename a component and the file it's in, I get automatic import renames across the codebase without having to do anything myself. And if I didn't, I'd get errors trying to run the code (I'm not sure how you'd configure CSS to do the same thing with unmatched selectors, though I guess you probably could remove them from the output at least with postcss)
> And what if I don't want to use VSCode? Maybe there are Tailwind plugins for every text editor...
They removed the question so I don't know what current trends are, but Tailwind is at least supporting 90% of possible users with just those 2 (and I haven't looked into support for other IDEs)
> On a sidenote, the devtools become real difficult to use in a Tailwind-like paradigm.
I haven't found this to be the case at all, I'm not sure why Tailwind would make the devtools more difficult. If anything, it makes it easier since I typically only have to look at the CSS section for elements which have inherited styles
A simple find and replace would do the same then for a CSS change. Again, that's not something that should happen often.
As for support in text editors, you can still autocomplete any class you have in your CSS. And the CSS linting will give errors too if you have problems. And there are CLI programs for discovering unmatched CSS, which works pretty well in my experience.
And the devtools suffer from all the added classes. It can slow down to a crawl depending on your machine. And you can't play as easily with the styles... If I disable a property in the cascade, all other items with this property will lose it. I would say it goes against the devtools grain. But I guess it depends on your usage.
Separation content and style works perfectly well. Just people never bother to learn neither HTML nor CSS and rely on some generated monstrosity, be it generated by WP or React.
It works for me mostly only theoretically. When I have to apply it at scale I run into the practical problems that people mention here; 1 big namespace, mostly.
I think most developers simply don't care about this, I know I don't*. I don't see CSS as some beautiful thing I should tweak and spend time naming and doing "right". I want to be able to slap some class names onto things that quickly make it look the way I want, with a system I know others will be able to grok almost immediately with a high level of consistency and get back to building the features that are actually going to attract customers and generate more value.
The advantage of Tailwind is commoditizing CSS into something no one has to really think about as deeply as you're suggesting we do. Someone who cares to can do that thinking and put it into a Tailwind class in one of the versions. It's also portable, in that anyone who works with Tailwind can come in and immediately contribute, instead of figuring out whatever structure we've built ourselves.
Tailwind provides me a lot of value in that it lets me continue building while providing a very nice UI (which is required in modern times) and not having to engage too deeply with styles, because I'm not trying to be a master of CSS, I'm trying to build a wholistic product and I have 500 other things I need to do.
* I'm a backend guy but recognize I need nice UIs.
Well, I wouldn't say it's about CSS being a "beautiful thing". It's about delivering great experiences to our users, experiences that use our native tools in an optimized way.
Because, you can ship the same experience with less code, less dependencies, less complexity. You can better serve users by easily catering to their preferences via the cascade. You can make use of new technologies that increase performance (see, among others, HTTP3). You can profit from the newest supported CSS properties that are way more expressive and give you more flexibility for cheaper.
Nobody's going to engage with those arguments because they miss the point. Tailwind is CSS, ergo it wouldn't work if what you're saying wasn't possible.
Writing good CSS for interfaces in a web application of significant complexity is expensive and time consuming. Tailwind solves that problem very well. Other CSS frameworks have done so as well over the years -- I wouldn't call Tailwind unique -- but the micro-class approach it takes is perfect for modern interface templating systems like Vue, where you tend to abstract at the component level instead of at the style level.
How is that better than enclosing CSS in a component file with a class as first selector?
I see that bad developers could make mistakes, but besides that, which is kind of easy to lint, the only advantage I see is the need to maintain only one file instead of two.
It is quite fast to make changes and see immediate visual results. There's basically one less step to making css changes. What you call "lazy" in your OP, the rest of us comfortably call "useful".
If I need to add some padding, I slap on some p-4, my browser refreshes, and I see the result.
I don't really get the spiritual debate. It's a tool, use it or don't.
You can do the exact same thing with CSS. It does not matter if the code is added to HTML or CSS.
And for me, at least, this is not a spiritual debate. On the contrary, this is a very practical debate. The popularity of the tool and the signal it conveys absolutely has consequences on all of the development community. Whether I like Tailwind or not, I have to maintain projects that were done with it, I get asked about it, etc.
I think that saying "it's just a tool" is kind of short-sighted. It's a paradigm. And as such, its practical implications are far reaching.
>The popularity of the tool and the signal it conveys absolutely has consequences on all of the development community
I'm stuck on some rather legacy (read: fashionable 5 years ago) stack either way, but its interesting that I'm conducting an interview later today where the applicant ensured to exhibit a Next/Tailwind/TS app that runs on Vercel.
I can't blame them either, I remember interviewing two summers ago and being asked if I had experience with Next straight out the gate despite it not being mentioned anywhere in the job description.
It is a philosophical debate about the relationship between HTML and CSS.
The "traditional" approach to authoring HTML and CSS is predicated upon on idea of separating concerns. The idea is that your HTML should not depend on your CSS, and your CSS should not depend on your HTML.
The "utility-first" approach reacts by claiming this is wrong. It goes on to reason that either HTML depends on CSS or CSS depends on HTML, but neither are independent. This is what Adam Wathan calls "dependency direction."[0]
Tailwind solves a communication problem, not a technical problem. It's extremely common on large teams to have people come and go. The more complex your CSS is, the more time it takes to train someone new. Think of it as a standard library for CSS.
No argument here. But I believe, as others have suggested, that Tailwind is for people who have given up on (or aren’t motivated enough to pursue) the idea that they can /ever/ learn CSS.
Adopting Tailwind is easier than thinking about CSS, even if they end result is (IME) just as wonky and disjointed as a ‘bad css’ implementation
Partially true. I had (once upon a time) mastered CSS to the point of being able to make pixel perfect documents. I understand CSS, that is WHY I use Tailwind.
CSS is the low level language of styling. For the same reason I use C# or Javascript instead of assembly language or C, I need to get shit done.
I can see where this comes from, but in my case Tailwind is nice because while I know a good deal about CSS it is far from my core competency. Tailwind offers me a well organized toolbox of things that are all good enough, but more importantly easy for me to use pick up and use occasionally. It is also something that I can work in with both FE and BE engineers, it provides a nice lowest common denominator.
Hmm, ya know after thinking about your reply… I could see there being a way of executing TW that increases the chances of higher quality FE—-and probably make refactoring safer and more systematic to boot.
Unfortunately, I haven’t experienced this :/ (yet)
i think you're kinda proving his point. it's easy to write "BAD CSS". I write "BAD CSS". you may be so good you only write GOOD CSS. i'm not. I may never be as good as you. tailwind is a framework for people like me. (there are lots like me)
CSS is really not that hard to understand and use adequately. And as I said here, linting should be more than enough to nudge you in the right direction, CSS-wise.
I also used to feel like the comment you were replying to. About two years ago I decided to try and lean in heavily towards “modern” CSS and honestly things have gotten so much better the past few years.
I also leaned in heavily to the component model with Web Components which was another huge win for my experience with CSS.
I actively enjoy it now rather than dread it. Catching up wasn’t too difficult and if someone else is in the same boat I would recommend the investment.
It depends on the project. More HTML and CSS than JS. But, as I said, the team has been generally using the Tailwind paradigm for 5 years now. The team has also been divided for while about it. Heheh.
I'm using tailwind in one of my projects. As a normally backend dev, I find tailwind rather weird. It seems very much like it just gives you classes for every css property&value match. It seems very much like I'm just writing the css but in a different way. cursor-pointer class for "cursor: pointer" for example.
However, I find the responsiveness side of things very useful.
Yeah, tailwind isn't intended to make it so you don't have to learn CSS. It very much tries to map to CSS fairly directly, so it wouldn't prevent you from needing to learn it.
> I'm just writing the css but in a different way. cursor-pointer class for "cursor: pointer" for example.
The difference is, when writing the CSS yourself you also have to find a way to apply this to the thing you want it to apply to. Which means you have to write your own selector. Which gives you 1000 guns pointed at your feet, and maybe two aimed away from you (and one of those is just the same one that tailwind gives you, but less portable).
> Yeah, tailwind isn't intended to make it so you don't have to learn CSS. It very much tries to map to CSS fairly directly, so it wouldn't prevent you from needing to learn it.
For me, a framework should deal with the basics and make thing easier. Making it so you just write css differently seems odd for a framework. It seems more like a css parsing framework than anything. The tailwind UI seems like a framework that provides you the basics.
It's not that hard but it's more work than I would like to do as a backend developer. Realistically, I want to put as little work as possible in to frontend and focus on backend.
The way I see it, the problem is the C in CSS. If you rely on `.author-bio > h2`, then every time you make a change to `.author-bio`, you have to consider all the contexts in which this class may be used globally in your site, and if you change the styles for `h2` even more so. Sure you can say you encapsulate every context with a globally unique id, but since you’re probably already using some kind of templating system for you HTML, it’s easier to specify the styles there. It’s basically the difference between having variables scoped global vs. local by default.
The « > » part should not be necessary 90% of the time.
And while using Tailwind, I still have to know where I include my components. I still need to test different instances in different places.
With that in mind, I don't see the added benefit of Tailwind here (again, other than limiting the damage done by careless devs). Maybe I'm missing something?
I don't think tailwind is the right solution, mainly because there's just zero type safety with it. The ergonomics are terrible for knowing what options you have available, and whether you made a mistake or not.
> if you do your CSS right
I think the reality is, when you hit a certain size and scale of developers working on your product, it's next to impossible to do CSS "right". It's just not a skill that's widely shared in large frontend teams - a part of this is that the role of a "frontend developer" is pretty broad now. There's a lot of frontend work where you just don't end up styling things.
This is why you might want to abstract out HTML is styled one level up, and then go from there. Having a good framework for people to style things consistently, and then create higher and higher level components for all the common patterns.
Personally, I think the better solution for this (as opposed to tailwind, not "let everyone write their own bare css") is something like Vanilla Extract's Sprinkles to create your meta framework for styling with full type safety and editor suggestions https://vanilla-extract.style/documentation/packages/sprinkl...
Outside of agency land building bespoke brouchure websites, I've never seen companies hire "CSS Developers". Closest would be hiring developers to work specifically on design systems/component library.
I think it's useful to think about analogies for other parts of the tech stack. You probably don't want every backend developer writing SQL by hand every time you interact with the database, so you create various levels of abstraction on top of that to "limit the damage done by careless SQL developers".
The negative sentiment ("careless CSS developers") isn't necessary. It's not about fixing the problems from bad developers doing bad things, but just giving people better alternatives to make it not possible for anyone to do "bad" things.
Sorry about the "careless" bit. Maybe I could have chosen a better word.
I get what you're saying. But again, linting should be enough to guide you in writing good CSS. It's really not that hard if we are interested. No need for a whole new way to do it. What I generally get from discussing about it here or elsewhere is that lots of devs just don't like CSS. Which is a shame since it's central to our work as Web devs. What do you, yourself, think about this?
>There's a lot of frontend work where you just don't end up styling things.
the problems these things all try to solve are not so much how to style things, but how not to have the cascade bite you because your devs didn't understand that part.
So how to describe that a problem - is it a CSS data model problem?
well part of the whole discussion up was that BEM was a crappy solution, really the best solution is to know how stuff works so you make your solution correctly.
But because some people don't know how stuff works you come up with rules that if they follow they won't mess stuff up. They won't make things in the best way, but they won't screw stuff up either. hurray!
the best way is the most remunerative way as well, which is that people know how to do things correctly, knowing how to do things right means that people make less mistakes, making better things.
However this is not the cheapest (because costing learning time) or simplest way.
I posted your thoughts on the Tailwind chat. I’m trying to push Adam or one of the other leads to come on and post a proper response.
I completely disagree with your opinion, as well as numerous other Tailwind developers lol.
Your opinion of Tailwind is kind of the like what the person who may have believed the flat head screw was the way when they introduced the Phillips head screw. Both types of screws are great tools, but a Phillips head may have seemed less superior to you because you didn’t understand its purpose and value.
That's great! I'd love to have a proper response as you say.
As for your analogy, I'm not convinced it's adequate. The Phillips screwdriver does not reinvent the way to turn screws as Tailwind does here with styles. The Phillips screwdriver does not add complexity in the building of houses.
They aren’t reinventing the way you write styles. Tailwind is actually just a CSS design token and utility class library at its core. It’s the Bootstrap of the 2020’s.
Regarding design tokens, they are taking notes from 1996, and they realized that it is much more computational efficient to describe your component visually with inline styles compared to loading separate style sheets.
Tailwind and CSS design tokens in general make it easier to make smart, efficient choices from curated palettes. Design tokens also create a common language for everyone who uses Tailwind - both across teams and across projects, which can break down communication barriers in large scale projects.
I agree wholeheartedly about design tokens. I use this in every project, always. But I only need custom properties, nothing else. And I get all the advantages you're describing.
And I'd say that striping the cascade, removing selection and specificity and implementing new ways to do the same things (ie: peer-[:nth-of-type(3)_&]:block) is indeed reinventing our use of CSS.
If you name your own tokens, then other people coming to the project have to learn to apply the same set of tokens correctly, and may even end up reinventing the same ones with new names. In fact, you might even do that (well, it sounds like you might not, but I certainly would, and have)
Tailwind is just that, but unified across all projects, with better tooling (VS code integration, tree shaking, lighter css files)
So this is where Tailwind comes into play. With TW, you don’t need to any custom properties. They include base stylings and preflight styles that fix and reset just about any browser quirk or bug. The end result is a consistent styles that look and function exactly the same on any device or browser.
There are hundreds of little tiny css style rules and fixes for a perfect website, and you have to remember them all. Tailwind has done all of that, plus a bunch of more.
Their utility classes are their biggest feature in my opinion. Just the ability to set dark mode styles inline with my light mode styles seal the deal for me alone.
Again, I agree the base stylings etc. I do the same in each of my project using pure CSS specifically because I don't want to remember them all.
So I have all the same kind of files, and change the design tokens accordingly. The only difference is I configure in CSS whereas you configure in JS. You can bundle it all and keep reusing the same files as you would do in Tailwind.
Is there a way to implement responsive inline styling (e.g. class="flex-col lg:flex-row") in pure CSS? I remember thinking a lot about what Tailwind offers and I came up with that and a vague sense that I probably just don't know CSS well enough to have an opinion I'm comfortable with.
Edit: I guess this question kinda doesn't make sense. There's a lot of CSS syntax that isn't available inline in the style attribute and the example I gave can be done with "traditional" CSS classes. The thing I'm really considering is how one can semantically choose HTML elements while using small bits of inline "styling" (read: atomic CSS classes masquerading as styles) to change the properties which need changing and forego CSS otherwise.
Anyway, ultimately I don't think that's necessarily better than other styling implementations.
I think another advantage of using the framework is that one does not need to learn CSS in depth and in detail.
I have learned CSS and absolutely love the cascade. If I hadn't, and was on the clock, I'd consider something more shortcut-like, even if it's less precise.
If I was using React, writing components in the way SPAs require, Tailwind could make more sense. SPAs fragment code into such little pieces, that thinking about CSS as a whole becomes less necessary.
But, I do know CSS, I have adopted the ITCSS code structure, I do have the Tailwind colors in my SCSS codebase, use the Utopia fluid typography and spacing scales, and with grid, container queries, flexbox, gap etc. life is good. CSS is fun.
It is, as of now, the only argument I've read that sticks. Lots of devs do not like CSS. And this is a way for them, as you said, to skip understanding the language.
Maybe it's less about representing good/bad CSS and more about representing the CSS people typically write in the wild.
I guess if people only wrote really good CSS in the wild, or hey even agreed upon what it looks like, there would be no need for tailwind, that's true. But that's not reality.
But could we not care and try to use this native language as it was designed instead of short-circuiting it by slapping costly dependencies on top of it? Wouldn't it be a better approach considering, among other things, the coming ressource optimization in HTTP3?
I used Tailwind for the first time about a month and a half ago, reworking my blog from `styled-components` [1]. I had been avoiding it because--as other people have said--it looked really ugly and unmaintainable. I was pleasantly surprised by just how easy it was to get going, however, and my fears about it all ending up as an unmaintainable soup were unfounded.
So I guess I'm a Tailwind convert :) It's very quick and easy to get stuff done using it--the design system is very well thought out. For internal dashboards I think you're still better off using an off the shelf component library like MUI, but Tailwind is a really good option for anything else imo.
Yeah, good question. At a high level I think the best analogy is React: when I first saw it, I wasn't entirely sure about mixing in HTML with my Javascript. It seemed strange. Now that I've been using React for years, however, collocating these things seems like the obviously correct thing to do.
Tailwind is similar: instead of extracting styles out to a separated styled component or even a separate .scss file, you collocate them with the rest of your layout. When I read code using Tailwind it's easy for me to "see" how things will look in a similar way that I can "see" how a React component will function at run time.
More concretely, I think these three things were important for me:
1. There's a really solid design system underpinning the Tailwind utility classes. With styled-components you start from nothing, and with off-the-shelf component libraries (e.g. MUI) you get a design system that isn't quite as well thought out. Tailwind's classes just work together really well out of the box because the defaults are so sensible. I'm not a designer, so this is a really big win for me.
2. Components help prevent class soup. I suspect I wouldn't enjoy Tailwind quite so much if I were writing plain HTML, but for things which _do_ need to be reusable like button styles I'm still writing code that looks like `<Button>...</Button>`. Nothing really changes here from styled-components -> Tailwind other than how the styles are written; they're equally maintainable.
3. One-off snowflake UIs are really easy to implement, because you can just write your classes right then and there. I've never worked on a nontrivial web application where _everything_ fits cleanly into the design system, and going through the ceremony of creating a styled component just to add a little bit of additional spacing is a pain. It also sucks for maintainability because a name like "Spacer" doesn't tell me anything about the styles, so I need to context switch and jump to the definition. In contrast, seeing "mx-2" instantly tells me what's happening.
I do think Tailwind's something that benefits from first-hand experience, though.
It’s pretty universally described as extremely ugly to the point where the most common request for years is people asking how to build component classes in CSS in order to move it out of the HTML.
But you could have the exact same design system in native CSS. I don't get why this should be considered a Tailwind benefit given that it comes with a lot more baggage. Am I missing something?
- styling is scoped to your components. You won't break your UI trying to refactor rules & selectors
- by default you don't need to invent class names. The components provide enough context
- it forces you to make a selection of colors an spacing, leading to a more coherent style.
- it is easier to understand than a lot of other css frameworks. It is just a "basic" rule generator with some QoL like automatically pruning the rules you are not using in the production code.
I'm currenlty working on a project which has used styled-componentes extensively. I plan to entirely remove it (and I am considering tailwind or vaniall CSS to replace it) for the following reasons:
1. It increases mental overhead. It is not possible to tell whether a component contains pure CSS styles or adds some functionality, unless you open it and read its code (in that point, it has lost all of its benefit for me). With CSS classes or even HTML style attribute, this distinction is immediately obvious: style vs. function.
2. It clutters the codebase. You'd find all sort of little components sprinkled everywhere.
Both of the above critics could be addressed by implementing a convention, however. For example limiting the use of styled-components to a specific package. The second issue is mostly programmers' fault, not styled-components. However, with CSS I don't have any of these problems to begin with.
Tailwind threads are always the same. And like in all of them, I'm here to say I love Tailwind, and thank you to the devs! It's such a small thing, but the 950 color is a great addition. It's one of the areas where I've reached for my own classes, so I can eliminate yet another little bit of CSS from my codebase.
Vanilla CSS, SCSS, BEM, Bootstrap, Styled Components, different kinds of CSS in JS solutions and I still prefer Tailwind over the other methodologies and libraries because I don't have to think about abstractions and naming things. Abstractions are huge foot gun in frontend development because it kills all flexibility.
With Styled Components or similar libraries you have to wrap all your components with all kinds of variants that inherit properties. Composition over inheritance is a huge benefit of Tailwind.
The big problem with CSS is the specificity and if you ever worked on a real big project with BEM or vanilla CSS/SASS it will eventually become a huge mess of specificity and more and more specific nesting of class selectors to override other styles that you don't want. With Tailwind you can just add exactly what you want, nothing more, nothing less.
Sure the html is "ugly" but that part is invisible.
It is also very likely your bundle size will be smaller because it only adds the CSS for the helpers that you really used.
Just my 2 cents I guess. People should use what they like.
950 color is kind of mad and arbitrary decision though. Why tailwind has color 50 and 950, but does not have 850? It is so common to have some `bg-gray-900` button on `bg-gray-800` background, and no way to slightly highlight the button (not to the level of background).
50 and 950 make sense because of the way human perceive colors. We perceive colors in a quadratic way. This is why sRGB has a gamma curve, among many things. It means that the difference between 500 and 550 wouldn’t be as relevant as the difference between 0 and 50
I've tried Tailwind on smaller projects and it's not a bad way of writing styling. Not having to think about class naming or selectors speeds things up a bit, and it's nice that it promotes only shipping the styles you need (i.e. no classes with lots of the same properties declared).
However, one thing I'm still wondering about is how easy it would be to maintain visual consistency in a large project with lots of components, and lots of different developers working on different parts of the app.
Say the branding guidelines a certain style, like rounded corners with some shadowing and a hover styles, something that can't be done with a simple utility class. This should be consistent across many different components and pages. Then, someone in design updates the guidelines to have a different value for rounding and shadows.
With Tailwind out of the box, each component now has to be updated separately, and developers have to remember, or at least be able to check in documentation if that exists, which components use this particular style.
Is the answer then simply to use @apply for combinations of style? Doesn't this simply re-invent CSS classes, and create another layer of abstraction (you now have a class, which is composed of other classes, which themselves are composed of values set in custom properties).
I'd be very interested to hear how people manage this in large teams, over time.
Because you can ship in a few days instead of wasting weeks trying to bike shed through something as basic as css.
Use tailwind as a tool, have a component library that can be put together in a couple days max, and now you have ubiquitous styling language and don’t need to waste hours on css of all things.
That is pretty much what it has always been. The reason I like it is
1) it is more standardised (since it is written in html rather than custom classes) which means you can pretty much copy a component from one project to another without worrying that maybe the css naming overlaps etc. It just works.
2) it limits the decisions you need to make. No need to decide exactly how many pixels the padding should be. Just pick p-4. And if that is too much take p-3.
3) You dont need to worry that something in a totally different part of the app will break if you change the css to change the styling of a component
4) It is just faster to write and in my opinion easier to reason about (im sure this is personal) since I can see directly in the html what styling is applied and i dont need to go and dig in different stylesheets to find out what "custom-button-large" does
Except for 2, I think these points could similarly advocate for just using the `style` attribute. Even then, `1em` is a pretty good "default" for "I just want padding" in vanilla CSS.
Or SCSS variables. Which is what I’ve gone back to after a brief love affair with Tailwind.
Not bashing Tailwind. It’s amazing. But I found myself making thatsamefuckingwebsite.com again and god damn if I didn’t want something to look different.
And as soon as you’re writing your own CSS, you might as well just write your own CSS.
Like literally the first time you write your own particularly uniquely styled component and have to mash your own classes in with Tailwind’s you think, hang on, why don’t I just…
Edit: like this site. Just found it via elsewhere. https://www.usebubbles.com/ First thought: justanotherfuckingtailwindwebsite.com
You can change Tailwind configuration. For example, it's entirely possible to design 1:1 iOS-like UI using Tailwind with custom style config. The default style is overused, but it's cool to have a pretty base for small projects that don't have their own corporate identity yet.
I would argue that the tailwind.config is actually the single most important feature tailwind has. Making the framework your own and being locked to your style guide is fantastic.
inline css does not allow for pseudo selectors like "hover:". It does not allow media queries either. Browser are also slower to process them. So there are a few good reasons to use tailwind appart from standardization of spacing and colors.
The real benefit of TW comes from the configuration. You never need to put actual values into your class names like you would with inline styles. For example, let's say you have a specific background color. You define it in the TW configuration, and TW generates a specific class for that color. So, instead of doing `style: background-color: "#123456"` a thousand times, you do `class="bg-my-color"`, and if you want to change what `bg-color` is you just change it in one place.
I’m our use, we have a hardcore design system that our designers use to build designs. Our Tailwind config is exactly set to the values in that design system. This takes the padding values from being any value to only sizing valid in the design system, generally p-1 or p-2 for anything smaller. This lock-in really helps make things consistent.
Tailwind is similar to using the style attribute directly, but it’s got a less verbose syntax and it buckets the possible style values for a more consistent result.
This is how it basically was since day 1. These comments always appear in Tailwind threads -- more often than not, the poster hasn't given Tailwind a good try.
It's definitely worth building a few small projects - it looks and feels bad at first, but once you get used to using it, it's really hard to go back to anything else.
I've built a few small projects with it, and as much as I love the design tokens the idea of having a CSS class for every value of every possible property feels like abusing CSS, and it makes it feel like it has the same complexity of css
It does feel radically different from the more traditional way of doing things, but I think it is for the better. I wouldn't call it abusing.
Tailwind together with view components has changed how I structure my code and it creates quite a bit less work than my company's old more BEM centric approach where we would create lots of tightly coupled CSS code controlled by variables and such. I find it easier to grok as well, because I don't need to reference SCSS files to determine the implications of applied classes when debugging or similar.
Now most of the component requirements can be codified in a few classes in our view component instead. Does it look kinda ugly, yeah sure. But I'm sure it has saved quite a few hours for me since I switched over.
This might just be because old process was even worse, regardless it has been a very positive change for me personally.
that's how I felt until my first `dark:text-white`. I got 'dark mode' out of the box and only needed to change a few things. I didn't need to google how to set up the css, then define a whole new dark mode. I was able to do iteratively, right on the component I was changing. This made 'more work' on the dev side, but on the testing side, you just had to find a single instance of the component and verify it looked reasonable.
I think the ability to mix up things like that is what makes it quite powerful. You don't have to go digging through your sources to find all instances of '.my-one-off-class-that-some-random-dev-also-used'.
Agreed. I was a hater at first, but now I’ll never go back. Took me a couple months to get used to it. However i split my time between both frontend and backend.
It's a little more than just a bunch of custom css classes which are granular to the point of single CSS properties. It also implements a tokenized design system - basically providing you a scaled set of units.
You don't have to remember whether you had a 4px or 0.5rem or 4% border radius on your buttons, you just have to remember sm, base, lg, xl, or full. You don't have to remember the scaling of your fonts, you just use the same nomenclature.
This:
1. Creates a more cohesive codebase where most everything is using the same units (I've never worked on a project where there wasn't a rampant intermixed use of em, rems, px, and vw/vh -- except on tailwind projects)
2. Creates a more structured component feeling -- you don't ever run into the cases where border radius is off by 1 pixel or widths are using different units
3. Creates a more cohesive design feeling -- text sizes are balanced with eachother, widths are balanced nicely, colors grade smoothly, etc
I was a long holdout on tailwind. I always say it as just another way to write css except on one line (css golfing). Either I was ignorant in the beginning, or it changed along the way, but by the time I started using it around v3 I couldn't believe I was holding onto CSS for so long.
I think one of the biggest benefits, which I rarely see mentioned, is that all the class names are shared. When building your CSS for production, you can look at the classes you use and only add them to your CSS bundle. If you remove a class from somewhere in your HTML, the associated CSS gets dropped from your bundle. Your output CSS will shrink or grow with the classes that you use. Typically it's harder to remove dead CSS from traditional codebases.
Because the classes are shared to begin, there is less redundancy in the final CSS than using custom classes, perhaps with mixins to do standard flex or positioning patterns. So the resulting CSS file is typically relatively small and kept small by the dead code elimination. You can ship the entire CSS file to any page or on the initial page load for a SPA and not worry about code splitting your CSS, which can be troublesome in some builds.
> So tailwind at this point is basically just a bunch of custom CSS classes which are granular to the point of single CSS properties?
It pretty much always were?
> How is that better, than just writing custom CSS classes for components + having some util CSS classes?
1) colocation of style and layout in the code (no separate file, no "dead-code" CSS classes)
2) isolation of styling rules (this style applies ONLY to this HTML component)
3) Built-in standardization across the codebase (spacing, colors, etc)
Only works well in component-based web development (ie React, Svelte, Vue, etc) as opposed to inheritance-based styling (old school CSS+HTML)
You can get a lot of the benefits of tailwind using other tools like CSS modules (isolation) or colocation (styled-components), or with plain CSS features (CSS variables for standardization). But tailwind has a major benefit of introducing almost-zero runtime impact (vs styled-components) and having everything already built-in (vs css-modules. There is very little the user of the lib needs to think about architecture-wise when using tailwind
It is on the landing page. Roughly halfway down.
That said, that hero example would be impossible to show in anything other than plain HTML as you would need a react version, an Angular Version and a Vue version. It is a demo of what it can do rather than than how.
Apparently, because it ends discussion about CSS frameworks in a team once and for all.
That may sound absurd given tailwind classes represent single CSS property value assertions. But you can pretend and say "look we're using a preprocessor and pipeline step for our CSS" all the while you're hand-crafting your CSS like in days past, making tailwind act like a no-op submarine, and without the bad looks of inline styles.
The benefit is that you don't have to create a badass taxonomy for your frontend classes (that might or might not evolve well) just because CSS is there, especially if you're using CSS-in-JS anyway and might prefer relying on code organization via JS (that you're using anyway).
CSS rules are just a redundant syntax for markup attributes anyway.
It’s a little worse in a way, since it’s another thing to learn and use and you still need a decent knowledge and understanding of CSS.
But the advantages out-weigh the disadvantages, IMO:
- provides a simpler, thoughtful, more logically organized version of CSS (with nice ways to extend it and escape hatches if you need them).
- the “CSS” —- meaning the CSS-like classes — live right on the HTML elements they style.
It makes it feasible to directly style HTML using CSS-like classes, rather than having to build and, importantly, maintain separate CSS and your own abstractions mapping classes and element types to styles.
I really like CSS, and in my personal projects I don't use Tailwind.
However, I use it in my day job, and here it is useful to us as a team. The variables combined with the tooling ensures we write consistent styles across our site. The color names and text sizes also correspond to what our design team uses in Figma, making implementing and updating designs quick.
That said, I still find it a pain to read, and we could probably have set up something very similar with CSS Custom Properties.
You could import your favourite design framework (say, bootstrap) as SCSS, change its variables to suit your design, and create any custom components using @extend:
or to the point, how is this different from just using `style=` attributes?
One of the big reason to not do that in the past was in order to disconnect the presentation from the page structure, but if you have individual classes for each individual css property, you're back at tying the two together.
You can’t do things like hover styles, media queries, etc. with `style=`.
Re: separating presentation from page structure, Tailwind is designed around the opinion that that whole idea was mostly wrong, similar to how frameworks like React brought back the `onClick=` attribute when everyone was saying “unobtrusive JavaScript” was the best practice
Wrote about this in depth a few years ago shortly before releasing Tailwind, can read here:
Tailwind is not just a set of predefined classes (like bootstrap), it is a code generator (with plugins and flexible even without them).
For example, if you define class `.myclass { @apply bg-red-100 hover:bg-red-50 active:bg-red-200 p-2 md:p-3 xl:p-4 animate-pulse; }`, tailwind will generate quite a big css ruleset, with @keyframes and @media-rules. And all of these media-rules are extensible, so if you want a different size for "md" or new suffix, just define it once in config and use everywhere.
Tailwind is just a CSS design token and utility class library at its core. It’s the Bootstrap of the 2020’s.
Regarding design tokens, they are taking notes from 1996, and they realized that it is much more computational efficient to describe your component visually with inline styles compared to loading separate style sheets.
Tailwind and CSS design tokens in general make it easier to make smart, efficient choices from curated palettes. Design tokens also create a common language for everyone who uses Tailwind - both across teams and across projects, which can break down communication barriers in large scale projects.
- It's a DSL within a DSL, which as a rule of thumb I always avoid because it means circumventing any static analysis within the main language. The rest of my complaints are mostly derived from this fundamental issue.
- It reminds me (not in a good way) of bootstrap classes circa 2011
- Unlike styled components, there is no static typing or intellisense as it circumvents the TS compiler. I'm sure Tailwind has its own solutions to this problem, but I have enough tooling to deal with already
- It's an arcane "language" that needs to be learned in addition to every other language in your codebase, which makes it difficult to onboard new devs
- A string value containing a long list of short identifiers does not make for readable nor maintainable code
- In 2033, CSS will still be around. Nobody knows whether Tailwind will be, but if "reminds me of bootstrap" is any indication, the ecosystem will not be thriving.
- It's not easy to remove from your project if you decide you don't want to use it anymore (unlike solutions that use CSS or object syles, which can be more readily swapped between frameworks, e.g. migrating from MUI to Emotion or from Emotion to CSS modules)
- None of the problems it purports to solve are recognizable to me
I know that people like Tailwind, but frankly I don't see why, and I suspect there may be some element of stockholm syndrome driving its popularity. And I'm always skeptical of any technology with culty vibes around it.
As for me, my preferred solution is either CSS modules or emotion.js, using either CSS or styled objects, both of which are fully supported by intellisense and typechecking, and are based on a 25 year old standard language instead of a 3 year old DSL within that language.
> It reminds me (not in a good way) of bootstrap classes circa 2011
Unlike Bootstrap Tailwind doesn't have hardcoded components and full on UI elements like "breadcrumb-item" or "modal-title". You want components? You build them yourself.
Tailwind is literally just utility classes with a few defaults for sizes and colors thrown in.
> unlike solutions that use CSS or object syles, which can be more readily swapped between frameworks, e.g. migrating from MUI to Emotion
You're confusing a CSS framework that actually is like Bootstrap (MUI) with a way of writing CSS (emotion).
You'll have significantly more troubles trying to move away from MUI with its rigid requirements for code structure and CSS (Typography variant="subtitle1" and Button variant="outlined" etc.) than moving away from Tailwind which is really just a collection of CSS classes that you may or may not use as you wish.
MUI to Emotion was probably not the best example, but Emotion to CSS Modules is more relevant to my point.
And to be clear, I despise MUI, and actually did migrate from it to Emotion, which was relatively easy because it uses Emotion under the hood. But what I'm getting at with the example of Emotion to CSS Modules, is that they both use standard CSS and the differences are mostly around where it's defined and how it's loaded. Migrating wouldn't be a piece of cake, but it would be mostly a matter of moving blocks of code around, and could be largely automated. Whereas with Tailwind, the utility classes are only meaningful as long as you're fully plugged into the Tailwind ecosystem. There is no "eject" button, AFAIU.
> but Emotion to CSS Modules is more relevant to my point.
And has nothing to do with Tailwind, Bootstrap, or MUI
> But what I'm getting at with the example of Emotion to CSS Modules, is that they both use standard CSS
So does Tailwind
> Whereas with Tailwind, the utility classes are only meaningful as long as you're fully plugged into the Tailwind ecosystem.
Same with MUI. Again, it's much harder to migrate off MUI because it literally binds you to a very specific way to structure your components and other components inside those components.
Hell, you can't even move from MUI version X to MUI version X+1 without half of your site breaking.
You want to move away from Tailwind to something else? Bring in that something else and use it alongside while you replace your components written with Tailwind classes with that something else. Because Tailwind is literally just CSS.
So you’ll come up with hypothetical reasons you don’t like it, instead of just trying something which is loved by many people, and seeing if you actually like it.
I do not like it in a boat, I do not like it with my coat, I do not like green eggs and ham.
Well, I've had to stop people from introducing it into our projects before, so it is something I have to deal with. I won't passionately advocate against it, but I did enough research and have enough experience to recognize when something will not be worth it to me. And I don't know why you would classify these legitimate points against it as "hypothetical," because as far as I can tell they're solidly grounded in reality.
The central argument of its value seems to be "you need to try it to understand it," and I just don't find that to be a compelling argument. It doesn't claim to solve any problems that I recognize in my current workflow of writing well-scoped styled components.
If you’re not going to try it, that’s ok, but I think it would be fruitful to try it for 20 mins, they have an online playground. A huge advantage of tailwind is you can copy/paste another tailwind example from anywhere and it will just work on your site. (It’s like copying text from one site to another!)
I remember the arguments in 2008 from people who insisted they needed a physical phone keyboard, like a blackberry. They need to actually try a good touchscreen, vs provide untested arguments why physical keys are better. (Better in some ways? Sure. Overall? No.)
At some point it becomes an ego thing, people don’t want to admit their initial impressions were shortsighted. And it’s ok. The better experience wins out.
The problem with that argument is that once you've sufficiently "tried it," you've put so much effort in that you're stuck with it, and since there's no way to eject, you're more willing to justify it to yourself as worth it. This is stockholm syndrome.
You're right I should try it, and maybe I will try it on some throwaway project eventually, but it's not a priority and I have no interest in adding it to ongoing production projects.
I was very open about the fact I haven't tried it from my first sentence, which was "here are the reasons I have no interest in trying tailwind."
I would have more interest if someone could explain a compelling problem that I recognize and that Tailwind solves. But nobody can do that, it's all just "you have to try it [and learn our initiation rituals] and then you'll understand!"
> since there's no way to eject, you're more willing to justify it to yourself as worth it
You honestly have no idea what you're talking about, and you're making that very clear.
Lots of people in this thread have used tailwind as well as many other CSS maintenance strategies, and almost all of us prefer tailwind.
Not that mass approval makes it "right", but you certainly can spend 3 days writing your next greenfield project with tailwind, and then if you want to "eject", it would take all of 20 minutes
> You honestly have no idea what you're talking about, and you're making that very clear.
Rudeness aside, I made it very clear from the beginning that I haven't tried Tailwind, and my criticisms were based on fundamental principles that could apply to any new tech.
Of course I don't know what I'm talking about when it comes to tailwind - I've never tried it. I hoped my points could be read as constructive criticism as to how to convince someone to try it, rather than an invitation for the cult-of-tailwind to pile on with insults and appeals to authority of influencers pushing foot-in-the-door sales tactics. It doesn't exactly instill a lot of motivation to join the ecosystem, and it only proves my point about the culty vibes around it.
Fair response. If you don't know what you're talking about, why are you making assertions that are incorrect, rather than asking "what's the process for ejecting if I try tailwind and don't like it?"
You just freeze the minimal CSS file generated by Tailwind (it tree-shakes out any class selectors for tailwind classes you're not using) and remove all tailwind dependencies; you don't have to make any more changes to your code, you're just left with the classes you've already added to your markup, which still work. You can gradually change those out however you want, at your own pace.
Also, using tailwind doesn't mean you can't use CSS the way you're used to in addition to the tailwind classes, though it's possible you could end up with specificity issues if, for example, you've added a tag selector, like `div {...}` which is overridden by a class you've added to a specific div in your markup. This is pretty straightforward though, and if you've been using CSS for any amount of time you'll still find you have to think a lot less about specificity than going all-in on your own CSS
Learning tailwind is 30 mins in their online playground. (It’s one traffic jam on your commute.)
There are countless blog posts and threads listing the advantages, but it’s better to spend that time using it and you won’t have to take someone’s word for it!
Thanks for the link. The twin.macro is actually a compelling argument against my favoring of CSS-in-JS, because it "combines the best of both worlds," but for the same reason, it also increases complexity by adding yet another interlinked dependency downstream of Tailwind.
So, how's this: I promise I'll try the playground for 30 minutes sometime soon. :)
But I don't believe that's enough to learn it, because you'll still need to be constantly referencing the documentation to remember all the weird little utility classes. That's why I didn't like Bootstrap - it required memorizing some esoteric language that is totally useless ten years later. Whereas the CSS I learned in 2004 is still (mostly) just as useful today as it was then.
The reason I'm conservative in the technologies I adopt is because I've been doing web development for nearly 20 years now, and I've seen five or six cycles of fads begin and end. Very few technologies stand the test of time, and it sucks if you end up stuck with one of them on the tail end (heh) of its hype cycle. Or sometimes it's not even the end of the hype cycle, but just a major upgrade to a new version that requires you to change hundreds of files in your codebase (this is the main reason for my dislike of MUI). I don't know if Tailwind has that issue with upgrades, but I know CSS certainly does not.
I’m similar, webdev since the pre-jQuery days, and hate framework churn. Tailwind is kind of like jQuery in that it gives a consistency layer that CSS was missing (just like jQuery gave a better way to interact with the DOM).
Either way you find it, glad you’ll be giving it a shot!
I had the same feeling about bootstrap (and I also never really bought into it when I used it back in the day; I figured something better would come along)
Tailwind is not that. Tailwind might disappear over time, but only because future improvements to CSS might borrow ideas from Tailwind
Have you tried it in earnest on a project? I was of the same opinion but once you try it (with VS Code and Tailwind plugin) it's hard not to fall in love with the ultra fast feedback loop and well defined colour palette.
How can the change CSS feedback loop get any faster? I change a CSS value and it automatically updates in the browser, seems like about how fast it can be.
Creating a "well defined color palette" is usually a part of the design-process when creating a new application/website. I understand that some people prefer the Bootstrap-process of already having a bunch of colors defined for you up front, but it certainly doesn't suit every project.
Plus personally, I don't miss the times when Bootstrap was trendy and every website basically looked the same. I like the individuality of the framework-less web.
Might be. I was replying to the "it's hard not to fall in love with the ultra fast feedback loop and well defined colour palette." part where I get the impression they like that they don't have to define their own color palette and just use the one provided.
Oh, maybe it wasn't clear then, you can use the default colour palette, and then gradually swap out the built-in class names with the colours you want them to actually map to, or create your own custom colour class names as well.
At the very least it should save a step or two compared to building the design system out yourself in a new project
It's definitely not for everyone. I'm on the fence, for example, I do like the utility based approach, but TW breaks a number of my common workflows. For example the feedback loop - I can't quickly add or change a few classes in devtools, since TW might not have compiled those yet. I can't also easily refer from the html code in devtools back to a component that rendered that without clutches (VueDevTools etc).
To the people moaning about “what is the benefit”:
You ship less CSS, especially the more complex your app gets. A app built with custom classes ends up growing linearly, often with lots of repeated css code. With Tailwind, the amount of css added always ends up being logarithmic.
It also ensures consistency across the codebase in both naming conventions and styling (e.g consistent spacing ratios) without seniors having to be vigilant about policing PRs.
Finally, the majority of people who have tried it find it quicker and easier to code with. Which means you can ship more functionality in the same amount of time whilst maintaining the same or better styling standards.
So there are three of the engineering benefits to using it. If you don’t like it and don’t want to use it, fine. But stop pretending that no one can give you good engineering reasons that justify it’s existence.
I think Tailwind isn’t that great if you’re really proficient with CSS.
But if you need backend devs to fiddle with styles or have some teammates who aren’t senior css magicians then it really shines.
Anyway I’m not entirely sold, I feel good old Sass is way better than styled components and Tailwind, but only in right hands. It’s painfully easy to write unmaintainable styled components and Sass/CSS.
A reminder that if you’re having trouble naming divs, you have too many divs. Everywhere I’ve worked that used tailwind just kept adding wrappers around every ui element since they didn’t know css basics.
Have there been any comparisons written about Tailwind's performance vs thoughtfully selected CSS? I've been writing Tailwind exclusively for the last year or so and I haven't noticed anything in particular, but I find that using utility classes causes me to lose an awareness of the cascading nature of CSS. Aside from the filesize bloat due to the bigger HTML files, do long and highly-repetitive class lists slow down style parsing or DOM interaction? And if so, would @apply directives have an advantage over class lists?
I can't say much about selector performance besides that class selectors (.class-name) being very fast, opposed to complex selectors (like "#some-id > div a"). Of course less classes applied means less work for the browser, but the real cost is the complex selectors
With regards to bloated HTML, that might seem the case but since you reuse the same class-names everywhere in your app (and tailwind JIT removes non-used classes), compression really cuts down on the size of your bundles. It just looks bloated in the web inspector. This is a disadvantage, it is a bit hard to debug HTML with all those class-name strings around, although I would say web-inspectors should just truncate "class" attr value
With bundler performance it adds some overhead (tailwind has to go through all your .js/tsx files), but in my experience not noticeable
Isn’t it ironic that the first section talks about extended color palettes, but their website does not honor my CSS (prefers-color-scheme: light) preference when I visit that page with JavaScript disabled. There is a moon icon in the upper right, but it’s broken without JS.
I’ve read a decent amount about Tailwind and I really appreciate what it offers. I see all the claims of people who were unsure, tried it, and fell in love, and I don’t doubt their experiences. It seems great.
The sad reality for me: I am very very productive with a mix of inline styles and Emotion/Styled-Components! I genuinely enjoy writing CSS. A library like MUI gives me a foundation of consistency and helpful utilities, but I love the ability to drop back into CSS and express ideas in a universal styling language that any experienced frontend developer should be able to understand. I move fast. I can show my code to others for feedback and they’ll be able to contribute. I genuinely enjoy it.
Tailwind does offer some ways of writing CSS but my understanding from the docs is that they are discouraged. They certainly don’t give the ease and quick feedback of in-line or Emotion.
I’m also highly suspicious of the longevity of the utility class approach and its shorthand. It makes me think of my experience with Slim templates in Ruby: it felt like a force multiplier at the time but but only other initiates appreciated it and it looked like absolute gibberish when I came back to it years later. These projects would have been better sticking with ERB since it’s the HTML everyone knows sprinkled with Ruby where needed. My initial impression of Tailwind is the same: “this looks crazy but everyone swears that it’s a breeze once you learn the syntax!” Will the end result be the same?
Again, no disrespect to anyone who enjoys it. I fully recognize the many drawbacks of inline styles and Emotion, particularly around performance. I’m currently lamenting the incompatibility of Emotion and React Server Components. I plan on giving Tailwind a fair shot soon and I’m open to having my mind changed, but I do hope it has more staying power than Slim templates.
This echoes my feelings exactly, but another aspect of it that turns me off is evident in the walking-on-eggshells qualifications you need to add to your comment to avoid being attacked by its "initiates."
In comparison, my experience with adopting TypeScript was one where my initial skepticism was met with people clearly explaining the benefits of using it. And TypeScript has a similar aspect where you need to try it to really understand its benefits, but it also has clear value propositions that can be described and considered on their fundamental merits. Tailwind does not seem to have the same kind of benefits, so the arguments boil down to variants of "with us or against us" and "look at all these people using it." And from that perspective, I see a lot of people who I respect a lot who are _not_ using it. Whereas I never saw many experts saying "TypeScript sucks don't use it" - they just quietly adopted it because type safety was important to them on its merits.
I agree, it feels like it was a reaction (no pun intended) for the CSS-in-JSS trend which started in React and complicated with Webpack pipelines. In my mind, Tailwind is just "Bootstrap for CSS-in-JSS."
Honestly, as much as I disliked the CSS-in-JSS trend, it did solve a reasonable problem with React — one which Vue and others had solved with their SPC.
Exactly. Tailwind and CSS-in-JS are both a reaction to the limitations of React JSX and how poorly it treats HTML and CSS.
If Vue/Svelte had gotten the popularity React has you would see a lot more people realizing that SFCs and scoped style blocks solve most of the problems people poorly solved with CSS-in-JS.
Tailwind has some other benefits to it like good token setup and ability to copy paste from project to project and have it just work, but the mess it makes of your templates and the difficulty of then editing it down the line doesn't make those benefits worth it.
I would say it is more the lower entry barrier for devs who do not want to spend time on learning css so they are not that relient anymore on a dedicated frontend person
I'd say to be good with Tailwindcss you actually need a pretty comprehensive understanding of CSS already! Originally I'd written it off as "CSS for backend developers who hate writing frontend code" and I was a diehard CSS purist, but actually using it, it definitely has a great DX for people who love writing component UI/styling.
I believe it is an even better match if you have components in a template system (without jsx), because you can just copy the html without maintaining some css in js. You can quickly have something similar to components in Django thanks to this.
No, it’s more so because Adam and Steve are super cool and involved frontend dudes.
Steve was the personal designer for Taylor Otwell and Laravel long before Tailwind. Steve has created all the most recent Laravel designs for many years.
Prior to starting Tailwind with Adam, Steve wrote up a bunch of fronted design standards and published a book called Refactoring UI. In that time frame, he also created a bunch of free open sourced sets of SVG icons called HeroIcons. HeroIcons were a direct replacement and improvement over Font Awesome.
Somewhere in that timeline, Adam and Steve put everything they had created together into a single project, and that was called Tailwind CSS.
Being on the ground floor of Laravel and the open source community totally helped with their initial exposure. All the things I mentioned above were also popular topics here on HN a year before Tailwind was created.
I don’t understand the downvotes lol.. I’m sorry if I come off as staning for Steve, but I feel that he deserves his credit. You can see his design principals being used on every Shopify checkout page, and every Stripe dashboard page.
I personally met him pre COVID at Laracon, Chicago. I bumped into him during lunch, and he was super cool and open to chat.
I have no affiliation with him, and have only followed him on Twitter after we met.
React was unique in that it didn’t have a solution for CSS out of the box. Vue, and the current gen frameworks like Svelte, include CSS right inside the component.
Same here. Started a new project at work using Vue 3 and absolutely loved it. I ran with tailwind looking for sanity after being on a few teams/projects where the CSS was all fuckered up. Now I get to roll out features with a perfect UI. It is fun.
For the amount of time that a typical web app lives, raw CSS is just a resiculous waste of time that sucks the joy out.
On the contrary, I think it is good for retention, so long as you gain enough mindshare soon enough. Tailwind has become something of the defacto CSS tool for modern front end development. I don't think Tachyons or Basscss (or other earlier atomic CSS libraries for that matter) ever caught on despite being the same idea, and neither were marketed as aggressively as Tailwind.
I’m surprised and a bit puzzled at what they’ve done with logical properties: they’ve completely ignored the existence of vertical writing modes (apart from single-corner border-radius, where you can’t), and named things in such a way that it would be ugly and inconsistent to subsequently support the block axis, since they’ve basically renamed inline-start and inline-end to start and end.
CSS is a tool as Jeff Atwood would say designed for pit of despair[1]. Which means, the default path is making mistakes and failing horribly.
And Tailwind CSS is a tool which is designed with Pit of Success in mind. This means, the default path is success and not anger and despair.
Not to mention, it doesn't have any performance taxes. And also, unlike other CSS framework, you should know CSS in order to utilise Tailwind CSS properly. People learn more about CSS by using Tailwind unlike many other CSS frameworks.
I love tailwind. I would like the addition for perceptual color palette. I do it by hand with HSLuv and I redefine the colors, but having a built in way to build light on ark and dark on light contrast that look good regardless of hue would be cool.
My understanding is that that's a non-trivial problem. You'd likely need some sort of AI system to do it, since the perception of colour isn't something that can be simply modelled.
Coming from bootstrap, I would say if you are not using tailwind, you are missing out. It is just breathe of fresh air.
But, but, but, seems like almost all the project that use tailwind ends up looking like linear. Not that I blame tailwind for that, there was an era when almost all bootstrap projects looked similar, I think it is the same thing.
I just tried to switch a simple quick site from bootstrap to tailwind and backed out. It seemed like I had to build my base template from scratch whereas with bootstrap they give it to me for free.
With tailwind, is there an easy way to start with a nice simple working responsive site that I can tweak?
Great to see yet another Tailwind version. I’m a huge fan. CSS is always a “get it over with” ordeal for me, and Tailwind allows me to finish the job in the quickest way. And Tailwind UI has been one of the best purchases I’ve made in the past year.
It's hilarious how every Tailwind thread ends up looking the same somehow. Use it if you want. It's just a (very good!) tool which some people find useful.
Thanks Adam and all the Tailwind contributors for your work!
There’s fundamentally two ways. First is what you just stated with the modifier. The second way is to redefine the colors with CSS vars and then write a normal CSS media class that re-wires what var means what color.
That's what I would do and use the dark: classes for adding borders and other styles that make dark themes work. F.e. shadows and floating cards doesn't really work with dark themes but does with light colors.
The spec authors should be looking at the popularity of Tailwind and be thinking of how to enhance the style attribute. Then Tailwind really could mostly be a bunch of CSS variables and inline styles.
Tailwind depends on @apply in PostCSS to function, something that was never officially proposed for CSS, but has been killed by its author and we know for sure CSS won't do, for the reasons the author of the original @apply idea lists here: https://www.xanthir.com/b4o00
So we have known all along that this will never happen. It was rejected for some very good reasons before Tailwind began.
The only time I can imagine coupling content and styling together is if you have mostly non-repetitive elements in the content (rare, I think, maybe some very "designed" landing page, or whatnot), or you have other ways to repeat the elements without writing the styles out each time for each element. (And at that point you've just moved the problem of having to invent names for CSS classes to having to invent names for bunch of "components" and their properties)
This is achievable in a much nicer way with SFC frameworks like Vue and Svelte where you also get scoped styles and other benefits. One of the reasons Tailwind is so popular is that so few developers know anything other than React.
Of course it's just class names, what I mean is that if fewer people used React and more used Svelte/Vue they would feel less need for things like Tailwind or CSS-in-JS.
My argument is that React is actively bad for writing HTML/CSS, and therefore people came up with clunky solutions to get around those limitations. Certainly Tailwind is more than just a solution for React, but a large part of its popularity is due to it.
> they would feel less need for things like Tailwind or CSS-in-JS.
Why do people keep mentioning Tailwind and CSS-in-JS in the same sentence?
And no, Tailwind would still have its place even if Svelte appeared first because instead of writing the same styles everywhere you'd still want to extract them into a file, and have sensible defaults for them.
> Why do people keep mentioning Tailwind and CSS-in-JS in the same sentence?
Because one of the biggest arguments for each is scoping styles to a component instead of the default global cascade.
> And no, Tailwind would still have its place even if Svelte appeared first because instead of writing the same styles everywhere you'd still want to extract them into a file, and have sensible defaults for them.
Writing same styles everywhere? I'm not sure I understand what you mean, that isn't related to Tailwind or frameworks. Sensible defaults are just design system tokens, those are usable in way more styling approaches than just Tailwind.
I'm not saying Tailwind wouldn't exist, I'm saying it wouldn't be as wildly popular as it is now. React's lack of CSS features has encouraged a generation of frontend devs to simply not learn CSS fully. Sure you need to know some CSS to use Tailwind, but in many cases people just copy-paste Tailwind templates from elsewhere (another benefit of Tailwind) and don't actually understand the styling. I see Tailwind classes that do nothing in the wild all the time.
> Because one of the biggest arguments for each is scoping styles to a component instead of the default global cascade.
Escaping the global cascade has been on everyone's mind since forever. BEM, one of the lost popular ways to try and scope CSS to components, was invented in 2006: https://en.bem.info/methodology/history/
> The problem with Tailwind for me is that Mr Wathan misrepresented « Good CSS » in his essay. His examples are BAD CSS, not good CSS. He then sets out to correct a problem with CSS that HE created by writing dirt poor CSS. `.author-bio > div > h2 { color: red } is NOT good CSS. The div part has no reason being there (why would the div change the color of the title ?). After presenting this auto-created problem, he sets out to solve it with BEM, where you need untold numbers of classes for everything. So now, CSS has a naming problem, created to solve a non-existing auto-created CSS problem. And Tailwind now solves this pseudo-problem.
Apart from this, the thing that really bugs me is that every advantage claimed (apart from one) is also non-existing because if you do your CSS right, the same claimed advantages arise in pure CSS. Design tokens ? No need for json, custom properties are all you need. Specificity ? Cascade layers, pseudo-selectors are here for you.
The only "advantage" I see is the possibility of working in one file only rather than a couple of files. And that, for me at least, is not a real advantage but only a justification for being lazy. There's no way the price of all these processes and dependencies complexity are worth the laziness-added value.
Does someone care to "prove" me wrong here ? At least, can someone engage these arguments ?
Looking forward to it!