Hmm, I’ve always considered tailwind like the spice to make css actually usable, kinda like elixir is to erlang, typescript is to javascript or C is to machine code.
Its still CSS just the stuff that you _actually_ want to build is pre-packaged and thought out for the use case.
And I’m not dissing on CSS - just those tools try to solve different problems.
CSS is the ground truth, and it kinda has to support all the weird edge cases and uses that tailwind doesn’t.
Tailwind is like usability overhaul of css, but still allows you to “drop down to css” everywhere you want to.
It can compose like css, but it also constraints you to what you can do. It also gives you tools to group, adjust, refine styles, but in a usable way.
It’s a transpiled language on top of css, but more ambiguous than sass or less.
Given enough time most projects I work with slowly gravitate towards small composable utility classes anyway, tailwind is just logical evolution of that.
And since design peojects usually gravitate towards design systems in the long run, tailwind is really good at facilitating that.
What makes tailwind feel wrong for me is that you put the css classes everywhere exactly like you would set inline style attribute. I would prefer using the css slectors and select by an id or class name and apply a css like that. I avoid frontend but this is how I see it used in my team.
Would be nicer if you could do it like
selector > color-xyz text0xyz paddifng-xyz
and never add those classes inline
But to your suggestion - you can! Thats what components classes do in essence. When you have a bunch of styles that _always_ go together - you bunch em up.
But in practice it is usually simpler to keep the classes and use other templating features of your platform to achieve this.
It becomes extremely nice as every time you need the question “why is my html look like this” answered, there is no hierarchy of other files to dig through - its all just there.
And as with any tool you can abuse it in ways that are not intended - seen plenty of ugly tailwind examples with tons of weird unruly code. But thats even more true for css itself. Omg the horrors I’ve seen with custom raw css cans still give me nightmares.
I know there are many tutorials doing that, but that is not how I use Tailwind. Tailwind entirely supports your own CSS files and you can use @apply to compose all of the existing classes together.
Just because something is old doesn’t mean it’s correct, this is such a curmudgeon take. Things we have have evolved over a long time, have been started hastily (JavaScript) and there’s no reason to believe we’re not in a local minimum and something much better is out there.
I personally believe the js model is completely wrong for the browser and something like an actor model would fit much better.
I’m not saying we should jump on every hype train, and personally really dislike the react ecosystem but I also think we should encourage exploring new approaches. CSS, html and js evolution is driven by the exploration of these new frameworks and they’re very different than what they were just a few years ago
I agree, it's exciting to have the industry trying gazillion things and see the survivors that get pushed into standards. It's much less exciting to have your project tied to frameworks (generic statement, not about Tailwind) that rot, requires massive rewrites on update, are unstable and forces you into non-standard stuff that tends to not interoperate well with the external world.
I'm puzzled to see the popularity of such frameworks while boring technologies often are well documented, well tested, highly stable, provide acceptable dev efficiency, readable by any dev, and often comes with much better performance.
I'm probably just a grumpy old man yelling at clouds.
I feel we need a club for grumpy old men that yell at clouds! I'm only 34 but after 10 years doing this I now fully understand what my seniors were trying to teach me when I started.
Boring technologies that work and will continue to work with the minimum of lock-in and fuss long into the future are what get me excited now.
I’m a bit older but I’m getting progressively more annoyed by this attitude of my peers, and increasingly think it’s an excuse not to learn new things.
I know plenty people that are stuck in Python and are some middle mangers and just yell bah! at everything new.
I’ve worked through the whole stack, am now heavily in elixir, work in a cutting edge LLM company and feel I’m better than I ever was. There’s a balance.
Agreed, balance is needed in every aspect of life. The conservatism of many experienced developers is likely an over-correction and the result of some scar tissue. There's always room for growth and trying new things, but with those lessons learnt in the back of your mind still.
I've shifted career and work as a photographer now, so remain ultra-conservative in my technology choices because I know I don't want to expend the time and mental energy to adopt over-complex solutions. It's less about how old/new they are, and more using the right tool for the job.
PS: Glad to see Elixir cropping up more and more. I loved using it before I changed careers, and still keep tabs on it. I've got an idea for a small API/service that might benefit my work, and unless I stumble upon a more appropriate choice, it'll likely be based on Phoenix.
it's kind of a trope now in social media for people to look contrarian against current web tech. There are whole twitter influencers out there that are not known for any achievements but just pooh poohing popular frameworks. Just an easy way of grabbing some status, I guess. And platforms love the engagement it brings.
I can see a top tier game engine developer talking with skepticism about current web tech, but it's more often coming from something like enterprise java devs from the 2000s that used to take months fudging with class hierarchies to deliver a basic form GUI. The kind that must take any opportunity to denounce electron apps but would never give up VS Code and go back to Eclipse.
Yes because SCSS and various other new technologies have tried stuff out and we took the best back to CSS. No reason to think tailwind won’t influence css. For me it’s an improvement upon the style attribute which we have been neglecting and have been told not to use for some reason. I think it’s great to be able to adapt a component locally without putting a one off class somewhere which we have been doing before.
it only took ~20 years to get a working vertical align (which was available in HTML from basically day 1, might I add). similar for grid to be available and it still kinda sucks.
It really depends, for most simple landing pages painkillers are just fine, I've also created extensive dashboards that were used 4-6 years without much iterations, then it's a waste to think too much about css structure. And clients are happy if it looks a bit sexy.
For a long-term project that will require lots of development a more thorough approach would be justified.
And it's not even about what the developers want to do, often it's about what the clients want to hear. I believe in "boring tech" and I'm a late adopter as well, but many clients think of old, dated, outdated, deprecated, unperformant when they hear about a take like this. Often we need to do React just because that's what many clients think the modern UI does. And, in a way, there is a grain of truth to it: since it's also cool with many developers, it's easier to find developers on the market for it, should the project need new people.
With that said, your premise is correct. Prevention is uncool, and safety seems overbearing, preparation is met with "YAGNI". Until people need it.
The multi billion dollar vitamin industry disagrees. Kidding. Only half. I dislike this saying because it doesn't mean anything and just makes some VCs think they're saying something that sounds smart.
There are frameworks that genuinenly improve the development experience for certain uses cases. As with many things, it's important to still now the basics (in this case, CSS), but why not use Tailwind if the philosophy aligns with yours and makes you more productive?
Sure, switching frameworks ever few months to try the hottest shit out there is also not great, and many people overuse frameworks (e.g., React is an overkill for many (most?) applications I have seen). But that doesn't mean there isn't merit in frameworks.
The vitamins vs painkillers analogy is about productivity-boosters vs problem-solvers. Using plain html/css/js is neither of those. You could say Tailwind fits both of them.
I was going reply at the top-level because my opinion is vastly different to the majority of comments so far, until I found yours. Years ago I very much enjoyed finding painkillers to make my work easier. I now only take vitamins.
I'm very much in agreement with the author (regarding Tailwind, I'm Web Component-curious but yet to be convinced to the degree is obviously is...). I started with Adam Morse's "Tachyons" library which is the pre-cursor to Tailwind. Conceptually that worked for me, particularly because I was all-in on the JS ecosystem, building a startup with React and Meteor (story for another time). I wrote up my thoughts on a now-extinct blog [1].
Over time though I found JS to be a fragile and brittle ecosystem to work in; I'm sure as many others have. I not only moved away from SPAs and JS as my backend language of choice to avoid npm dependency hell, but also any JS build tools because using the latter is functionally equivalent to the former.
When my choice of language/framework at the time (Elixir & Phoenix) added support for Tailwind by default, without a JS build tool (handled by an Elixir lib) I was conflicted. I had gotten used to vanilla CSS again with all the new additions such as custom properties and wasn't convinced I needed Tailwind. Even though it didn't bring the JS build chain I hated, it still represented a hard dependency to replace down the line if required, and still required a build tool. It was potentially a decision future me would regret. These days I'm all about not snookering future-me.
I think Tailwind has it's place where you're already using a build tool that can support it (JS or otherwise) and you're working in a team that needs a design system straight out of the box. It gets you up and running quickly (particularly with their TailwindUI components and themes) and provides a point of reference for everyone working on the project without coming up with a design/token system of your own. But that can be said of the older frameworks like Bootstrap or Zurb Foundation (remember that?!).
Personally I'm very happy writing HTML, CSS & JS without any build tools, bar a bit of templating to bring in partials here and there. Admittedly I'm working on very different websites now, but I spend years thinking that the foundations of the web needed augmenting and abstracting away (they probably did at that point...), but now I'm quite happy to work with it in it's natural state.
In your analogy, wouldn't tailwind be more of a multivitamin, in that it contains a bunch CSS classes (vitamins) conveniently packaged and ready to go?
I haven't used tw yet, but I intend to because I was blown away by how much sense the authors' book Refactoring UI made.
Taking multivitamins is usually the wrong approach. So they are indeed a kind of snake oil.
Which condition do you intend to treat by taking multivitamins?
Have you looked at randomized controlled studies and found that they support your idea that taking MVs has a positive effect on that condition?
Have you got your bloodwork done? Did the doctor then suggest that based on your situation MVs are the right approach? I never have heard of such a thing happening.
So yeah, TW and MVs are similar. Both appeal to people who think "Hey, why do the work and figure things out and act appropriately? I can just swallow this magic pill!".
Tailwind provides many classes to use right out of the box, whereas vanilla CSS requires classes to be written, which takes longer.
If someone's good at, fast at, and enjoys writing vanilla css, it might be the way to go, but if they don't have a sense of design or lack skill in writing CSS, a framework allows pages to look professional quickly.
A site made with a css framework may not be as extensible as one made with vanilla css, but if there's strong enough desire it could always be taken out and swapped for vanilla CSS.
For quickly getting things done on projects where time/resources are , I'd go for a frame work (for the reasons above: I lack a sense of design and would spend an eternity tinkering and doubting my design choices).
This was my experience as well. I talked to three different doctors in two different states and they were all lukewarm at best about multivitamins when I mentioned them. "It won't hurt anything" was about the best I got from one of them.
I love tailwind. I strongly feel that most modern CSS solutions are massively overthought. In engineering we have bigger problems to solve than a key/value list that makes a div blue.
Tailwind removes the thinking around CSS, naming, preprocessors etc etc, it just lets me write good CSS and focus on components and other engineering problems.
I seem to be one of the few people who can read CSS properties horizontally as well as vertically, so I'm all good on most peoples major complaint.
Tailwind on the other hand looks like a hellish nightmare, horizontal reading, proprietary syntax, no selector targeting of other components.
Is "horizontal reading" worse than reading two files?
What if the other file is actually 30 files compiled with SASS?
What if they're 30 files, compiled with SASS, and written by a bunch of devs who don't know CSS well, didn't use BEM or anything to name things well, and didn't organise them at all?
Tailwind isn't better than great CSS, but it's significantly better than bad CSS.
> Is "horizontal reading" worse than reading two files?
I see this complaint a lot but I don't really get it. You can have a styled component in the same file or a separate file. In VSCode, you just command click on the component and you go straight to the style definition. Not an issue.
> What if the other file is actually 30 files compiled with SASS?
I only work in Styled Components-exclusive codebases so can't comment
> What if they're 30 files, compiled with SASS, and written by a bunch of devs who don't know CSS well, didn't use BEM or anything to name things well, and didn't organise them at all?
Yes, you have. And this is really, really common in large scale web apps, especially where they've been mostly written by people who are 'backend' or 'full stack' developers.
Tailwind didn't just spring forth as a tool to screw with web developers. It was developed as a solution to a problem. That problem being bad, unmanaged CSS at scale. If you don't have that problem obviously Tailwind isn't going to look useful to you.
If horizontal reading bothers you so much it resembles a hellish nightmare (Dante would like to have a word with you), nobody stops you from going like this:
It's a fairly limited set of rules that are mostly consistent, extensively documented, and easy to remember. But yeah, a little bit of effort is required when dealing with a styling language with over 300 properties.
Without Tailwind, you'll have to come up with a unique, declarative, distinctive name for each and every element you're piling styles upon. At first it's a button, then there's buttons that should look like links, and then clickable icons. They share some properties, but not others, and before you know it, you've invented an ad-hoc description language in CSS classes that nobody except you can understand right away. With Tailwind, you may have sequences of tokens that seem confusing at first, but at least it's the same -- few -- sequences in every single Tailwind project under the sun.
No side effects, no blurry concerns, no more specificity issues. If you don't appreciate that, you haven't seen large enough projects yet.
> Without Tailwind, you'll have to come up with a unique, declarative, distinctive name for each and every element you're piling styles upon
I can honestly say I've never spent more than 5 seconds thinking about what to name a styled component, do you really get decision paralysis with this?
The equivalent styled component of the default Tailwind button of "bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded" is "styled.div`background-color:#8888ff;color:white;font-weight:bold;padding-y:2px;padding-x:4px;border-radius:4px;&hover{background-color:#aaaaff}`".
Obviously you wouldn't actually write it like that because it's inline in your code so you can format it better, but the Tailwind version is less verbose and easier to read if you did.
"Less verbose" I guess by a few characters... at the expense that you're not writing real CSS rules. So you're having to translate every rule into whatever Tailwind's syntax is for the same thing.
My biggest issue with Tailwind is point #5 on the article: Tailwind encourages div/span-tag soup. Together with the class name soup my HTML becomes unreadable.
A big issue that these articles never mention is that using browser dev tools to debug CSS becomes a huge pain with tailwind. It also makes it harder for community to create custom themes/user scripts for your website/app since targeting specific elements becomes incredibly hard when no class names exist.
Not to mention, it basically puts a dsl on top of CSS.
CSS by itself is great, and with all the modern changes you hardly need to use preprocessors like SCSS (there's still some advantages but far fewer than say, 5 years ago).
I don't understand the people in the thread that hate writing CSS...
To be honest, I don't find that a problem. Most frontend development is done in a higher-order abstraction like React. For the most part, I don't read HTML and I don't write HTML. If you use the right level of composition, "div soup" should never really be a problem.
It doesn't the author is just bad at semantic HTML. That first example should be an `<article>` and the 5th example doesn't actually show div/span soup.
I love tailwind too. The article did not convince me as there was also no real solution / alternative proposed.
I have written custom css since the year 2000 and using tailwind just makes me much faster (is like setting flags) and simply by reading it, I understand how an element looks like. No matter if my past-self wrote it or another engineer.
It can pollute the HTML (although @apply helps a lot to define your reusable .title, .card, .btn, .btn-lg, .btn-primary etc), but at least it is written in HTML and not in JS, which is even harder to transfer to other eco-systems.
Also extending styles (tailwind config) is amazing if you want to reuse your styles in other projects.
Especially in the HTMX community I'm alwayws wondering why people are chosing Tailwind. I tried it too and had the same problems as stated in the article.
Mainly that its polluting the HTML so much. I went the opposite route and am using PicoCSS now which works with semantic tags and can even work without any classes. Feels much cleaner
Spaghetti-ness is orthogonal to locality. You can have a clean god object, or a tangled abstraction. In my experience, neither invites spaghetti-ness more than the other. With less abstract code, you have less abstract spaghetti, and with more abstract code, you have more abstract spaghetti. And you can do both cleanly as well.
This - the burden of affixing and naming the hundreds of pieces of composite styling consisting of 30+ tailwind classes is fully moved to the poor guy who needs to read, grok and maintain the code that the original author was too lazy to care about.
Disclaimer: I’m extremely newbie in front end, probably less than 6 months of experience combined in the last 6 years.
I can’t stress enough how easy it is using Tailwind, it just works! I don’t care about the long ass lines because for how I’m used to format html pages, I’d have to go to a new line anyway, it’s just that now I can understand what’s happening in react components without too many troubles.
Another plus is that by checking other people’s html code, I can immediately see their tailwind tags, without searching through files for css definitions, I see how they change their stuff there and I can immediately learn how to replicate their patterns.
Imagine how fruitful saving time is, especially when using framework like nextjs, you can literally launch a prototype in few days of work with these technologies.
Don’t get me wrong, I know that you’re not going to build the next Facebook or Microsoft with Tailwind and Nextjs, they have their drawbacks, but their impact on the critical path from the idea to a working MVP can’t be ignored.
I don't quite get the hate for having CSS in another file. Do you also put all your react stuff in one single file ? That same logic and argument can be applied against all modularization.
And really 20-50 tailwind classes in a single element is VERY hard to read and keep in mind. No - it does not make things clear or understandable. One tends to need to re-read and scan over from the beginning and eyes glaze over. Esp if some elements only vary with a few classes missing. I guess it works for people with very high attention to detail and high amount of working memory. I only find it personally frustrating. With a CSS class applied to that component, one at-least has a singular NAME to refer to that piece of composite styling and your memory can be used for other matters.
Maybe tailwind css works well for some bright, big-memory developers. I did try it for a couple of projects, including needing to maintain someone else's tailwind project - and only felt stupendous pain.
However, the "atomic css" philosophy behind tailwind is great. I find frameworks like https://open-props.style/ a far better application of that principle.
You are supposed to abstract messy tailwind classes via your programming language and the component framework.
For example: using loops, breaking things into smaller reusable components, etc.
Tailwind devs specifically recommend against making your own abstractions in your CSS that coincide with your abstractions in your programming language.
So for example instead of CSS classes for buttons just make components for the buttons to be used directly.
yeah, it works, but try getting back to this codebase in 3 months and then refactor something small. worse, it’s someone else who will have to do it after you.
As a non-web developer with a couple of relatively sophisticated side projects, I've never understood the appeal of Tailwind. It somehow manages to be hideous, verbose, and absolute gibberish all at the same time. If I wanted that, I'd write everything straight into the style tag. I can't understand why Tailwind would be any easier to maintain (and I'm sorry, but you will never convince me that I need a javascript precompiler for my damn stylesheets).
Yeah, it isn't Tailwind that doesn't support web components. It's Shadow DOM that is such a bad abstraction that it breaks the web in innumerable ways and need dozens of new standards to fix its shortcomings.[1]
And yeah. That <fancy-component> that is seemingly not an eyesore? It's not because Tailwind is bad and "pollutes HTML". It's because web components hide any and all ugliness from you so that you can pretend they are beautiful.
Because in the end there's literally nothing on the web but divs and spans
It's worth noting that many of these pain points are directly related to Shadow DOM's encapsulation. While there are many benefits to some types of widely shared components to strong encapsulation, the friction of strong encapsulation has prevented most developers from adopting Shadow DOM, to the point of there being alternate proposals for style scoping that don't use Shadow DOM. We urge browser vendors to recognize these barriers and work to make Shadow DOM more usable by more developers.
I'd like to like web components, but their reliance on JS to instantiate along with all the chaos of the shadow DOM keep them off the table for me. I think they are a great concept defeated by the implementation.
So essentially what partials in a template or server-side include solve.
That's the only "build-like" part of my current website, but I'd much rather manage this beforehand and serve static HTML, or run a server-side process than use JS/HTML web components at runtime.
```
<marker-of-dynamic-behavior>
{your standard static html}
</marker-of-dynamic-behavior>
```
This is just a better way of doing DOM scripting, enhancing without waiting for Document Ready event, and having more freedom when to load the dynamic bits.
I use Svelte for frontend develoment, and used all of JS frameworks that came before it. It's very web component'y. I feel Tailwind was partially created by the problems rising from the bad design choices of many modern web frameworks.
In Svelte, There is less need to use Tailwind, because HTML, CSS and JS (or TS) are all encapsulated in a single source file. Editing CSS alongside the HTML is easier than bloating the HTML with a class hell. You can use native syntax highlighting, IntelliSense, early compiler error catching and linting plugins of your editor.
Of course it's easier to use. Pressing the bold button in MS Word is easier than setting up styles etc, but one makes it easy to create an impossible to maintain mess that could have been made by a primary schooler, and one makes it possible to create a consistent style that looks professional.
The only reason I think Tailwind is becoming popular now is it's exposing a bunch of things like rounded corners and drop shadows that are still cool but unlike Bootstrap you can slightly tweak your rounded corners easily. It'll still lead to everything looking the same, then people will probably ditch it and go back to really minimalist styles like HN to look cool again.
Tailwind is opinionated, meaning it encourages a structure that helps devs avoid common potholes.
You may not like its choices but saying it creates a mess has been the opposite of my experience.
One of the main pitfalls I have noticed no longer running into is that the structure tailwind encourages prevents issues with CSS selector specificity. As a result I’ve definitely noticed fewer instances of ‘!important’ in code review.
You could instead learn what patterns should be avoided and why. This means you can make meaningful judgements on whether it's ok to use those tools on occasion (like goto in C).
Tailwind is a mess by default. People didn't invent separation of style and content for no reason. They did it because what they were doing before was as mess. This is that same mess.
"You could instead learn what patterns should be avoided and why."
In an ideal world yes. But in the real world nobody knows everything, we have deadlines, and no company actually sets aside time to onboard you on CSS.
But also, it takes a while to establish a pattern. Using tailwind wasn't my decision and it took a while of working with it before I noticed that I was rejecting fewer PR's for `!important`. It took a little longer to establish the cause was tailwind and the reasoning behind why.
But also, how are people supposed to learn with all this noise? Most of the critique of tailwind in this thread is incredibly surface level.
I really dislike tailwind too, but I think there is lot of value for lots of people in the idea of having all the styles contained with the template and thus making copy-pasting of code easier without having to deal with the pesky 'Cascade' part of CSS.
Personnaly, I love the cascading part when used correctly, along with the 'latest' evolution of CSS such as 'calc()', variables, on top of using CSS selectors.
The endless roundabout of discourse on which technology choice you should or shouldn’t make is exhausting. As a senior engineer im able to sift through the bullshit on this but as a junior I remember these discussions were draining and also made me feel like shit about decisions I’d made.
I guess it drills into a part of human nature where we are always measuring ourselves and our things against others.
I don't feel that a simple upvote is enough to express my support for this statement. I'll +1 this all the way to retirement!
Technology-choice as fashion needs to die. There are suitable tools for the job, and unsuitable ones. Deciding between them gets harder when loads of amped up juniors are selling each other on the benefits of the latest and greatest without actually putting them to the test over the course of years/multiple projects/iterations.
Decent arguments. Ultimately, I think your preference comes down to:
- Do you care about how your html output looks? - I personally don't, just like I don't care about what my Webpack bundle looks like. Web standards will always be slower to evolve, which is why we build tooling on top.
- How do you think web components will be used? - I believe they will be used sparsely, only by libraries. But if you want to replace your frontend framework (I currently don't see why), Tailwind will not work.
We've opted to work with CSS Modules (which give you many of the Shadow-DOM advantages), but I would be lying if I didn't see the appeal of Tailwind every day. For me, it's the redundancy of having to give semantic names to elements that are already described by their React component names.
Tangentially, developers often are tempted to use classes for things that should be components. CSS classes must not be used for code reuse on a large scale, because CSS and HTML are bidirectionally coupled and you will end up search-replacing large sections of html because the design team wanted the text to align in a way that is somehow impossible without adding a div.
As in: it took years to get something thats even remotely comparable to framework components. Tooling can move fast and course correct, the standards have to get things right the first time.
> Do you care about how your html output looks? - I personally don't, just like I don't care about what my Webpack bundle looks like.
It's not a good comparison. You won't ever read the output of your Weboack bundle, but you will surely read the html you write (or worse, is tasked to modify or debug).
If you're already using a build system, then throw in Tailwind pre-processors, and you will ship only the classes and styles that are actually used on your site.
Unlike, say, Youtube which ships 2.74 megabytes of css. With amazing non-compressable unique names like .`yt-mini-app-container-view-model__loading-icon-animation` and `.yt-spec-button-shape-next--size-l.yt-spec-button-shape-next--icon-button.yt-spec-button-shape-next--segmented-end`.
And re-inventing utility classes, badly:
.yt-spec-button-shape-next--size-xl .yt-spec-button-shape-next__icon{width:24px;height:24px}
.yt-spec-button-shape-next--size-l .yt-spec-button-shape-next__icon{width:24px;height:24px}
.yt-spec-button-shape-next--size-m .yt-spec-button-shape-next__icon{width:24px;height:24px}
.yt-spec-avatar-shape__button--button-extra-small{width:24px;height:24px}
etc.
And Youtube is just an example of a symptomatic issue: everywhere CSS ends up growing beyond anything reasonable, with multiple repeated and duplicated styles that everyone is afraid to touch.
Tailwind helps with this a bit: there's a fixed number of utility classes, you're supposed to use them inside components (so they are collocated, but unlike CSS-in-JS you don't write what are essentially inline styles, but chose from a fixed set of classes), and only those needed are shipped.
Exactly. I had the luck of working with a codebase that knew how to harvest the power of vanilla CSS (though vanilla CSS in 2020 was already the same as vanilla CSS in 2014), and it's quite powerful. Add to that the browser devtools and it can be very productive.
As someone who used to make websites in the myspace days (and has about that much experience with web dev, plus a few static client sites from high school), I gave tailwind a try for my most recent project. I think it saves me a bit of time, and it's easier to get a decent aesthetic quickly. That said, I don't feel it's strictly necessary, and I don't like the HTML bloating either. It makes me want to create classes, at which point it wouldn't be necessary to use tailwind anymore.
The author says this about using @apply:
> Therefore, it’s simply the truth that CSS files built for Tailwind are non-standard (aka proprietary) and fundamentally incompatible with all other CSS frameworks and tooling. Once you go Tailwind, you can never leave.
How true is this? At worst you could use your output.css and at best I'd expect an automated tool that could do this conversion.
Imo, it's correct, assuming there isn't an automated conversion tool. Moreover, Tailwind has a bunch of confusing class names, and certain limitations (as in classes not being available).
"I think the folks building Tailwind are talented and nice people. But at a pure technical level, I simply don't like Tailwind. Whoever it was built for, it was not built for me."
Tailwind is just a way of writing/architecting CSS. There is nothing in it that "enables" rich web applications which browsers doesn't let you do with (vanilla) CSS, at the end it's just using CSS under the hood (utility classes). And CSS is not the alternative to Tailwind; there are numerous ways to write/architect CSS and Tailwind is just one of them, very opinionated and rigid that you should follow it's way of doing it. But you don't need any specific tool to write CSS, that's the point of the article.
Instead of learning/memorising CSS properties and values, you learn and memorise Tailwind classes which are just abstractions to regular CSS properties and values and you need to write them inside class tags. I think the lure of Tailwind comes from IDE integrations and its documentation. But it doesn't add any "new features" that enables rich web applications which CSS lacks in anyways.
I am a .net guy and had to write react for over six years daily, combined with c#, so I got pretty decent at it. Even did some sideprojects with react.
Recently, I started a new project for work with Blazor, and I felt at home again. It was weird, just a relief to work with what I know best.
I'm not saying Blazor is good or you should use it, but for me, coding was fun again. I truly hope I do not have to work a lot with JavaScript ever again. I just do not enjoy it. Maybe I have to go to full backend after so many years of full stack.
Most of the devs I've encountered that really like Tailwind have their focus more in the realm of development and engineering of a whole system where the UI is a means to an end. They are not deeply focused into the nuances of user interface design.
I can understand and appreciate what Tailwind is all about. It's a standards approach to naming conventions and puts all the details in the markup. Which has its value.
I've found a happy balance to be:
1. utility classes for layout and structural details
2. custom classes for look/feel details
3. after x utility classes, its time to combine into a single class
x is very much based on situation and intuition not a hard rule.
I'm still using LESS because of nested css, and classes can be composed.
One benefit of LESS is the style code is decoupled from react/angular components and more importantly the shadow dom.
I hated tailwind with a passion at first glance. I thought it looked horrible and while it still does, I decided I don't care.
After a while of using Tailwind at work, I have started to love it. It it just so much more productive and I rarely need to step into css-land anymore. You still need to know and understand how CSS works in order to get the most out of Tailwind.
Tailwind is just like CSS but with shortcuts ready there for you to use.
Depends on what you're going to use them for. If you need the actual JS functionality web components can offer, then yes. Though at this point you're in JS land anyways and probably using some kind of web component library (or your custom-built helpers/wrappers/etc.), which usually handles this for you.
If all you want to do is prevent the "div/span-tag soup" as he calls it, you don't have to register anything, though. You can just write <ui-card><ui-card-header>My header</ui-card-header></ui-card> and style that using regular CSS à la ui-card { background-color: red; }.
"User agents must treat elements and attributes that they do not understand as semantically neutral; leaving them in the DOM (for DOM processors), and styling them according to CSS (for CSS processors), but not inferring any meaning from them."
Like I said: If you want to use the JS-based functionality, you obviously have to register it. Simply using any made-up element in your HTML and styling it via CSS just works ouf the box. See https://codepen.io/dkoch-org/pen/yLwPVYG for a quick example.
How exactly is this different from "the 'div/span-tag soup' as he calls it"? You just renamed some divs, and relied on the standardised behaviour of unknown tags. They are indistinguishable (and just as non-componentised and non-reusable) as the div/span soup.
I can't understand why people bother about HTML with long class attributes so much. If you use "btn" instead of a long string of Tailwind classes, you just move the actual CSS properties into a stylesheet file, which you need to switch back and forth to just to change the looks of that button.
And having said that, when using Tailwind with some kind of component-centred framework, those classes will be local to a <Button> component anyway, which is exactly the same as some kind of custom component the author praises (that also needs styles within.)
If you need to adopt the HTML to fit a certain style, you're doing it wrong. HTML should be a semantic markup, it shouldn't change much when you need to change the styling/CSS. So you don't really go "back-and-forth" to architecture CSS, you just write your CSS. But maybe it's a Tailwind thing that you need to add additional elements to HTML just to be able to style it correctly, I'm not sure. It's like saying you shouldn't have JSON files (and embed the data inside the business logic) as you need to change the JSON file when you need to change the logic of the app. In short, you adopt your CSS architecture to your semantic markup, not the other way around.
I don't know about you, but I've never seen anyone create a user interface by writing down the full, semantic markup, and then proceed to create CSS for that finished HTML structure. Instead, it's usually an iterative process of adding HTML, styling that, then adding more content.
That isn't even related to Tailwind, or any other CSS framework -- just that Tailwind allows you to stay in the HTML (or component) context, without having to switch to a stylesheet there.
Your JSON comparison doesn't fit: We're talking about styling, not business logic. But if you mean that I would need to define `"userAgeOver21": true` in a JSON file instead of having some `{{ %if user.age > 21 }}` in the code, then yes, I'm firmly in the latter camp. Not having to switch context often overrules pedantic purity every time.
I don't understand the big problem with switching different files. Don't we write components and tests in separate files? When we develop a component we add it to other components/views. When you need to add new props to a component, you open up the component file, add your prop, open up your component test file write your tests, if there are any tests fails you go back to component file and fix it there, then if everything works you add your props in the view components. Especially when we are talking about components and component libraries, you don't change the styling every other day especially when design tokens comes from centralised places (spacing, colors, fonts etc.).
What people misses out is CSS should be written in state-based architecture. For example for a button you have idle, hover, active, focus, focus visible, disabled states, and combinations of each button intent (default, primary, destructive, confirmation, warning) and color scheme (dark, light, high-contrast, low-contrast) states. Each of these states should enable-disable or modify some prop of the element, in most cases combination of different elements (sibling, child-parent). Trying to write them in inline classes is a PITA, especially the main concern for choosing that direction is just so we don't have a separate CSS file or need to find a name for the class (if you have a component, which Tailwind creators recommend you should, then you already need to find names for your components).
Also in addition to having separate component, component test and view/layout components; we also have separate hook files, separate state/context/store files. Even the component files doesn't encapsulate its own logic inside the same file anymore as to increase reuse of such logic. Somehow we practice separating almost every thing in the frontend to its own file, but when it comes to CSS it's too much "back-and-forth".
> I don't understand the big problem with switching different files.
Maybe it's really just fundamentally different workflows - I doubt we'll reach consensus here, and that's probably okay.
> What people misses out is CSS should be written in state-based architecture
I agree with you here. That breaks down as soon as you have states that depend on the layout - saying a button should be larger on smaller devices requires adding a style into a media query that lives separate from the button styles, unless you add hundreds of individual media query blocks. Tailwind alleviates that by making "md:" a state prefix just like "hover:".
> if you have a component, which Tailwind creators recommend you should, then you already need to find names for your components
True; I need to name my button component "Button", but I don't have to find a name for the wrapper container of the icon that goes to the right side of buttons that include an icon, which it needs to create a flex context.
How do you change a single CSS property (let's say "border-color") with Tailwind, when the conditions are: "color-scheme: dark", "high-contrast", "focus-visible", "not:disabled", "intent: destructive"? And how do you change 3 such CSS property (border-color, color, background-color) on the same conditions? As far as I can tell, you need to repeat the same condition for each property you need to change. And when you have all these combinations together, which is not uncommon for component libraries to have such different states and combinations, it's just become unreadable mess; just to be able to see which CSS properties the element has without switching files.
I guess to change these 3 property on the same condition, you need to write this TW classes (or create a "variant" in separate config file):
class="dark:contrast-more:focus-visible:enabled:data[intent=destructive]:border-slate-700 dark:contrast-more:focus-visible:enabled:data[intent=destructive]:bg-slate-50 dark:contrast-more:focus-visible:enabled:data[intent=destructive]:text-gray-50"
Or am I missing something that Tailwind makes it as easy as writing these states and combinations in regular CSS (without apply, which TW creators don't recommend using)? If that example is the preferred way of writing TW, and it's only 1 condition combination, I would happily switch back-and-forth files and write regular CSS without that syntactic high-fructose corn syrup.
> I've never seen anyone create a user interface by writing down the full, semantic markup, and then proceed to create CSS for that
Indeed, not in the past 7-8 years. But we used to do it, and the outcome was great - semantic, accessible and machine-readable HTML was the norm. It’s unfortunate that we lost this in the transition to components.
Is that so? From my memory, most people used tables for layouts, or full-out relied on div tags for everything. At some point, HTML5 brought headers and footers and navs and more, and if anything, that made the situation better since.
But if the working groups continue to pretend HTML is for text documents instead of web applications, things will never get more semantic.
> But if the working groups continue to pretend HTML is for text documents instead of web applications, things will never get more semantic.
I mean, HTML is and will always forever be a system to display a few pages of text with some images thrown in. And even for that it sucks big time.
Anything standards committees have been throwing at it over the years are just haphazard hacks to make it into something it's not with no coherent goal in mind.
I started in 2004. Spent the years of 2007-2012 writing semantic, standards-compliant html (microformats, the works), css and js. Even my first years at booking.com still had that as a concern. Unless this was all a fever dream…
“Need to switch back and forth” is a strangely negative way of putting it. Do you “switch back and forth” to a function definition, and is that an argument for procedural code and repetition?
Then your second paragraph is a great point against the need for Tailwind and the long class attributes, as you’re going to encapsulate all of that in a component (and “switch back and forth” to see its styles) anyway.
You've pretty much answered this yourself - a function, just like a component, is a self-contained unit. If you're working within the scope of a function, you don't switch back and forth; but I'm pretty sure you wouldn't want to have to declare the names of any local variables in that function in some kind of global variable table in another file ("let's add a loop here.. switch to vars.file, add someFunction_firstLoop_i as 0... back to the loop, add the variables...").
> The problem is that all these tokens are defined…in JavaScript. A CSS framework. Using JavaScript for its design tokens. In 2021.
And THAT right there is the core problem of such frameworks.
The trinity of frontend technologies, by design, have a clear separation of concerns: HTML structures, CSS styles, JS implements logic.
Of these 3, JS is, by necessity, the most powerful, and the one that can change the other 2 the most. So, as programmers like doing cool things, the temptation is always there to just write some JS that grabs the other 2 and does whatever with them.
This would, in theory, be fine...if there was a universally agreed way to do this. The problem is, there isn't. We still pretend, and can even implement it in a way, where the concerns are actually separated (thanks to serverside rendering we can even do so dynamically), and we have not one method of violating this separation of concerns, but a gazillion ways, spanning the full range of compatibility from "no problemo" to "are you crazy?".
This needs to stop, I say desperately, while being fully consciouss of the fact that it never will, since the genie is already out of the bottle and has been for a long time.
I'd actually love a tool that converts tailwind CSS to regular CSS on save because my biggest issue with CSS is that I constantly have to come up with ids and class names.
HTML itself is beautiful. Show me a better way to express varied words and images with an eye for creative layout and design the way great books play with this content.
Every design system build on top of HTML is just an abstraction that adds layers of complexity whilst reducing the inherent flexibility of HTML. It's much like the years when every SPA framework rebuilt the concept of a back-button and page history, or standard HTML form inputs. All were shittier versions of what the browser provided (even if imperfectly at times).
That's why there is this endless flow of snake oil frameworks like Tailwind and all the others.
People see some fancy demos and think "wow, so cool so easy" and "This is the newest framework, so it must be the best" and go for it.
Then over time, they get caught in a web of problems that the complexity of the framework produces.
Then a few people go for the vitamins route (plain html+css+js) and most go for the next painkiller on the market.