If you work in the front-end, you've probably heard a lot about TailwindCSS, a CSS library, much like Bootstrap. Much unlike Bootstrap, however, Ta...
For further actions, you may consider blocking this person and/or reporting abuse
Ah, if only there existed search and replace...
Or just create a custom color palette in your Tailwind config called 'brand', set your colors and be done with it. If brand colors change, update the color palette - easy.
Right, but branding is more than just color palettes. It's also - do we want the corners to be more round or less round on buttons. What if we want to have switch toggles instead of checkbox toggles? What if we want a specific page to look like a specific brand that isn't our main brand?
(This happened with a client of ours which sold Louis-Vitton gear -- Louis-Vitton wouldn't allow them to sell LV stuff on the client's page unless the pages that they landed on were branded with Luis-Vitton's color scheme).
Right, and Tailwind offers plenty of flexibility to manage these things via your config if required. It's not just a static set of a utility classes that cannot be altered without digging into the source - override the default border radius settings, or create your own presets for your brand if need be.
The exact use case in your article and comment (branded button) is mentioned in their documentation somewhere (I distinctly recall reading it), and I'm sure they suggest creating your own branded button class using @apply. If your branded button border radius requirements change, update the class, if the new border radius is outside the presets, then extend the config and then update the class.
If a specific client demands you brand their pages, then add a color palette for their brand, and make sure those components switch out
brand
forclient-brand
where required? Tailwind certainly doesn't stop you from using colors outside their default palette - I've only ever used the provided colors for non-brand accenting (e.g. greens for success, reds for errors, etc) and the grays for text/borders.In regards to moving to switch toggles from checkbox toggles, you're likely going to adjust the layout of the component somewhat, or perhaps add an additional container element ensure things are aligned correctly - I've encountered this exact type of scenario many times over the years - more often than not, it's more than just a few lines of CSS.
And if you're building a modern application, you'll likely have a checkbox component or at least a rudimentary template/partial to stay DRY - which will prevent the need to update every occurrence of that particular component across your application - again, something which I believe they touch on in their documentation.
To be frank, I wasn't a fan of Tailwind at first, and I certainly don't think it's the "be-all and end-all" solution - but after using it on a few projects I've come to love what it offers out of the box (especially the font, text sizing defaults, colors for accenting, gray set, grid, gradients, screen breakpoints, space-between, etc) with the ability to extend/override anything I desire if the case arises.
It's really allowed me (as a full stack developer building business applications) to start flowing without having to worry about any of aforementioned when I just want to get something clean, consistent and functional on the screen.
With all that being said, if you're creating basic web sites, landing pages, marketing pages - or complex applications without a component framework - Tailwind probably isn't the solution you want.
The problem is that the minute you start using @apply and using semantic classes again, you're moving outside of Tailwind's "utility classes" paradigm.
Now - while I could argue that "you might as well just write out the CSS" there is some value to alternative syntaxes. There's all sorts of tools for transpiling non-standard code into standard code. Typescript -> Javascript, Coffescript -> Javascript, ES2015+ -> Babel -> ES5, Sass -> CSS, SCSS -> CSS, LESS -> CSS, Knex -> SQL...
It would be an interesting -- and I think worthwhile! -- project that would use only @apply in CSS files and then transpile them (maybe with SCSS) into the appropriate CSS around the same time you're transpiling all those "$" prefixed variables, Sass functions, and "&" notation. If you want to have a tool that is designed to make
@apply px-5
shorthand forpadding-left: 5rem;
then that would be an interesting tool that wouldn't break semantic structure.padding-right: 5rem;
I've had the same thought - and it's essentially what I've been playing around with on a Svelte project with Tailwind's JIT mode. All the component markup, script and style tags are self contained in their own .svelte files - using @apply in classes within the style tag.
Certainly makes the mark up a lot easier to reason with when you have a lot of nested elements and many utility classes applied - I won't argue that fact.
The only issues I can see are:
1) Each components generated CSS classes are included in their own style tag within the head element, so I'm not sure what sort of performance issues this might cause if you have a lot of components.
2) Any class used with @apply within the svelte components, gets marked as "used" by Tailwind and ends up being compiled into the stylesheet loaded on the page. So if you don't use those utility classes in the mark up (and only in classes), they are essentially dead weight.
I'm sure neither issue would be difficult to resolve - either way, it's interesting none the less!
See, and this is the problem with writing a very opinionated article without understanding it. Tailwind is trying to get you away from using the @apply method. They have mention that in multiple tweets, articles, and videos.
Instead of @apply bg-blue-500 for your brand you can easily set a color theme of "brand" in your config then use your theme in the css. ie:
.button {
background-color: theme('bg-brand-500');
font-family: theme('fontFamily.brand');
///and any other variable you have set in your tailwind config.
}
then you just change your tailwind.config when you need to and you are done. Same as using a sass variable etc. It's not that hard and completely follows a dry principle.
How is this an improvement over CSS variables though? Why not var(--color-bg-brand-500) ?
A properly designed stylesheet tags an outer element with whatever the thing is. You then can assemble the object, and only light markup is needed for child elements because you can reach in with the stylesheet and control them. I had a job interview where they had "code standards" for doing css where you weren't allowed to nest tags to control them. Everything had to be top-level. Idiotic.
When you are writing code with frameworks, it's easy to use the framework to be absolutely consistent about how the children are constructed, so the markup can be very minimal. It makes it easy to read when the css tags are only used when they actually control some behavior, and they read semantically rather than as named inline styles.
It is more examples, that Tailwind will make your project doomed. It's very limited to strictly one style of UI and modifying it can be harder according to project design. Trust me, web development is not only greenfield project with fancy ui.
Sometimes you need reusable components. It's hard to make it with Tailwind.
He seems to blame the tool rather than using a better methodology for writing a better style
Color is not a brand, after all. And that could be a "hack". You don't try to win.
But that's just it.
Search and replace will only search and replace based on text strings. Which is great if the only place you use "text-blue-500" is in components you want to change.
That's the thing about utility classes - by definition, they're the same name everywhere you use them. So if you wanted to change "text-blue-500" to "text-red-500" in buttons -- and only buttons -- you'd have to find, and then manually look to see if it's a button before you replace it.
On the other hand, if you have a .button class, or even better, a .branded-button class, you can just change it in one place.
Find and Replace might be useful for changing variable names that are already fairly unique, such as from "my-button" to "branded-button" but it's not useful if you're trying to change, say, only some instances of "float-left" to "float-right".
But this is exactly how you should be using Tailwind anyway. If you are applying utility classes all over your html to make your buttons then this is akin to using inline styling. The power of tailwind is that you have an entire set of utility classes that allow you to make small tweaks on the fly because your designer wanted this specific button to have juuuuust a bit more margin-top and be fullwidth at certain resolutions, but you can also continue writing CSS as normal.
I see Tailwind as a utility. It's not there to replace CSS, but compliment your workflow so you can get on with building components.
Anyway, judging by your article and your replies in the comments you've made up your mind about Tailwind and that's ok, but there are many developers that are in favour of it, myself included. Best of luck!
I'm sure that you could use Tailwind that way, but at that point - why not just use small tweaks in inline styles instead of using Tailwind's classes? Inline styles also have the advantage of being higher CSS priority than class definitions, so you get exactly what you want right away.
But then again, the problem with "if you use it this way" arguments is that they're different from "if you use it as intended." You can see from the Tailwind's own documentation that the intended purpose is to replace CSS.
I'm not saying that utility classes aren't useful. I'm just saying that they shouldn't be used for everything. And they certainly shouldn't need all the tooling overhead that comes with tailwind.
I don't know why you keep saying this is not how Tailwind is intended to be used. The page you linked to is titled "Utility First". I infer that to mean the expectation is you start with utilities, and move to something else if you need it. Practically every word on that page seems to back up that inference.
Further down the page is a section titled "Why not just use inline styles?" which explains what they see as the advantages of utility classes over inline styles. You didn't even acknowledge their reasoning in your article.
The section after that one is "Maintainability concerns". This is where they expressly state that using apply to group styles together is, actually, using it "as intended".
Again, it seems clear to me Tailwind's intention is you would build styles using utility classes first. After some point, they completely expect you to group at least some of those utility classes into a "bigger" class. You seem to think this grouping completely negates the benefits of using utility classes, and that you might as well write it in CSS.
The documentation page that discusses this in particular is Extracting Components.
I'm always wary when somebody says a newer syntax is "hard to read". It's definitely possible to write code that is hard to read. But how can you say it's hard to read when you've spent years training your brain to parse some other syntax. Readibility is subjective with things like this.
For example, I found the example line in your article pretty easy to read. The purpose of
md:h-32
andlg:h-64
are actually more obvious to me than the media queries. But I do agree the long horizontal line harder to read. But you don't have to do it that way.I like your analogy of using single letter variables. But I don't think it's the same thing. These are just short forms of CSS properties. They are clear and documented.
I'm not sold on Tailwind myself. But if your conclusion is that it "provides no value", I don't think you argued it that well.
Eh... If that is your interpretation of Utility First, then I can't fault it.
It wasn't mine, for a number of reasons, but you may have caught me out on an assumption I didn't know I was making.
See, I thought that "Utility First" was referring to a coding philosophy, much like the philsophy of "Mobile First" -- you code for the mobile site first because the mobile site will always work on the full web-page, but not necessarily vice versa.
Mostly, though, the reason why I don't think your interpretation is correct (Start with utility classes, then move away from them) is because almost every example on Tailwind's site is about how you can convert from semantic classes and CSS/SCSS to Tailwind Utility classes. If anything, Tailwind seems to suggest that CSS is a pain point that needs to be resolved and that utility classes are the solution.
I agree that Tailwind might have use with rapid prototyping, but there's no real instruction on how to move from rapid prototyping to final product - You write Tailwind, you distribute Tailwind.
I remember a similar argument from the author of Clojure about how Clojure (and other Lisp-like languages) were "hard to read." He said: "I don't know how to read German, that doesn't mean that things written in German are hard to read."
But we can admit to ourselves that it is harder to learn certain languages than others, especially for an English speaker. And we can ask questions: Does this have a similar grammatical syntax? Does the language belong to the same family, does it have cognates and loan-words? Does it use the same sounds and tones? Is the alphabet the same?
In the case of programming languages, we can ask similar questions:
In this case, my criticism of Tailwind being "hard to read" deals primarily on the fact that the syntax is not expressive, and indeeds, chooses terseness over expressiveness. Back in the days of limited memory, sometimes a terse command was better than a long one, we still use "cd" for change-directory and "ls" for "list" in most Unix shells, but no such memory problems were at play here.
It's also hard to read because it's embedded inside HTML, listed horizontally, rather than vertically. Now I'm not saying that it would be as hard to read as if we did styles in PDoublePrime but compared to the default of regular CSS, it makes it hard to read. Additionally, since you're no longer adding your own semantic class names to your HTML, it can be hard to tell by looking at the source exactly what element in the HTML code you're actually looking at when you debug it.
Re: @tofraley
At the risk of taking sides (trying not to as I don’t understand TailwindCSS enough), I will say this: Usually when I encounter situations like this, I’ll bring it up to the designer. When that happens, at least in our case, it’s usually a misunderstanding (but not always). For example:
Only pointing this out since, on the development side, all too often I’ve found developers simply matching the comps precisely without first ensuring that the change was intentional and (in this case, accidentally) creating one offs that ultimately weren’t really intended. 😊
That's not true, you can use 'primary', 'secondary', etc.
tailwindcss.com/docs/customizing-c...
If you're relying on find/replace tools to make hundreds or thousands of edits to your codebase because of a change like this, it's still a problem. Everyone has seen (or caused) a scenario where a find/replace has gone wrong and replaced the wrong thing by accident, e.g. replacing "Arial" with "ArialBold", but accidentally creating instances of "ArialBoldBold" because your find-fu was off.
However, if the code was following DRY principles, there would be very few instances that needed to be changed, so would be far more likely to be handled better.
Not the point though. The point of CSS ,and/or SCSS for that matter, is too make styling more structured. If you need to do mass search/replace that might be a first cue.
Naming it primary, secondary ect. would be a way to go instead.
Search and replace still means you’re changing multiple things. More changes mean more chances of things being misaligned and it requires more testing. On an enterprise system, this increases the regression cost.
Damn... I wish we had:
Search and replace
The ability to use alias for colors, such as text-primary-500
The ability to abstract groups of tailwind classes into its own class. For example, with a keyword called, I don't know, @apply or something
Too bad we don't have any of those things and thus obviously by direct deductive argument Tailwind sucks...
@Ranieri Althoff, if you have never introduced an error via search-and-replace I salute you for your charmed life as a developer!
Use @apply and use same style everywhere. In react Vue we use components so we can just change style in one Component and it would work elsewhere.
if only all developers were careful enough to use search and replace responsibly
@rsa - I think you have summarized why using Tailwind is a bad idea. You have ended up creating CSS that describes the text color blue, not what you want your style for a particular element to look like.
There may be places where I want to continue using "text-blue-500" in other styles.
When you have a Button comp… Easy. Maybe variant:red is not a good approach. variant:primary
problem solved. works also for all other comps. Don’t see the problem here from the author.
We do we need constant values if we have search and replace...
Then don’t use functions at all
Lol I've been seeing hate articles with things that are non existent problems
And besides if you are using a js framework or in my case laravel components it's as easy as changing one file
The author was referring to the number of code changes.
With standard CC, you have to do the change in just one place.
The whole issue with the frontend community, in one comment. Well done.
Search and replace does not work all the time, as sometime you have to apply logic to it. Maybe you want to update only 763 elements.
In that case, you will still need to go one by one changing the class if you just put "button" in all of them.
You shouldn't. If the class is .button, and the .button class is only defined once, then one change to the .button class definition in your css should apply to all items that have the .button class.
I should have been clearer in my example by using something like ".branded-button" but you do see how you don't have to go in one by one, right? Because you're not changing what the class is named, only what the class does.
You often create a component for these scenarios, making different button components and reusing them. This pattern follows DRY too and also gives you the tooling and productivity of tailwind.
If only this was possible and such an easy change, you can't replace every instance of this in your app, what if it applies only to buttons/etc.
Yeah, because everybody want to use find/search every time when the want to change something in all places xD
You assume you want to replace all instances of text-blue-500
A bold article to write seeing as how it seems Tailwind is the starchild of CSS these days. But, an article I think needed to be written. I share most of your views on Tailwind.
I even tried to start a project from scratch using Tailwind because I thought "it's really popular and it looks really pretty - maybe I just need to buckle down and use it". It took me a few days until I came to your same conclusion - why don't I just use plain CSS (or in my case, SASS since I was already using it)?
It seemed silly to write:
when that's basically the same as:
and yeah - it's a lot less clear exactly what's happening. In my book, clarity always trumps cleverness.
The colour scheme is nice though, so I usually import it into my SASS files.
To someone more familiar with raw css, then that's going to be more clear. After using tailwind for a few days that syntax starts to be easy to understand. I'd argue actually much easier to know what happening than long lists of cryptic css commands.
A few:
w-full width: 100%;
w-screen width: 100vw;
container: The container class sets the max-width of an element to match the min-width of the current breakpoint.
How about a simple ring around a component?
Use 'ring'
In css: box-shadow: var(--tw-ring-inset) 0 0 0 calc(3px + var(--tw-ring-offset-width)) var(--tw-ring-color);
ring-inset --tw-ring-inset: inset;
All of this can be done using other libs and dependencies, but tailwind sure makes it easy.
Even the things that Tailwind "simplifies" are made more complex, and "ring" is a perfect example.
I'll admit, rings are difficult in CSS, which is why if I need to make one, I usually end up writing my own utility class for it.
But even looking at "ring" you end up having to add 5 classes or more to get your ring styled the way you want it. So "ring" ends up being "ring-3 ring-blue-300 ring-opacity-50 ring-offset-0 ring-offset-red-500" by the time you actually use it.
On the other hand, you could define all those into an actual utility CSS class, call it ".branded-ring" and just use that wherever you need it (instead of having that long string of five classes everywhere in your file.) Or even better, you could write branded-ring as a SCSS variable or a bit of styled component
css
`` code. If you use a CSS-in-JS solution, you could even have the color of the ring change according to props, giving you behavior control over style.And it would be more readable, more customizable, and then you don't have to worry about it. You would be able to write it once, and then your entire team could just import your code and reuse it - rather than every developer having to remember how to tailwind-style a ring every time they use that.
Of course, rings aren't that difficult to do, because Google is a thing that exists, and there are a dozen websites which explains how exactly to do it.
Of course, what happens when the CSS spec updates and rings are added due to popular demand? It happened with flexbox. It happened with css-grid. You never know.
You can use
@apply
, which does the exact same thing.It allows you to make a single class
.branded-ring
while still leveraging Tailwind's classes.You can do that in things like Sass, too. It's not a benefit of Tailwind.
But that's the point. It's not a good example of how using regular CSS (or pre processed CSS) is "better" in this case, it's not.
I'm not sure I follow. I'm saying that having the same feature as an existing build process doesn't make the new one better, it makes it the same. I'm saying that the claim is that BMW make better cars than Ford because BMWs have four wheels.
It's not a valuable claim in the original article.
He doesn't like/use Tailwind as he doesn't see the benefit over using what he already does.
That's fine and totally reasonable, but it's not an argument against Tailwind. His whole article is about how Tailwind is useless.
Maybe to him it is, fine, no one argues that. But that doesn't make Tailwind useless in general.
His examples are supposed to show how bad Tailwind is. It isn't. It just doesn't fit him or his way of writing CSS.
Cool, absolutely nothing wrong with that, but again that didn't make Tailwind useless or bad in any way.
lol same for that last thing
I am coming up with a better solution. Working on it now.
It's a criticism of an open source project, quite the opposite of a personal attack lol.
Go and read the full article he attacked people who use Tailwind and expressed judgements. There is difference between constructive criticism n personal attack. everything in this world has pros and cons he could not provide any rationale arguments you can critisize and bash everything and if you think people who are using are fools then make a solution better than Tailwind. Enough is enough he expressed his thoughts I expressed mine I dont know him you dont know me lets lave this.
@tanzimibthesam you can't on the one hand criticise Brian for writing an article against Tailwind and demand that he must provide a better solution before pointing out the problems with Tailwind, and then lambast him for doing exactly that.
In the field of development, we should regularly challenge the de-facto ways of doing things, and always be asking if the tool/method/etc is really the best thing to use in a given scenario. It's how the entire industry moves forward. We can question and bring forth discussion about things with articles and posts like this one. You don't have to agree with it, but it shouldn't warrant personal attacks or profanity.
He has to provide a better solution cause something is called personal criticism and one thing is called bashing and saying everyone is wrong who is using it.He is doing personal attacks and providing negative vibes. Stop defending this silly man. You dont know him and I dont know you or him neither nor he is providing a solution nor people are gonna stop using Tailwind.
He doesn't actually have to provide a better solution to anything if he wants to write a post pointing out what he feels are problems with that thing.
As for personal criticism, I can only go on what I saw on this whole thread. This involved him making some points that he felt were issues with Tailwind, and you throwing insults and profanity at him in replies. The only personal attacks I saw were from you. You're right in that I don't know him, I'm fairly impartial in this, although I do happen to agree with his criticisms of Tailwind.
As for him providing a solution (as I've said, he has no requirement to do this, it's akin to a non-driver pointing out problems with a bad motorist, or a non-artist highlighting parts of an ugly painting), he did actually mention he was working on something (and provided a link), for which you attacked him again. Those comments of yours appear to be deleted now, so I can't provide exact quotes, but I believe you did mention his proposed linked solution was a waste of time, bloated, and pointless.
Yup leave it man peace 😂
Not to re-open this, but I get a smug set of satisfaction from the fact that Airfoil has already been declared "bloated" despite the fact that A) it hasn't been written yet, B) the point of Airfoil is that you only really get value from about 9 of Tailwind's 300+ classes, so why not just write those nine in a way they can be reused and integrated?
I understand putting so much of your identity into, say, a political movement that when someone makes criticisms of the political movement - no matter how valid - you feel personally attacked. But I don't understand how you can do this with a css framework.
Amen
For us web dev isn't massive part of our business and kicking media queries into the dark abyss was satisfying when moving to tailwind.
A few things.
I wish you luck, always fun to learn something new and see how the community can alter development.
Interesting.
I would say that even if web dev isn't a massive part of your business, then why would you want to deal with Tailwind anyway? You're not really skipping out on the bulk of complexity of CSS, you're just writing CSS using an alternative syntax that maps 1-to-1 to actual CSS. It doesn't make it any easier.
Compare that to something like Bootstrap, which does make things like breakpoints, media queries, etc. easier. Yes, it's more opinionated, and "bootstrap sites look like bootstrap," but if web dev isn't a massive part of your business, then that's all you need.
And while you can compile tailwind into CSS classes (with either Sass, as you mention, or @apply) -- why would you want to? Why not just write the class directly, skip the middleman?
As for "container" - yes, it's easier to write 'container' than it is to fix max width at all media queries... the first time. But once you've done it once, it's easier to reuse. Now, if Tailwind were just a collection of commonly used CSS utility classes, I'd say that it has value, but "container" is a massive exception to the rule. 99% of tailwind is just one-to-one mappings of CSS properties.
In fact, I'd be surprised if someone hasn't written a very stripped down version of Tailwind that is just a single CSS file with "container" and one or two other cherry picked utilities. If they haven't, I might write it myself.
I work at a consultancy. The answer can be "very," depending on the client's whim. But aside from that, the main reason I might rewrite a style is because it's a bug fix, and in that case, I'd rather have to fix the bug in one place rather than fix it in 100.
Yes, but it's not like Tailwind invented the 760 grid system. If all you want is to avoid writing media queries everywhere, there are already tons of great libraries for doing that.
My problem isn't that there aren't some examples of good code out there in Tailwind. My problem is that it's 99% bad code, and the 1% of good code has been done, better, elsewhere.
The answer to virtually all of your complaints is extracted components.
Let's address your complaints one by one though:
It's WET, not DRY.
Not if you use extracted components.
You have a wrapper class you like to use a million times? Great. Extract it! Then you only have to edit it once to update everywhere. Still DRY my dude.
HTML should only concern itself with the structure of your page, not the styling of the page.
These are inextricably linked though. Ever use a modifier class to change how your component appears? Where is that going? In your HTML.
Know what modifier classes are eerily similar to? Utility classes.
For example: need to stop page scrolling when a modal is open? Rather than writing a new class to do that, just use the
overflow-hidden
class already at your disposal.It's hard to read.
I totally agree! ...So use extracted components.
Now you can write your html with a simple class like
card
, and then go to town in your CSS with:You lose a lot of the features built into standard CSS
Not true. Again, use extracted components.
It solves a problem that doesn't exist
At this point it should be obvious the problem it's solving, but just to clarify: it makes writing CSS easier and modifying your components in a logical way. Meaning, less time writing out individual css properties and values.
You want to see an obvious problem it solves?
I want a box to fill it's container, according to you I should just write plain CSS like so:
5 lines of CSS I have to write or copy/paste from somewhere. And if I want to update the positioning to be
1rem
in on each side? Now I have to update 4 lines individually.Not with extracted components:
If you want better than CSS, there are already solutions.
All of the solutions you mentioned don't make writing CSS any easier. You mention CSS-in-JS solutions, but that goes against your argument that styling shouldn't be in your HTML and you mention BEM/SMACSS but that's just a writing convention.
It literally provides no value, and tons of problems.
There is massive value in efficiency. If you want to write code faster and keep your stylesheets lean, there is plenty of value in something like Tailwind.
And I say this as someone who up until 6 months ago, refused to try out utility classes for similar hesitations. But instead of writing a big long post about why I think it's useless, I gave it a try and found a way to fit it into my workflow in a way that has allowed me to speed up my development time and still create accessible codebases for new developers (extracted components still live alongside regular CSS).
BONUS: nowhere did you mention the treeshaking capabilities of tailwind. If you're managing large-scale sites with massive style guides and you care about bundlesize, that alone is a benefit of Tailwind that I'd find it hard for anyone to argue against.
As an aside:
Personally, I don't love when people use a platform like this, where lots of newcomers to our industry frequently look to for answers, voice an ~opinion~ that borders on condescension about something that they don't seem to fully understand.
It's ok to have an opinion, or prefer different tools, but if you don't like something or don't understand the value, you don't need to pull a Tucker Carlson (???) response to it.
Yes, I've worked places where we do this. But I've also worked places where we use Bootstrap, and they're both bad ideas as far as I'm concerned. I don't think we should use modifier classes.
Who said anything about Bootstrap? I'm also very curious what you're doing instead of using modifier classes to style variants. Are you just writing inline styles? Duplicating other class styles to create a new class just to avoid this?
I guess everything else I pointed out you don't feel like addressing? It's pretty clear to me that you aren't interested in wavering from your original "opinion" here.
Best of luck navigating this industry with that mentality.
I did, me. What I'm saying is that I've worked places where we've used Bootstrap, which uses modifier classes and does basically all the things people criticise about Tailwind. Just because I've worked somewhere that does it a particular way, and where I go along with it because it's my job, doesn't mean I approve of something. So yes, I have and still do use modifier classes, and no I don't think they're the right approach.
Writing semantic HTML. Where there's an absolute client requirement to do something non-semantic, then adding classes beyond the semantic, but pushing back against it.
Everything else you pointed out was something I (mostly) agreed with.
I'm not sure why tailwind is so divisive, I've not met anyone who thinks it's "okay", we either love it or hate it.
Personally I love it and here's why:
I've always hated external css files, or one monolithic global css file. Looking at some html and then spending 5 minutes trying to work out what ut looks like was always frustrating. Sometimes SoC isn't a such a good thing. You mention Vue, but Vue's SFCs were actually made to increase the coupling of your html/css/js!
You can't do media queries with inline styles.
Tailwind let's you abstract your units. This is one of the biggest pros for me. I can use a class like p-3 in multiple places, but if I decide I want bigger spacing, I can just update my tailwind config and all of my p-3 elements will update. You mention colors, but these are just tailwind's defaults. In reality you would configure tailwind to have primary and secondary colors, e.g. bg-primary-light. Then when your cpany decides to rebrand, it's super easy.
If you don't like how you end up with super long class names, there are simple solutions. I use a simple concat library to split my classes into multiple lines. I group my classes either by breakpoint or by area (like all flex related classes) and it's really readable.
On the same topic, if you're using something like react tailwind should actually encourage you to make more components. All of my tailwind classes are neatly tucked away in low level components. My application level components are incredibly terse and have no styles or classes on them.
But the biggest win for someone like me, is I can just "get on". I don't have to worry about coming up with BEM names, or where to locate my styles, or how to keep spacing consistent, or compiling sass. I can work on the stuff I love (functionality) with the confidence that it will look good and consistent.
That said, I get a lot of the reasons people don't "get" it. But if you were to join my team I'm afraid you'd just have to get over it! 🤣
I get it.
I honestly think that Tailwind might be a good fit for you and your projects at this time.
I actually think a better fit might be a more opinionated framework, such as purecss.io/ - but forget that for right now.
If you are designing websites as a secondary consideration, if you're not comfortable with CSS, if you just want to "get on" with your structure and behavior, then maybe I can see it. In this type of scenario, I could see how Tailwind might be used as a rapid prototyping tool to try out different designs, but that once a design is settled upon, Tailwind code is rapidly stripped out and replaced with a more scalable, maintainable solution.
If I were to join your team, yes, I'd get over it. I'm a professional - if my team lead were to go with Tailwind, I would explain my concerns, state that I believe it to be a large mistake, but at the end, follow the team lead. That's what you do. Make your case to the guy who makes the call, then follow the call.
But if I was team lead, and one of my experienced senior engineers were telling me that a framework I was considering was completely worthless and would generate tons of technical debt for no appreciable value, I'd at least pause and think about what he was saying before plowing ahead.
I started writing CSS for money in the year 2000. I am very familiar with CSS and all the different ways you can use it, LESS/SASS/BEM/SMACSS, etc.
Tailwind provides a lot of value and solves tons of problems for me. I've been using it for about a year on a large Vue project. It's been really great.
You can always supplement it with hand-written CSS. Sure it introduces some problems (like anything else), but the benefits far outweigh the cons.
It's sort of ironic that the site this is posted on took inspiration from Tailwind in our own approach to CSS!
It's entirely possible that was actually me. I produce a potent musk.
I respectfully disagree! Personally, Tailwind solves a lot of problems for me. For one thing: CSS is magic and I refuse to listen to anyone that thinks they can explain it to me because I might get hexed in the process. A tool like Tailwind keeps me safe from the dark arts (this is why I always burn sage when talking to @pp).
More generally, I think critiquing Open Source tools for their issues is fair (especially if those critiques are attached to a PR!), but we also have to be mindful of the limits of our own perspective.
As a CSS or front-end expert with a team of engineers to back you up, Tailwind might not be the best choice, but that doesn't describe all of us. When I build a landing page for a charity organization (I'm not billing, I can't handcraft all the CSS for this thing), I'm definitely using Tailwind or something quite similar. Tailwind is a great solution for those solo indie hackers out there; it improves productivity and abstracts a source of complexity that not everyone has the time or aptitude to dive into!
Another way to phrase it: more or less these points would also apply to Rails or Laravel, but those frameworks solve a lot of problems.
I'm not sure anyone wants to replace CSS with Tailwind! That sure is some all-or-nothing thinking (I learned about that in therapy, hell yeah)!
You use the example of Assembly and C, but I think this is more like C and Ruby; I'm not a C developer, as much as I try to learn about it, but I can build some pretty cool stuff really quickly with Ruby. Of course, the stuff I build in Ruby is going to have some weaknesses for having used that abstraction, but if I didn't use Ruby I probably wouldn't ever get the code to compile anyway.
However, I can go ask some friends who know C or Rust or something similar to extend my Ruby code when it really needs that performance boost!
Maybe one day, I'll have to re-write my Ruby, but that's a problem for millionaire Jacob. He has more users and paying customers than his little Ruby app can handle.
Tailwind doesn't stop you from cracking out that hellish CSS abomination whenever you want! When my Tailwind implementation makes something difficult I'll hire a warlock to summon whatever void-being we need to fix my layout.
While we disagree, I'm glad we can have a discussion about it. Maybe you're right; if people find this article searching for more context around Tailwind, they will find a lot of opinions (and the strong stench that comes with a multitude of opinions).
However, for now, I think the enlightened 21st-century philosopher-king Jason Mraz penned it more directly than I can every hope to: "You do you and I'll do me."
I love tailwind. I love the absolute tiny css file that goes along with it (when purged). I love that my boss will not mess up the rest of the site by editing a css style for his pet project page. I love not having to invent names for css classes. I love extracting tailwind classes to re-usable components.
You have bigger problems than I can deal with here.
I suppose in some cases, tailwind would be an improvement if your boss can go in and edit your company's css file for a project page. But then we're not exactly talking about best practices, are we?
You can replace the word "boss" with "others".
Still doesn't change the problem.
It seems like the problem is one of scoping, and tooling though, now that you mention it.
First, it seems like you're editing a global .css file. Now, whether it's SCSS, CSS Modules w/ a bundler (Webpack? Rollup?) it's... rare these days for there to be one universal CSS file precisely because web development has gotten much more complex. The output might be a single CSS file - that's the point of a bundler after all - but the input shouldn't be.
One of the key things you can do with CSS (and it's even easier in SCSS) is to introduce scoping.
So, let's say that you have a pet page.
All you have to do is, in the root of that pet page (whether it's
or or whatever...) is add )You can then write styles that apply only to that pet page.
It's even easier in SCSS
This is the power of CSS Combinators, one of the things you lose with Tailwind.
Sorry, I guess I should have been clearer. I understand scoping, components and most modern css best practices. I used to do agonize over all that with sass/less/postcss - code splitting across files where it made sense, components, namespace scoping, BEM and other methodology experiments. All with some form of build using npm/gulp/grunt/bundlers/etc. Now we just tailwind and don't really need the other stuff. It works great for our team.
Oh boy did you get some reactions to the post.. I totally haven't read all the comments so I might just rephrase some other comments in my own words and maybe add my own two cents while I'm at it.
First of, don't use apply. Don't. I'd deny any pull request using
@apply
. Horrible feature. Yuck.From skimming through the comments I didn't see the point of standardization though. You can ignore all extra work of making sure all your devs in your team use the same kind of class-namings. To BEM or not to BEM, all these decisions go out the window, reducing extra time needed in planning that is better used to actually get to work.
The example you have in your section "It's hard to read":
How are they any different if you put the code into a component? All tailwind really helps me with is to not get fuzzy and build my own broken diy-css-framework over the time. It stops me from doing stupid things like getting into the habit of writing bootstrap-esque classes á la
.card .card-title .card-body
and so on. Instead of writing several classes myself now I write more components and think about making my project more modular, increasing reusability while maintaining a single source of truth. Now you might say "but I can have a source of truth too in my .css file". Sure. But why would I go through all the hassle and time to slowly write all the css classes myself that are literally right there from the get-go?Convenience and maybe a good portion of laziness? Yup, absolutely.
I'd probably just don't use it if there is some crazy specific task from a client where you can see right away that you're going to rewrite 90% of the tailwind config anyways. Overall it's just crazy fast to get websites done with tailwind while staying consistent in your markup, especially in prototyping stages.
So all that's left is probably to look at it by a case by case scenario and decide what tool to pick for the job. As always.
I agree. Not that I don't think you shouldn't bundle related CSS properties together into reusable classes, but that the whole point of Tailwind is to avoid that type of composition altogether. I may not agree with Tailwind's philosophy, but I don't mind pointing out as part of it's criticism when it's being philosophically inconsistant.
Weirdly, "making sure all devs use the same class namings" is not really a concern that I have. I mean sure, it's a good thing to aim for, but it's only really a "must have" if you're using an unscoped global .css file for styling. Most of the work I've done has been in Vue or React; which means I'm either using Vue's
<style lang="scss" scoped>
, CSS Modules: "import 'myComponentStyle.scss", or CSS-in-JS: "const myComponentCSS = css\
" (which probably won't show up right because of markdown not interpreting backticksI suppose if your team is operating on one big global .css file (instead of using CSS modules or CSS-in-JS) you have to make sure it is using the same naming conventions.
But for the most part, it's more important to me that class names are unique and descriptive of content rather than follow a certain format, so that they can be easily searched for in the source code of the finished HTML (for debugging) or understood by the rest of the developers on the team.
One of the patterns I'm seeing is that people who really seem to like Tailwind point out how much more useful it is than CSS, and don't seem to have a whole lot of experience or willingness to try CSS-in-JS or pre-processor (SCSS) solutions.
I have no problem with utility classes, used sparingly. Ideally I'd prefer SCSS mixins or resuable CSS-in-JS code compared to them, but what's wrong with that?
This is a compelling argument for a framework like Bootstrap, but not one like Tailwind.
One of the problems I have with tailwind is how many of it's classes - something like 99% -- though I haven't done the actual math, I'm pretty sure that's the right ballpark, give or take 1% -- are just one or two lines of CSS.
"p-8" is just "padding: 1.5rem;". "rounded-full" is just "border-radius: 9999px".
I did go through and identify about nine tailwind classes (out of how many hundreds?) that DO actually provide some convenience and am rewriting them in my own utility class library.
By all means, prototype away, but I wouldn't recommend it if you're dealing with end products meant to be delivered to the product owner.
I honestly don't use it as much as my text might suggest but I can see the appeal and tried to find some points to make you maybe see them from a different point of view :D
This caught my eye because I honestly never worked in a situation where I hand over code to another owner and I mostly work on internal products. The rare SaaS things I worked on were in good ol' SCSS though.
What would be interesting to see is the type of projects people work on using Tailwind. Is it a lot more agency-type of projects, internal sites (as in admin tools) or SaaS?
Bootstrap and Material Design are also both utter messes of applying way too many tags to way too many elements. I prefer to write my own cleaner more terse styles. Tailwind just is even worse but I haven't had to use it thankfully.
With this kind of overelaborate markup the stylesheet turns into a gawdawful warring mess of !important and even worse ng-deep messing up other devs pages especially because the backend devs that big companies tend to hire to do front end work seem to be incapable of using their own elements, creating simple reusable styles, or cloning well done markup from other pages and think that building a page is sort of like assembling tinkertoys without having to concern themselves at all with the messy art of design.
If you're non-stop appending classes to get what you want, then sure, it can be a bit messy. I've found Bootstrap + a small amount of custom css with @extend to be great. I started making sites like that in 2012 and haven't looked back. Rebranding is super easy just by changing some variables and fonts.
In my last project idiot devs were using Bootstrap and Material design tags for different purposes on every page. It would have been better for the project if someone that actually knew what they were doing had written simpler styles and templates for all the common elements and they were almost always overriding things with the stylesheet many times with inline styles for all the framework items they were misusing. Every single page had elements common to other pages that were laid out differently and badly.
I was the only one in the entire project that was writing comprehensive reusable styles and using for loops for repeated elements and I was making some headway in that the clients were liking my pages and not so much the dreck they were doing, but I got fed up about the massive unpaid overtime and took a different job. I still think bootstrap and Material design are barking up the wrong tree. They are too complex.
As an example I just started a project in VueJS 3. I needed controls so my first library that I tried had utterly beautiful looking controls but when I installed it the compiler warned me that it was making my bundles too big. And looking further it was a big camel designed to get its nose into your tent and then force you to pay $900 per developer to use a designer tool they wrote to handle the massive complexity of the whole thing.
I found a open source implementation of the multiselect I needed written in native Vue, with maybe 80 simply named css styles only 8k gzipped, easy to modify without a tool, which is the right way to build things.
Any framework can be abused or misused through laziness/ignorance. I think plain CSS is actually the most susceptible to abuse. Freehand tools are the most flexible but with no standard laid out, most people will just end up making a huge mess over time.
I understand the argument that Bootstrap is heavy but it's only JQuery that makes it heavy and BS5 will get rid of that. If a project doesn't need a component, just don't include it. Perhaps I have heart shapes glasses because I prefer a standardized look and feel over something unique but I'm going to keep reaching for standard libraries that let me get a front-end done in days instead of weeks.
I still think Bootstrap is a stunningly awful POS. I have been forced to use it on three projects now, loathe it. I can write my own stylesheets way better. There are a few good ideas in there, such as the font icons, but the whole idea of putting ten tags on every element and the idiotically meaningless names of the grid controls can just go somewhere the sun doesn't shine. It doesn't save you time, it makes things harder.
I create my own standardized look and feel.
All of the projects where I loathed Bootstrap were using modern frameworks. It has nothing to do with jQuery, it has to do with the terrible metaphors Bootstrap uses.
Strong words. You aren't forced to use 10 classes everywhere. You could come up with one class which extends those 10 classes and then use one repeatable class, same as any compiled CSS. I think of BS and all the other frameworks as just time-saving utility and for me it's always done a good job of that. I don't honestly know how it could possibly make things harder unless your always overriding it, which is a miss-use.
I wasn't the one overriding it. But the stylesheet was a mess of overrides nevertheless. I've never seen anyone compile the Bootstrap classes into one class, they were using them everywhere with multiple classes on every object.
The problem is that it becomes very difficult to see where some unwanted style attribute comes from. I also don't even want to understand how the grid classes work, because the names don't make any sense whatsoever.
What I really can't stand is how large companies hire back end developers that think that using a CSS library like this is a substitute for actually writing a well conceived ui. They pile on the various containers and objects and get something hugely inconsistent with layout anywhere else. I have written very large applications, and I didn't need a third party library to do it. I have in the past copied just the bootstrap style icons into a project but not used anything else from it. It's a style of markup I strongly disagree with.
I've been writing CSS since 2000. I love the way tailwind works. It's especially nice for modern website development. An agency owner I collaborate with just mentioned that he appreciates it because it unifies the frontend style of a website while allowing junior developers very strong documentation on the style guidelines.
Everyone out there reading this that loves TailwindCSS checkout TailwindUI! I've been using the newly released React Components on my Gatsby websites and it's awesome. Super seamless, super optimized, and it's very fast to build out components.
I actually start using Tailwind from TailwindUI with React, that's where I got the bad developer experience.
It is ok to use tailwind UI as a whole component. but if I want to make changes to it, I have to read through hundreds of lines of html with really long classNames. the problem of tailwind is that it enable ppl not to think about components, which makes readability really bad.
I'm going to have to disagree. Unless you are trying to use it without purchasing them.
The site has HTML showcasing the components on the frontend if you aren't logged in. If you purchase TailwindUI there are React versions of the components.
*Example:
*
export default function Example() {
return (
<div>
<label htmlFor="email" className="block text-sm font-medium leading-6 text-gray-900">
Email
</label>
<div className="mt-2">
<input
type="email"
name="email"
id="email"
className="block w-full rounded-md border-0 py-1.5 text-gray-900 shadow-sm ring-1 ring-inset ring-gray-300 placeholder:text-gray-400 focus:ring-2 focus:ring-inset focus:ring-indigo-600 sm:text-sm sm:leading-6"
placeholder="you@example.com"
/>
</div>
</div>
)
}
I am talking about the full version of tailwind ui. take the pricing section for example, the
three tiers
component has poor readability. i cannot tell by a first glance the structure of the component. What I am trying to say is tailwind enable developers to write code like this. When I work in a team, it happens. The example is functional and performant, but it is not readable. If we are using styled component, for example, it will force the developer to carefully decide the components in that pages first, then we will see things like<Title/>
<PriceCard/>
<CardWrapper/>
<CardTitle/>
<PurchaseBtn/>
, which will show the structure clearely.Lets wrap this discussion I am not sorry to this guy cause everything has its pros and cons but this guy could not provide rational argument in most cases.
Why do we use framework because it eases our lives we could have just used Vanilla Javascript.
Tailwind should be compared with Bulma Bootstrap and not with saas which i believe is a mess too and not a css framework and some like it. While Tailwind has some cons it is definitely solving problems for many and many are buying premium version I even dont own one.
The way he bashed Tailwind we can also bash React Vue Angular and everything that exists.
But if someone is using it let them use it rather than spreading negative judgements.
This post was like begging people to not use Tailwind with mostly irrational arguments and most people who agreed I believe never made a full project with tailwind I understand they have their own preference .
In return this post just gained negative publicity which at times is good for a brand.
Bottomline nor people who need to use Tailwind are not gonna stop and neither the guy will provide an alternative solution.
But if you ever bash a technology mention a few good sides and atleast have minimum respect to people using it.
I am not replying anyone to this comment and I have deleted all my comments previously. Remember onething dont always see the world through your eyes a product might seem bad to you but its provides solution to others and people are making money. Everyone stay fine stay safe tc.
Immense thank you, @brianboyko !
So glad articles like these start to be written, providing simple and precise explanation of what is wrong with Tailwind.
My personal a-ha moment came after inheriting a project with it. It was supposed to be a no-brainer, after all you don't have to learn someone else's home-made CSS framework with Tailwind (they say)!
Yeah,
lg:pl-12 lg:pr-6 -mt-1 lg:mt-0
, give me home-made CSS frameworks any time instead of this mess.@brianboyko thank you so much for writing this article -- especially the part where you talk about why you wrote it. Additionally, while most folks won't read through all the comments, it shows an incredible level of dedication when an author takes time to read (not skim) comments and provide thoughtful responses.
Apologies in advance for this very cynical and bleak perspective....
While most of your article focused on technical reasons why Tailwind would not be a wise choice for most projects, I thought it might be helpful to at least call out why Tailwind is so popular in the first case: a lot of developers don't really know CSS, and they don't really care. Tailwind promises to make CSS more accessible for those developers. Unfortunately, I think a lot of your points above (which resonate with me, someone who knows CSS) just don't make sense to developers that have no strong desire to become proficient with CSS.
Why would these folks care that
@apply
isn't in the CSS standard? They're told to use it by the Tailwind documentation and that's really all that matters.You make a great point about not being able to use combinators, but (really) who among these developers were ever going to use combinators anyway?
Let's be honest: Tailwind is for developers that don't know and don't care to know CSS. Tailwind is for developers that want to pretend they use CSS.
This is very similar to the extreme dependency on a grid system for layout when CSS Grid exists, is infinitely more powerful, and can be picked up in a weekend of study. Call it laziness, willful ignorance, or mediocrity, but Tailwind is popular and will probably remain so as long as developers don't want to do the work of learning CSS.
Great take Mark. Had a good chuckle!
Your perspective is neither cynical or bleak, but it is incredibly condescending and presumptuous, even more so than @brianboyko 's very condescending and presumptuous piece, so props on upping the bar! 🎊
I do know CSS and I also absolutely hate reading it. The reason I love Tailwind is that everyone writes CSS differently and with Tailwind you can’t do that. No more reading through an inscrutable CSS file, flipping back and forth from the HTML to figure out what the hell it’s actually doing. People don’t like Tailwind because they’re ignorant of CSS, they like it because in many cases it’s a better experience for both writing and reading it.
You're getting a lot of pushback here but I completely agree with you. It's pretty baffling to me how popular it is, but I LIKE CSS so maybe that's the difference.
Not trying to throw shade but many of the people I see favoring Tailwind admit that they're bad at CSS or actively hate it.
At this point I know CSS very well so it seems like much more work to fiddle with abstracted utility classes and learn the "Tailwind way" of doing something, rather than the CSS way...which I know isn't going anywhere and has standards.
Oh, and there's a lot to hate about CSS.
The standard names can indeed be confusing. Dealing with priority -- i.e., what styles overwrite other styles -- can be problematic as well. In the original spec, there was no support for variables, which made it impossible to reuse code from class to class, and even today there isn't support for functions.
And yet, we continue to use it -- and our dependency on it grows, because while nobody likes the CSS standard, nobody can agree on anything that can replace it. The best we have are tools that transpile to CSS.
This is why I really do think that something like native support for SCSS files should be a priority of whatever muckety mucks are in charge of WebKit. But then again... I don't see that happening anytime soon when the existing solutions are good enough.
Having read the article, I disagree with some of the statements and find others to be factually inaccurate.
Things I disagree with are mostly summed up in this part: "If you choose Tailwind for a mission critical application, you will end up making your job harder, your application more brittle, and your team, in the long-term, will suffer."
I have not (anecdotally) found this to be the case. I maintain many applications that use vanilla CSS, many that use styled components + react, a few that use SCSS, and many that use Tailwind. I have not found apps that use Tailwind to be more brittle or cause me or anyone else in my teams to suffer. I do not see any evidence to support this statement.
This that are factually inaccurate:
I say if you don't like it, don't use it. If you like it, use it. Not everyone loves React, some Vue. Some vanillaJS. I use to use my own rolled up CSS. Then bootstrap with my own stuff. Then later I used Foundation and my own CSS. Personally, I like Tailwinds.
Use what works for you and your team today and hopefully later in the future.
And btw, I was one of those early 90s guys that started developing when Netscape 2.0 was so AMAZING (it was) and later used tables (HATED IT), so most of the stuff today is GOLD!
As personal developers, you should work with the tech stack that you like. As professional developers, we rarely get that option until we're at the level where we're making architecture decisions for the team.
What I'm saying is: Even if you personally like Tailwind, you need to know how your decisions will affect the product and your team.
The point of these criticisms of Tailwind (and other similar criticisms of other tech (Why Does PHP Suck is always a fun read), is that when we criticise these technologies harshly, we are explaining not why we don't like it but why team leaders and architects shouldn't choose this tech for their stack.
For example, I don't like Java, but I can't make a compelling case to never use Java in enterprise applications. I really like Deno, but I can't make a compelling case to move our Node-based production over to the new platform. It's not about preference, it's about profession.
Or more bluntly:
As a professional developer, when we switched all of our new projects to Tailwind, everything got easier and more efficient for us. We don’t have time or resources to implement some ridiculously verbose CSS methodology like BEM. You’re effectively just saying “you shouldn’t use this because I say so” and frankly you sound like a clown to me.
I was about to write a piece like this (and I might do it anyways!). But I totally agree on the "does not solve problems it claims to" part. They claim to solve the naming problem, only to delegate it to single file components… where style is scoped so you don't need naming anyways.
And I would be super concerned about maintaining it. Built of speed no doubt. But I moved away from bootstrap utility classes when I had to change some margins—but not all. Now why was this one
m-4
? Should I change it tom-3
?One of the biggest benefits of using tailwind is constraining styling to a set of pre-defined utility classes to follow a design system, and (almost) automatically have a consistent UI in terms of colors, spacing, etc.
Not a single word about that in the blog post...
The author sounds like they’ve never had to work with a set of design standards and just use Bootstrap or some other gross and inflexible framework for everything. That’s cool if you want to make an incredibly boring looking site. I’ve done the “override styles in Bootstrap to make it less ugly” dance before, and it sucks compared to using Tailwind or any other utility-first framework.
This is amazing for big/enterprise applications
Also did you give this post a read?
😎 never used tailwind because like every other flash in the pan including my own flash in the pan inventions, I always go back to Sass or Sass like things, because that's what I saw first. It's like the baby duck 🦆 sees it's mom 🦃, you only get one first impression and that's the one that sticks.
I've been coding HTML since the mid-90s. If I felt that way about everything I'd still be using
<table>
tags."but you should, youl like it" to which I say, I like ducks
While I agree with the overall sentiment; I’d like to add that tailwind is not as popular as it is without a good reason.
I’ve used it myself before and I found that (at least when starting with a project), it makes it very easy to get something looking very modern and clean. I think the thing that makes people like it over eg inline styles is that yes, it’s “inline styles with extra steps”, but it’s also inline styles with prettier defaults.
It can very quickly get you satisfying results.
What about if you're using Tailwind with some framework like React when you're building components and use Tailwind in those components? I mean, instead of replacing 123 occurrences 'blue-color' you just replace it in one place, in the button component.
After all, is Tailwind just a replacer for simplifying CSS?
I'm not defending Tailwind. I know what it is, but I've never use it. Thank you for your article (like you see from other comments [still valuable] it's controversial) but while I was reading I wondered if all disadvantages described in the article are in context of web development without frameworks like react? Because Tailwind with React could be just a replacer for more difficult CSS?
How far down do you go with turning things into components though?
For example, imagine creating a very simple alert modal component. This contains a message, and a button. Now, I've done this exact thing, and the button is just an HTML
<button>
. I could embed a button component into it instead to mitigate the problems of Tailwind, but that seems like it's going too far in the direction of breaking things into the smallest possible parts. There's a point at which something becomes too small to separate out into it's own component/class/modules/etc. There's a balance between making the code readable and logical, and also ensuring that it's comprehensible by the human who is managing it.Should the modal text be its own component too, as it contains styles very specific to a modal. It needs to be re-used across all of the other modals (prompts, confirmations, password queries, etc), and we want to avoid the need to be making multiple find/replace changes that Tailwind might force us to make otherwise.
Tailwind would allow us to do this in a more sensible manner, but it's not generally how TW projects appear to be done the majority of the time (going from the numerous articles and code examples in Git repos), and it's something that was already very much possible in vanilla CSS, let alone the many pre and post-processors for CSS that have existed and been in use for many, many years successfully.
That is a good point, and in theory, that could work. I don't think that when the rubber hits the road, though, it will.
A really well organized React/Vue project will probably be like that. You have a roughly 1-to-1 ratio of "components" to "css classes". You style only in "dumb components" (i.e., stateless, takes only props), and if it's not "one className entry per component", it's at least really close.
It eliminates many of the problems I've pointed out about code-reuse, and having to change class names in multiple places.
But it doesn't eliminate the problems with debugging. If you try to inspect an element in the browser - that is, after it's no longer a component, and now lives as part of the DOM, you can't really identify what the component is by class anymore. It makes it harder to identify the root cause of the bug, which increases the Mean Time To Repair.
It also doesn't eliminate the problems with having to learn new Tailwind syntax, with prioritization (if you were to give an element "h-12 h-8", or "h-8 h-12" which height would apply first... and how would you know unless you looked at Tailwind's sourcecode to see what got defined last?)
And it certainly doesn't account for the scenario when the React or Vue app you're working with doesn't have a very "atomic/molecular/organism" structure at all - but is a mishmash of big components, small components, components that depend on Vuex, components that have props reassigned to internal state which on-change run a callback prop... (Ugh!)
What I do think might be useful is using something like the Twind library to rapidly prototype what you want your final CSS to look like, but then taking the CSS outputted by Twind, copying it from the browser inspection, and plopping it right back in to something more long-term like emotion/css.
I respect people who use it, but I think it is completely unnecessary and adds complexity on top of standard CSS without any convenience. You put a million inline-like classes on an element, then you either slam it into a component or try to move it to some SASS file. When in a SASS file, you then @apply not-so-configurable classes without any access to mixins, variables (both CSS or SCSS) etc. It makes no sense to me.
I agree it's not readable at all. Styles and HTML are not separated anymore it's sad.
And a question is to answer, which order for theses classes ? Not all developpers will order it in the same way...
The people I know using tailwing are generally bad in CSS or too lazy to write it.
Have a look to RSCSS -> class names will have a real utility again and HTML is READABLE !
I'm not very adept with CSS yet I still agree with a lot of what's being said there, mainly how unmaintainable (and unreadable and just plain ugly) it makes your HTML if you use it how much of their docs suggest.
The parts I like about it is that is pre-defines sizes for a bunch of things in
rem
(m-x
etc), that's it's easy to make something responsive or darkmode or whatever modifier by just adding a prefix and the typography add-on (makes it incredibly easy to style generated HTML so it looks nice).So I just use those parts to make my own classes with a mix of
@apply
and regular css becuase it's no problem to mix that.You might actually be a good candidate for Tailwind, but not to use as intended.
I make an argument that "if you use it this way" is not "if you use it as intended". What I'd suggest in your case is using it as "training wheels" to CSS. If there's something you can't figure out how to do in CSS, but you know how to do it in Tailwind, try using tailwind in your first draft to apply the styles you want, then go into your Chrome/Firefox element inspector to see how Tailwind's styles got translated to CSS, and replace the CSS. This actually seems like a really solid way to start getting better at CSS.
Again, though, it's not used as intended.
I fully agree. It makes, code ugly and I cannot imagine a case where this makes me faster. I have a few utility classes and a nice grid I made so I can change collums, padding and positioning while writing HTML und the real look is made in CSS. But yeah, people are using what they want. Not all are thinking that code should be minimal and nice.
you've just chosen your hill to die on
Thanks for writing this article. I felt that I was the odd one out who doesn't feel productive while using Tailwind. Glad to know that there are many. I prefer writing my own sass
Oh no. You're not the only one.
Wow, I was wondering if I should hop on the TailwindCSS bandwagon and came across this post at the right time . More than the article itself, enjoyed reading the back and forth between the developers in the comments section. This is such a healthy discussion I have seen in my career !
Tailwind CSS is only a tool which can be used anyway the wielder pleases. If you decide to write all the utility classes inline, so that you'd have to edit them one by one when there's a change, good luck.
But as you noted, you can simply create a class and apply the various styles you need on that class using
@apply
. With this, you can combine selectors pretty much like plain CSS.It saves you from writing long CSS styles, pseudo classes, and media queries. Your HTML documents will look the same, and your CSS documents would be shorter.
On top of that, adding dark mode support to your entire application is a breeze with Tailwind CSS.
So I say the advantages of Tailwind CSS over Plain CSS would be:
That does not sound like using a revolver in place of a nail gun
I agree with pretty much everything in this article yet I also find myself really liking the the naming conventions tailwind has used. For example, I find the media query prefixes to be very intuitive.
I think the middle ground here is to use
@apply
all over the place despite tailwind's documentation recommending against it.All of those classes really make no sense.
I haven't used. But I do believe solutionism is a problem in the dev community. Either making solutions to problems that don't exist OR brining a tank to a knife fight
I think it's pretty clear it provided a good solution to a problem, otherwise the company formed on the back of it wouldn't be multi-millions in profit, and it wouldn't have rocketed in popularity past Bootstrap.
Some of the arguments in the article are valid, some are the typical ones we often see from people who've not taken the time to use it (throwing up a 1 page app isnt even close enough to fully appreciate what it can do).
The common arguments such as bloated html and duplication of code often just highlight how much people totally misunderstand Tailwind.
The #1 seller of hamburgers in the United States has been, for years, McDonalds. Does that mean a Big Mac is the epitome of high cuisine? Does it even mean it's healthy?
Millions of people use PHP, too. That doesn't make it a good programming language, and it doesn't make it a good idea to start a new team project in PHP.
I think you're falling into a rhetorical trap here: a bandwagon argument. A viewpoint can be in the overwhelming vast majority and still be wrong. The popularity of a position doesn't have impact the objective truth of it.
Hey, let's not be putting PHP in the same bucket as Tailwind! :P
But absolutely agree, popularity doesn't equate to worth of a project/language/etc. Just look at some of the projects on npm like
is-odd
(and its counterpartis-even
which relies on the former). Thousands of downloads per week to avoid modulus math in our code and make things look "nicer" and more "functional".Tailwind might have solved a problem, and that's logical to assume so (I've not seen what that problem is, but that doesn't mean it didn't exist), but it also creates its own problems, as you've pointed out. What we need to be doing is more of this, more questioning on our tools, and looking at alternatives that solve the problems in better ways without creating more issues.
I may be prejudiced on my view of PHP, mostly because I once took a job... an overseas job, too... where the job listing was for a JS engineer, the job interview talked about JS experience, the take-home test was to write a JS front-end (React), the technical interview was conducted in Javascript, and the job title was for "Front-End Engineer"... and then I open up the codebase, and it's 95% PHP.
I explored all possible avenues -- transferring to a different department -- putting transition to Node on the roadmap for the next quarter -- everything. No, apparently I was now the PHP guy on the team.
I lasted two and a half days, and started packing my bags, getting ready to move once again.
Interesting article, a different view about the css "star" of this moment.
However, let me do briefly the devil's advocate.
For example, to avoid classes pollution and the "style inline" effect you can use the @apply directive.
tailwindcss.com/docs/functions-and...
So you can leverage the simplicity of tailwind without polluting your code.
I briefly touch on the @apply directive in the article.
The thing about @apply is that you have this utility-class library that doesn't use semantic classes. @apply is then created to convert your utility-classes into something you can use in your semantic class.
Why not just write the semantic class in normal CSS and cut out the middleman. It's easier to read, more expressive, more powerful, and you don't have to learn a whole new syntax.
There is one particular case where @apply might be of use - and that's if a programmer knows Tailwind but doesn't know basic CSS... in which case I would not consider that programmer qualified to professionally write front-ends.
Because you can use variants defined in your Tailwind config and change them all just by changing the config. Duh. Your condescension is unearned when you couldn’t even figure that out.
UPDATE: I ONLY use tailwind classes. I have zero @apply's in my code and I do not have any SASS/SCSS. I wrap most of my styles up in components.
You're completely missing the point of Tailwind. @apply is the powerful paradigm shift NOT utilities. Sure, It's utility-first...NOT utiltiy only(that would suck) as in quickly prototype and then apply custom classes. Get instant media-queries and even dark modes. We built a completely custom design system for a large company completely powered by tailwind. so you just add the "button" class, get the designed button, but you can add utilities IF you're trying to see how a modified or alternate or one-off theme could look like. Then, after all is said and done, whatever classes you aren't using, get taken out of the file so that you don't have extra bloat.
These concerns are addressed by them
tailwindcss.com/docs/utility-first
Actually the first example on the page shows EXACTLY why I don't like Tailwind.
Take a look at the first example of the code. I don't know if you can use markdown in the comments. It looks like a huge amount of code, compared with the Tailwind example below it. But think about it. Is it really less code?
The second example - the tailwind example, is pretty much the same length as the HTML in the original example. All that CSS code is still there, it's just moved to a place where you can't readily see it, examine it, look for bugs in it, etc. You could get the same effect just by putting the CSS in a seperate file...
Additionally, the CSS they use to demonstrate the "complexity" of CSS is... needlessly complex. I'm not saying it's not passible - it'd pass code review if it was in my wheelhouse - but there are better ways to structure it.
First, I'd use CSS variables, I'd use SCSS if possible, and I'd use properties to make organizing it a lot more paletable.
So, my solution would be:
Doesn't
<div class="chat-notification with-box-shadow">
look a lot better and easier to read (not to mention tells you WAY more about what the component actually is) than<div class="p-6 max-w-sm mx-auto bg-white rounded-xl shadow-md flex items-center space-x-4">
?In fact, how is a programmer who has to work with the HTML supposed to know that
<div class="p-6 max-w-sm mx-auto bg-white rounded-xl shadow-md flex items-center space-x-4">
is your chat notification? If you've got a bug in your chat notification, it would be awfully useful if programmers could find it to know where to start looking!A few months in you need to add another component. Designers says it should look completely like your chat-notification. What do you do? Duplicate the styles, or rename your "semantic" class to something more generic. (By the way, class names is not and can not be semantic .chat-notification is not more semantic than .with-box-shadow).
And where is the seperation of concerns / html is for content arguments when doing ".with-box-shadow" classes?
Naturally I choose neither.
First, let's look at plain CSS, no preprocessors, no CSS-in-JS, just the tools we've had since the beginning of the century.
This is actually a very good use case for writing a utility class like "with-box-shadow" -- when you have reusable code. It doesn't remove the need for semantic classes to tell you what something is and keep one component separate from another.
I'll admit that having 'with-box-shadow' does violate separation of concerns, and if I really want to be a semantic stickler, using just standard CSS and HTML, I'd have to rewrite the same code in multiple places, duplicating, as you said, the code from one semantic class to the other.
I'm not a semantic stickler, and in this case, wrote a utility-class because it A) made sense, B) was limited, C) there were no better options. As I said, I'm not opposed to utility-classes. I'm opposed to a philosophy that all classes should be utility classes.
But thank goodness that in the real world, there are better options - preprocessors and CSS-in-JS! Either allows you to reuse bits of code more idiomatically. (and use functions, too, making it even more powerful.)
If I'm using emotion/css or another CSS-in-JS solution, for example, I wouldn't have a with-box-shadow class. Instead, I could extract the code to a variable: 'boxShadowCSS' or '@mixin hasBoxShadow' That new variable could then be interpolated by both .chat-notification and .new-component's own definitions, like so.
Tailwind wouldn't actually solve the problem, the code would just end up looking like this:
To which I have to ask - if the designer says that they no longer want it to be exactly alike, that they want the new component to not have a drop-shadow, which one of those "shadow-md"s are you going to delete?
So you did actually duplicate the code into .chat-notification and .new-component.
I think a lot of the knee jerk reactions regarding seperation of concerns comes from something we all learned was the right way, but never really adhered to anyway.
As you see yourself, .with-box-shadow is not a good way to seperate concerns, neither is .col-sm-4, .card, and other often found classnames.
Tailwind to me is about accepting the fact, that completely seperating concerns between html and css, is at best an academic approach, and in most cases completely unnecessary for most projects. Often adhering to this is creating a much larger burden on the developer for little to no gain.
The author of Tailwind, Adam Wathan wrote this article about utility css and seperation of concerns. , that I really think you should read.
I'm not trying to concince you into using tailwind (or other utility first methodologies for that sake), but at least acknowledge that this methodology works wonders for a lot of people. At least you could append "for me" to your title.
To me, Tailwind removes complexity and adds function. My team now has a well documented vocabulary for building nearly anthing. Before that we had CSS scattered all around (thats not CSS' fault, though 😉), and different naming strategies across different projects. A .card could be named .article, or .box (or something semantic) depending on the project, and the mindset of the developer implementing it first. In tailwind it's just utilities, and I can onboard a new developer to an existing project in no time, and never fear that a change in one place, breaks something completely different in another place.
If, by "duplicate", you mean, I created a const variable with the data, and then referenced that variable in two places... then yes, I guess I did.
But isn't that the whole point of variables? Especially const variables? To make it so you don't have to type out the same thing multiple times?
It's not an academic approach, it's a "best practice". As in - used in practice, not in theory. It's not academic at all. Using semantic-only class names is the best practice. A close second - a "second-best practice" if you will, is using utility classes sparingly. Using nothing but utility classes is a "worst practice."
I think that the methodology might work for some people, but not for people developing professional quality software in a professional environment, for the reasons I've stated. If you want to use this in your solo side-project or hackathon app, go right ahead.
Regarding Adam Wathan's article...
I don't know what to tell you. The point he starts with "dealing with similar components" as a dilemma -- I get it. There is no way to do that without duplicating code in regular CSS.
It's the limitation of the scripting language. It's like trying to write a function in HTML, you just can't, it's not built for it. CSS isn't built well for code reuse. I wish it was. So in order to solve these problems CSS preprocessors like SASS/SCSS were developed, as well as the myriad of CSS-in-JS solutions. It solves the problem of "not being able to reuse code" directly - by allowing you to set variables and functions so that you indeed can reuse code.
I often feel like the goalposts keep shifting here. To clarify: Yes, I would rather take the problems with duplicated code in plain-CSS and keep semantic classes, than the myriad problems with Tailwind. However, all of the problems that Tailwind claims to solve already have been solved by other tools and they don't introduce the problems that Tailwind introduces.
A metaphor: say that in the 1990s, the only way to build a house was to bang nails in with a flat rock (CSS). And then, around the mid 2000s, a really smart guy invented "the hammer." (Sass) It took adjusting, and you have to learn a new tool, but it did the job much better.
Around the early to mid 2010s, another guy invented the nail gun (CSS-in-JS/Aphrodite/StyledComponents/Emotion, etc.). It worked even better... but it required power and a steady hand, and you had to be careful with it. It was (computationally) expensive too, so a lot of people stuck with the hammer because it was working fine for them. Which was okay. People would often use a manual hammer when the manual hammer seemed appropriate, and the nail gun when they seemed to need it. And all was good in the world of carpentry.
Then in 2017, someone came up to the carpenters and said: "Hey, see what happens when I do this!" and starts hammering in nails with the butt end of a loaded revolver (Tailwind). Look at how much better this works at hammering in nails than banging them with a rock! It's like a miracle!
You do like your strawmen don't you?
Imagine for a second that React could use components, I know it's not possible, but just imagine, and your strawman code would become like this:
If only React or any other js framework would have the concept of components. How beautifull the world would become, right? Maybe one day we'll be able to write code like this, but most likely not for years to come!
And
CSS isn't built well for code reuse.
is also wrong.All the utility classes are there in the css file, once. And are being re-used by all these different components. Which makes the final css tiny, and those CSS classes, wait for it... re-usable. OMG, WOW, SUCH IMPOSIBILITY.
Imagine, just for a second that you put that code in to, wait a minute.... a component named ChatNotification? Wow all of the strawman arguments burn away!
Suddenly you don't need to parse all that CSS it's right there visible in the template. Sudenly you have context of what is what.
Few cents:
In other words you wrote a sketchy review about based on shallow experience.
P.S. css in js is inferior
All this fuss about Tailwind is probably in anticipation of React/NextJS moving towards server-side components, which don't support CSS-in-JS which needs to manage a stylesheet on the client. So a library of classNames works around that.
Try SCSS Modules. Works in NextJS 13 server-side components! Tiny bundle size.
Most frameworks support at least the basic CSS Modules. Standard. Composable. Modular. Time-tested. Easy to work with. Efficient, small bundle!
Love the image "This is just inline styles with extra steps". Perfect! Haha!
Remember CoffeeScript? Yea. When everybody has to refactor their website/app originally built with Tailwind, they'll realize.
IMO inline styles are better for modern web dev. if you want to keep it dry you should do so by reusing components instead of some other CSS shenanigans, as reusing components is a lot easier to think about and generally ends up being cleaner. If you're reusing styles separately components your codebase is becoming much more complex for no good reason.
Anything that's not inline is necessarily a lot more effort to create something that's harder to understand fundamentally
To me, this article is just another one of those opinions. Tailwind is not the ideal solution for everyone. If you're looking to rapidly prototype a website and produce results quickly, Tailwind is an excellent choice.
But if you're looking to maintain a monolithic codebase with well defined layouts and schemes that may need small individual tweaks and updates that occur globally, then yes, Tailwind doesn't really help the solution.
If you don't really know what your codebase is going to look like, you're still playing around with your layouts, and you're making tons of little tweaks on micro scale, Tailwind can make these changes super fast. Not everything deserves to be a full fledged CSS class, you know.
But yes, when you have your codebase figured out and things aren't changing all over the place, you can begin to translate Tailwind into a more structured and elegant CSS-first solution (or better yet, SCSS). Plus, you get all the time in the world to waste naming classes once you're not in a rush developing truly useful code.
I know most front-end developers disagree with me :).
I think Tailwind CSS is the best way to build web apps quickly for backend and full-stack developers. Because I am one of them. When I started building web apps there was only bootstrap. Yes, bootstrap solves many problems but still, I couldn't warm up to CSS. Because CSS is too primitive (yes I know the CSS is an engineering product) I couldn't use it. Then I loved CSS when I use SASS but still, again there are missing some things. I need more speed and simplicity. Finally, Tailwind solved all problems for me.
These days we are not developing simple websites. If we choose the long way we can lose a lot of time. If you can use the right tools you can save time. And you can move next step.
This article has some right arguments and I think some titles are outdated now (2022).
"and starts hammering in nails with the butt end of a loaded revolver (Tailwind)."
well said! thats how I experience it too. I tried to use tailwind in few projects, but as the project got more complex, re/styling it was a huge pain in the ass..
It might be good for smaller projects and when you simply start and need to design components quickly, but even then, you need to learn the new syntax, I could almost do the same crap in style="..."
This article is just full of ignorance. If you would learn to actually use the system, ie... take a deep dive and truly learn it, you would find that many of the things you point out are absolute rubbish. For instance look-up the @apply directive. @apply lets you apply all the classes to one class. That's just one example. I could point out so many other things in your article that are so wrong.
I would say that CSS-in-JS is a screw/screwdriver, and Tailwind and cousins are the nail guns.
The screw requires a screwdriver to use, which is a rather different tool to a hammer, but it achieves a very similar outcome.
If you use it correctly, the nail gun allows you to quickly and neatly shoot in some nails, but it isn't always flexible enough for what you need to do. In that case, don't discard it: use the nail gun to quickly do all the main stuff, and use the hammer when you need to.
If you don't use a nail gun correctly, you can hurt people. But you can also hurt people with a hammer or screw driver. And nail gun wounds are usually clean. Hammer wounds are not.
P.S. Check out WindiCSS.
As a senior dev you know that there is no best tool. All points you mentioned are valid, by they depend on the context.
With custom CSS you often find yourself doing exactly what tailwind is doing. Then you struggle with naming things and end up with lots of unused CSS that you know there is in your CSS but you just do not dare to remove it.
Right at the start you know bow complex your designs are and you can quickly asses the overhead you may have with not being able to use the cascading nature of CSS.
There are tons of use-cases where Tailwind will save you a lot of time and money not to mention a built in support of themes and even dark/light modes.
There are ways to mitigate some of the disadvantages of Tailwind and despite it somewhat defeating the purpose of utility-first approach, it does not mean that Tailwind is a bad choice.
I use it where the benefits outweigh the disadvantages. And I do it because I know how unmaintainable custom CSS can become especially when many people work on.
it's your opinion and I agree with many points. But I strongly disagree that TailwindCSS does nothing. It's a trade off...
Personally, I thought the same thing when I saw Bootstrap add utility classes, and everyone and their mother suddenly using them. "Hey, look at this! I can do
This is a test! and I don't have to touch any CSS!" Isn't that just inline styles with extra steps? But at least Bootstrap still gives you components and you don't HAVE to use those utility classes. Tailwind is much, much worse; from what I can see, it's almost entirely classes like this, and it seems like a major step back for CSS design. If you're going to litter your class attribute with a million and a half styling classes, why not just cut out the middleman and use style="" directly?First, you can define primary color in tailwind config so all you have to do is change it to red in this case.
Second, Tailwind is meant to be used with a component oriented system like React or Vue. You don't have to manually edit 1000 places for a button, instead you just need edit one button component.
I've got to admit, everytime I look into Tailwind, I find myself asking what is the point of it. I don't see what benefits it has over just writing CSS. Personally, I think it's easier and quicker to just write CSS.
So many fallacies here - Just another case of a developer who has only half-assed the adoption process and doesn't understand design decisions that have been made.
I partially agree with you...
but have a look at this...
No, Utility Classes Aren't the Same As Inline Styles | frontstuff
frontstuff.io/no-utility-classes-a...
It seems like you’re going at great lengths to say that you don’t like New Orleans Jazz, which is to say that you don’t like Jazz at all. I’m guessing you’re not into Free Jazz either. However, Jazz is pretty much everywhere in New Orleans especially on festive days like Mardi Gras.
Also, Jazz is not really made to sell albums, that’s not its purpose, so I would refrain to suggest that. Jazz was initiated as a form of protest music, as an act of liberation, so learning to appreciate it wouldn’t be so bad I would imagine.
TailwindCSS, Much like any BEM structures on HTML, much like ANY CSS library depends on utility classes, is ABSOLUTELY ANTI-PATTERN and nothing good comes out of it in the long run.
I totally agree.
Wrote about it here eavichay.svbtle.com/never-bem-again
A good rule of thumb is that if people do something you think makes no sense. They probably know something you don't.
In this case i think it might be several things.
My feeling is that the author of this article is more at home in the theoretical than in the practical world, otherwise you would never come up with such a post.
There are many ways to reach the goal, and fortunately many good tools for daily programming and earning the daily bread.
I find this criticism disrespectful only because it does not meet the personal taste of the author. Readability and design of code are as individual as daily life. So, each as he likes!
You really don't understand about Tailwind. Please know more about Tailwind and rewrite the article. About @apply keyword, customize theme. You are having a superficial view...
It's actually impressive how you can be so consistently wrong.
Gosh... This conversation happened literally more than 10 years ago...
Plus this article very conveniently ignores a lot of the features of tailwind.
Also... Mission critical systems. I almost laughed. Have you seen a project with 10+ frontend developers each writing their own CSS in their own ways? How much complexity does that add? :D
A CSS framework at least gives you 90% percent of the practices.
But I agree with one thing. I also hate New Orleans Jazz....
He only knows how to use Bootstrap is my guess.
Here hope this "helps"
dev.to/neophen/tailwind-is-bad-bec...
Thanks for explaining me why I don't need it. How I understood: with CSS you write 10 statements to style some component; with Tailwind you write approximately the same number of Tailwind classes. So I don't see a reason I should even bother trying 😉
Hey, I fixed this article: dev.to/benface/tailwind-css-might-...
I tried Tailwind a few months ago and enjoyed how fast it was to prototype something at first. Once I started really getting into the project I found myself frustrated at a lot of the behavior you mention above. While I'm not exactly a CSS master I find it much, much easier to embrace the cascade and work with the strengths of CSS.
Check out the C.U.B.E. methodology if you get a chance (it's not a framework!): cube.fyi/
I'm feeling very represented by this article. I tried giving Tailwind a spin, create a simple website just for a practice. Few days in and I felt this is not for me. I get why people like it, but the fact that I have to constantly refer to the docs to remember the class name, felt counter productive, since I know the exact CSS property to do so. After completing it, I realize I have to fix several issues here and there, and guess what, the exact class name outlined in docs doesn't get recognized. I'm not sure what the problem is, but re-building Tailwind fixes the problem.
But I get why people like it, writing a more concise inline CSS might suit some people. And I agree with the author. Not liking this tool doesn't mean that everyone should hate it. More choice, more power to the people :)
This is a good explanation. There is a principle called "separation of concerns" that applies here.
My only complaint is that you should never name a class the same as a key word.
wrong:
.flex{
display:flex;
}
Is really bad form. You should do something like
right:
.flx{
display:flex;
}
The problem with development in general these days is people like taking shortcuts. The mantra of "deliver fast" has clouded the (at least) equally important principle of "deliver quality". Tailwind and similar stuff are great for fast prototyping, but then again these prototypes tend to become "Minimum Viable Product" and therefore slips into production. And the nasty prototype code sticks in the product codebase through all production releases forever.
Efficiency is one (good) thing, but laziness is a totally different thing.
Tailwind just destroys a lot of good code design philosophies, and this article has pointed out many of them quite nicely. So I agree with this article and disagree with comments implying that this article is pure badmouthing.
Having read the article, I disagree with some of the statements and find others to be demonstrably inaccurate.
Things I disagree with are mostly summed up in this part: "If you choose Tailwind for a mission critical application, you will end up making your job harder, your application more brittle, and your team, in the long-term, will suffer."
I have not (anecdotally) found this to be the case. I maintain many applications that use vanilla CSS, many that use styled components + react, a few that use SCSS, and many that use Tailwind. I have not found apps that use Tailwind to be more brittle or cause me or anyone else in my teams to suffer.
Fortunately, the onus isn't on me to prove a negative. I do not see any evidence to support your assertions, here. Only more anecdotal statements.
Things that are demonstrably inaccurate:
Thus, I find your article outdated, or disingenuous, or both. There are obviously pros and cons for each, but I find it's best to learn the substance of what you're trying to prove before you attempt to publicly shame a library/technology you don't appear to understand.
Look at all those comments!!!
Looks like you opened a can of worms :D
I've also been in the business for a while now and came to a similar conclusion about Tailwind. I do think the utility first approach has some merit; but I'd much rather just add a global stylesheet to a project where I define carefully tailored utility classes; rather than drop in something that does absolutely everything... and then waste time figuring out exactly which classes I need to use to meet my goal. The custom approach also has the added benefit that junior devs have a clearly defined selection of classes they're expected to use; rather than coming up with needlessly convoluted solutions using arbitrary Tailwind utilities.
I think component-based frameworks have contributed to Tailwind's popularity. I've seen people obsessing over building all their styling into their components (so they are properly portable) when the likelihood of those components being used in other projects is literally nil. That can lead to a ton of unnecessary CSS duplication (because global CSS is apparently evil); and Tailwind looks like an effective solution to that problem; because it's just another dependency in your package.json...
The real test for Tailwind will come when people have to implement re-designs 😅
To be fair, when I first started to use Tailwind and obviously before that I was rather sceptical about using it because I thought aswell it would bring us back to earlier days, now frown upon, of inline styles. However nobody seems to care and I realized Tailwind is just one of many Utility-first CSS frameworks. You are correct in assuming that you could just write normal CSS instead of using Tailwind. That said I believe that frameworks are tools that help us not to repeat us. They are not necessarily some kind of magic, rather they just safe us time and writing all those handful classes by hand is possible but not needed.
Maybe you should try to start implementing only the most basic things like for example colors, so you use text-orange-600, bg-orange-600, outline-orange-600, border-orange-600, ...
You also mention using @apply it pointless. I sometimes find myself thinking about that aswell. Needles to say I do use it, because it mostly allows me to be consistent (especially with things like colors) and let's be honest, it's just faster to write :D
I've recently used it in a project for the first time. I share some of your concerns.
I was also using tailwindui, which is a set of patterns built on top of tailwindcss, so things got extra blurry for me.
I felt like there was more html than required (tailwindui) and tailwindcss felt like "classitis" from back in the day. I also feel like I know CSS pretty well, but I was having to learn a new syntax for no real gain.
The maintenance side also looks like a headache as you end up with really long classnames that scroll off the screen for days.
I'm sure I've got plenty more to learn, but it's a rocky start.
Great article, well written and your point is valid. Just because a lot of people are using it, doesn't make the case.
In the end, everybody is free to use what they want, howevrt keep considering the up- and downside on the short and longterm.
Key point for not using tailwind is, that I have never ever had problem for what it is trying to do. I coded almost everything tailwind is doing just in an hour with my own classes and reuse it in projects, why would I mind to learn another thing, cause some people know too few things in styling/sass/less ? Use whatever you want, but don’t make such a big thing out of it.
I love your article since it confirms my own internal rant about Tailwind😉 One remark from the side: utility classes do have one advantage over inline styles you did not mention: These days, it's best to have your site send "Content Security Headers" to avoid accidental execution of dangerous 'code'. When you use inline styles, you have to taint your content security headers with the ugly "stye-src: unsafe-inline' directive - which also opens up your site to nasty styles injected by others.
But that's no argument for Tailwind - there are better ways.
I think "inline styling with slightly different tradeoffs" or "slightly different syntax for writing classes" surmises the two ways Tailwind can be used. The former is perfectly sensible for 'single-use' code (e.g. a lot of websites rather than web applications are expected to expire within a couple of years at most), the latter is a lot more questionable for me. I often talk about how when you have a custom solution and a standard the custom solution should offer great benefits over the standard to be picked.
Aside of what you already mentioned I think there are two more angles to be considered: Tailwind as an alternative CSS syntax introduces a lot of abbreviations (Reminder: "Code is written to be read by humans, not computers") and it's like having to learn a new language without any certainty that anybody will use it down the line. Additionally I think some of the popularity of Tailwind is coming from people less familiar with new CSS features. Many comments talking about the advantages of Tailwind will often talk about the advantages of things such as flexbox and grid layout. This then results in these people further postponing learning these properties properly, making Tailwind basically an underarm crutch (the type of crutch which ends up harming the patient) for those people.
One of the fundamental false assumptions in programming is that you're going to happen upon things that are reusable while writing your code. And thus you write everything for potential re-usability, despite the fact that it also makes your code more ugly.
CSS outside of Tailwind has this exact problem to a T. The idea that you're going to create this easily modifiable theme for your website where all you have to do is change a few definitions on a handful of classes and everything is good, is laughable. If you have enough reason to restyle small things, you're likely going to have enough reason to redo the entire layout of the site. And then those classes you built up in CSS are suddenly going to be useless. And there's a good 50/50 chance that a lot of your CSS that just sits there in your file are dead definitions that don't actually get used.
Tailwind embraces the reality that components and the like are highly specialized & rarely reused outside of library code.
As for losing out on CSS features, there's no reason why you can't use both. If you have something you genuinely know is going to be used tons of times, it's completely acceptable to just define that thing. But in the large amount of cases where things aren't going to be used tons of times, tailwind saves you the back and forth between CSS files and what's on the screen.
There's another side tangent here where, honestly. The article suffers from a lack of acknowledging the existence of modern component/template libraries. Lets say you genuinely had a button with the same style across the entire website. There's 0 reason why that button couldn't be a component with its styles set, that gets reused everywhere. There's no reason why you shouldn't be able to create a "PrimaryButton" component in: put your templating infrastructure here.
Then changing the styles on that button across the entire website is incredibly trivial. If it's something you're going to reuse across the website 40 times anyway, may as well make it easier to reference too.
And as for HTML being about the document and not styling. That was false the day HTML was made. In fact, the way we structure documents often comes down to our styling desires. Why is something inside multiple div tags with different classes, even though it's just a text blurb & an image? Because we needed all of that to make our pretty slider.
There's no way to separate HTML from the styling system. Styling inherently requires DOM manipulation for anything more complex than simply displaying text on the screen.
I agree with everything said here, it's liked because of it's simplicity. Inline styles are quick and dirty and a lot of newbies and devs in general like quick and dirty, which explains why tailwind is liked beyond reason.
Sharing my opinion as a beginner. At first i hated using tailwind, the more i learned about tailwind the more i liked it. But the only downside i personally faced with tailwind is not being able to use the combinators. i guess the developers will find a way to include that in newer versions
Brian, why do you not want someone to use this library so badly?
Because, quite frankly, most of the projects professional engineers work on are not greenfields; we are bound by the decisions that were made by the previous owner.
There's often not enough time to refactor, if a decision made in the past turns out to be the wrong one. Instead, you just add it to the technical debt.
When I see a framework that's only going to cause problems down the road, I feel that I should warn people considering adopting it what those problems down the road would be, so that hopefully they choose something better, or at least go into it with full awareness of the things that they have to watch out for.
Have you ever actually inherited another person’s CSS before? I’d much rather inherent a Tailwind project. Maybe you enjoy working with CSS vomit, but I sure as hell don’t.
I agree with all of this, and have been mulling over making a post about it for a while.
Save yourself the trouble and don’t. You too will sound like a clown.
When it comes to Components, Tailwind makes sense.
Well, I love Tailwind but I agree with some of the principles here, using 8000 classes inline is the thing I hate more, which is also why I hate bootstrap.
However, with Component Driven Development, using BEM convention along with @apply for me is amazing, especially having Figma components based on Tailwind spacing, classes, etc.
You can define your own project variables to use with Tailwind itself, so I can't see the problem.
you can save a lot of time just saying “I don’t like it” and that’s it.
use what do you prefer, I’ll listen jazz while writing some tailwind classnames 😄
Tailwind allows me to have consistent CSS on my whole app.
Let's not even talk about how easy it is to make your website responsive with tailwind instead of writing annoying media queries.
How could you not love it?
The title is super funny.
.. <('_')> ..
I almost named it: "TailwindCSS: If it's named like a fart, and it smells like a fart..."
But that would be slightly unprofessional, so I toned down the obvious joke and buried it to the third paragraph.
Ah yes, comparing someone’s hard work to a fart in the body of the post is not at all unprofessional.
I mean you can still use tailwind and use the function @apply in the css and make class names with it? And with the newly introduced 'jit' mode it's faster than ever before to compile it
@brian boyko I'd maybe revise your statement about similarities to inline styles. It's well known that tailwind is only responsible for generating CSS. How that CSS ends up in the HTML is ultimately up to the build system - not tailwind.
And this is an important fact too, because CSPs have been under growing scrutiny to block all inlines. When you look at it from that perspective, Tailwind is doing all of us a world of good having one more tool in our toolbox to avoid unsafe inlines.
Second thing to consider: tailwind encourages devs to drop frontend libraries in favor of rolling their own UI. So, in that respect, it is actually like more of a gateway technology into learning more about CSS - not avoiding learning it.
The Rick & Morty meme really brought it home. Peace Among Worlds Tailwind 🖕
F**k you! (It means "Much obliged.")
As a fan of Rick and Morty, I totally understand why people view fans of the show as insufferable douchebags. Case in point here.
haters gonna hate
Tailwind really scared me away for a long time when I first saw it. Although I never considered it as basically inline styles in a class attribute, long chains of classnames were off-puting.
Until I really tried it in my Vue-based project, which has one specific need - ability to provide many options for initial theming of app instance. Not only colors, but buttons, inputs, layout to some extent etc.
And as many people in comments said, tailwind config is the place when it really starts to shine in terms of customization and "the management center".
On top of that component based frameworks like Vue really works with it nicely, at least for me. I'm all about separation of concerns, but not having to constantly move between template and style sections is convienient once you get used to it. I can focus on logic which is ideal if it doesn't rely on querySelectors anyway, components should be small if possible, so tailwind doesn't bite back.
In my opinion there's no CSS framework in existence that would not fail without proper planning of using it. Styles needs as many planning and strictness as other parts of frontend to avoid inconsistencies.
I really don't like React, kinda like Vue and really like Svelte. But those preferences came out from my personal experience with them, I can write how I don't like the shadow DOM and JSX to immediately receive response that they're not a dealbreakers and JSX is an attempt to avoid Vue/Svelte template magic - who wins? Someone who finished a project. But then competition was never about a technology being used.
Bootstrap really got under my skin during it's fame, cause a lot of people wanted to use it on front websites...where from my perspective it was a tool for creating more technical things with established UX components and quick prototyping, not hacking it from Adobe Photoshop design into client's site with many whoopsie-doopsie layout ideas. Bootstrap + Adobe...very dark times for me. But it was popular, so it was required "in case of changes needed from other developer". Add code bloat to it, float clearfixes where inline-block, although also hacky, didn't throw content out of document flow just to put it back after and yeah...nope for me. But in my opinion it's a perfect example of harmful hype, maybe you had similar experience with TailwindCSS (everyone wanted to use it everywhere).
Wrapping up, cause it's a long one - just because it didn't "click" for someone and there's a ton of fuss about it forming one more cult around it (especially then) - doesn't mean it's useless. It's just another way, especially when at first it's strengths can be overshadowed by questionable approach (here - coming back to tags highways). Sometimes the best thing to do is to try something new in a sandbox - away from hype noise, deadlines and already existing projects to rewrite. Cause work environment with a time span, sometimes stubborn teammates/clients and waterfall of new frameworks keep coming can put everything in a bad light.
First of all congrats on pointing to Benoit Rouleau post. I am a tailwind fan, I read his and he is really angry.
I do understand your frustration and see where you are coming from. Correct me if I am wrong but it seems like you are mad at Tailwind because somebody forced you to use it, despite the fact that there were better options. Aren't you Shooting the messenger instead focusing on the message? Tailwind is just a tool designed to perform a specific task and with every tool there is a technique and a use case . I used to hate it a lot and I would prefer writing css from scratch or use bootstrap, but I gave it a try and for rapid prototyping it is a great tool. I love customizing things in real-time, especially when I am doing demonstrations, and it has so many options. I really love it and Adam did a great job here. I am really sorry for you, you are missing a lot without Tailwind. My challenge to you would be helping to make it better.
I find it easy to use tailwind for POCs. Especially since I use React, all I need to do is create my components and the rest of the team can use the component without thinking about the implementation details of that component unless they want to change it's design
I tried it out, I’ll stick to BEM or SASS.
The most unreadable CSS I’ve ever seen was in BEM. You can use SASS with Tailwind.
If tailwind provided a ::after and ::before way, I'd even consider it worthy of being tried
There is a Tailwindcss pseudo elements plugin. It shows how that could look like in some future Tailwind version.
npmjs.com/package/tailwindcss-pseu...
Interesting opinions here... I've been writing HTML and CSS by hand since 1999 (full use of CSS a few years later since support in 1999 was still iffy). I agree with the author, Brian Boyko. I have researched Tailwind extensivelly. I just don't see the benefit. It feels like we are going back in time when FrontPage generated all our styling inline. I hated it then, I still don't like it now. However, I think maybe a lot of developers do not really grasp CSS. It's another technology to learn. In that case Tailwind may be a good option.
I love functional css... havent used tailwind bt love tachions.
Tachyons was the first utility-first framework I used and I loved it. Tailwind’s like a version 2.0 of it. I don’t think anyone even maintains Tachyons anymore.
I wasn't expecting a tweetstorm cause this post.
Gotta agree with you here.
css-without-using-css doesn't need to be a thing imho.
Reading style horizontally is the only one enough reason not to use TailwindCSS, also all the cryptic names of classes. I don't want to learn cryptic version of css properties I already know.
After taking a look at your article I realized one thing:
...You truly don't know how to use Tailwind CSS for real.
Agree, long ass html classes will wreck you. Good luck with querrySelectorAll ByClassName or worst good luck using it in angular. There will be alot of !important, return Null, and conflict everywhere
I’ll agree it’s difficult to read
no words 🤣
I keep going back and forth on loving Tailwind and not loving Tailwind. I need to go back and re-read the post more thoroughly (just skimmed it). Always good to read a well-thought-out counter point.
What about @apply, I don't understand why you don't mention it, as it addresses at least some of the problems that you consider unsurmountable.
I do mention it.
Second paragraph under " It solves a problem that doesn't exist. "
You clearly just scratched tailwindcss from the surface
Something to think about. 🤔
Tailwind is design system framework that is meant to be constrained and works best with ui component if you need abstraction.
Please don't use combinators in big projects...
I agree with every letter in this post. Tailwind is inline styling, there's nothing good with it.
Not to mention the weight it adds to your HTML files by having to add a huge list of classes to your elements.
Consider this avabucks.it/
Very good article, appreciate it.
Not too many people want to post well-thought-out critiques. Done well, it is an important part of the conversation. Thanks for doing this.
At last... Someone, who thinks the same... We can talk about dynamic class/style... oh! sorry, **tailwindcss **doesn't have that eather...
You captured my feelings on tailwind perfectly. This will be my reference going forward the next time I’m dragged into this debate.