Why Tailwind CSS Won
matt-rickard.com
matt-rickard.com
It's internally inconsistent, so you can't guess what the Tailwind class name is for styling, while you can do this for CSS on the majority of properties. In Tailwind, font weights are just `font-bold` for `font-weight:bold`, while font variants drop the `font-` prefix part, and become `ordinal` instead of `font-variant-numeric:ordinal`. That's not an isolated example, it does the same with text-color versus text-decoration, and text-decoration-color adheres to neither of those systems.
It's quite close to learning an entire new styling language on top of CSS. It may be the case that putting everything into the HTML is more efficient from a productivity point of view, but I don't think Tailwind's specific implementation achieves that.
So why not color-{color}-{shade}?
A plugin is likely available for that, too.
I use PHPStorm a lot; https://www.jetbrains.com/help/phpstorm/tailwind-css.html
Panic's Nova? https://extensions.panic.com/extensions/jasonplatts/jasonpla...
Vim? https://vimawesome.com/plugin/coc-tailwindcss
etc.
That said, it's not needed. It's just a quality-of-life improvement, like most other IDE features. You can write a Tailwind site in Notepad, if you prefer.
I don't, but I've been using Tailwind for a little while. Once you grok the syntax structure it's not that different to writing CSS.
Personally, I think this code looks like utter shit, and I definitely would not wish to maintain this.
<a href="#" class="-mx-3 block rounded-lg px-3 py-2 text-base font-semibold leading-7 text-gray-900 hover:bg-gray-50">Product</a>
<a href="#" class="-mx-3 block rounded-lg px-3 py-2 text-base font-semibold leading-7 text-gray-900 hover:bg-gray-50">Features</a>
<a href="#" class="-mx-3 block rounded-lg px-3 py-2 text-base font-semibold leading-7 text-gray-900 hover:bg-gray-50">Marketplace</a>
<a href="#" class="-mx-3 block rounded-lg px-3 py-2 text-base font-semibold leading-7 text-gray-900 hover:bg-gray-50">Company</a>
This isn't a pathological example constructed to undermine Tailwind either — this code is copied and pasted from their website.If we see more articles to that effect and this is not an outlier, it means the Tailwind cult is in its "red dwarf" stage, where the community becomes smaller, but denser and more convinced than ever that the entire world is a copy of their small bubble.
That's good, it means in a few years Tailwind will be considered a dead tech. Tech bubbles are so weird. It's like the tulip mania or the NFT craze. It all makes sense when you're in the bubble. While those outside are looking at it, and seeing what is clearly mass psychosis.
And that’s good because of what, beyond your own personal preference as to your Framework Of Choice?
Tailwind projects read like the wall writings of a mad man, who is convinced they've discovered the secret of the Universe. And that secret is compiling absurdly large, GIGANTIC lists of CSS rules, trying to reinvent the concept of a "syntax" within the constraints of an identifier name, then copy-pasting them inline all over your HTML code, with great redundancy and repetition, obscuring the actual DOM, and then treeshaking the gigantic class lists, so your browser doesn't immediately crash while opening a basic homepage.
It's good because projects like Tailwind are built on marketing and emotion, they rely on ignorance and the web design equivalent of a "get rich quick" scheme that promises great results with no effort or skill, they seek to be viral, and when they succeed, engineering arguments about the merits of good design, or even basic logic cease to have any effect, and then these projects realign the rest of the community, so you see other projects "built on Tailwind", often not even for any reason other than it's cool to be built on Tailwind.
So as the bubble grows, you start also seeing jobs requiring "10 years of Tailwind experience" more and more often, the projects you rely on are starting to switch to Tailwind, and now you have to use Tailwind, like it or not, because everything is glued to Tailwind. If the bubble keeps growing, then we also see a myriad of "like Tailwind but for JavaScript", "like Tailwind, but for SQL", "like Tailwind, but for web services" and there's no end to how far it can go, because bubbles, driven by the aligned wide-eyed stupidity of millions of delusional people can grow to wrap around the entire industry, before they pop.
And when they pop, the damage and loss of value and productivity is immense. Having to redo big parts of an ecosystem, so you can scrub away all the millions icky sticky pieces of Tailwind mania off things, that is splattered on everything, and the smell is completely unbearable.
So. When the bubble of BS stops growing, and starts shrinking, without massive damage: it's good.
It's good. ^_O
In my opinion, tailwind is gaining some popularity because some people find it faster and easier to use than writing traditional CSS files.
I realise it also has some downsides, and seeing all those class names in the html is particularly ugly, but if the people using it got their project out faster, then surely there is a place for it?
One of the tests of intelligence is can you defer immediate gratification, so you can reap higher rewards in time that compound themselves, or you lack impulse control and therefore you essentially have the model behavior of a house fly.
This incessant focus on "here, now, me" that I see glorified, which doesn't consider at all anything outside a point in time and space that demands the impulse to be immediately satisfied... is not a good direction for tech, or for society at all. It's like choosing porn over a family.
Obviously, I'm describing a broader problem here, not just some CSS tool, but Tailwind and many of the "frameworks" we see pushed in the industry do also embody this philosophy, quite clearly. Many things do these days. Ship faster, do less, faster, faster, faster. To what end? Are your projects so worthless, that you need to ship them today and then leave hell to yourself and others few months down the line? Not to mention that all the claims Tailwind is "faster", somehow, are written in weasel language to hide the fact Tailwind adds tangible, often significant lag and load to people's devices when they use your site. Does this matter?
Of course, a fancy experiment is all good. You won't see me writing long posts about how Brainfuck is the end of humanity. But Tailwind has a good size community that actually believes their approach is superior, they're on a mission from God, and it's become viral, dragging in more and more people in, and influencing other projects into the same stupidity. What else does it mean to write a post called "Why Tailwind won". Won what? Was there a war going on? Won over what? Bootstrap? Bootstrap is a framework. Won over CSS? It runs on CSS, it's not an "alternative to" CSS, although it sure makes it impossible to use most of the benefits of CSS in a sane way. Yay, what a win.
If Brainfuck was totally serious, and you saw your company is starting to write critical projects in Brainfuck, wouldn't that give you a serious pause?
I do agree with you on the headline though, of course tailwind hasn't won anything!
If you have a very simple page this doesn't matter, but as your site/business grows, it does.
Second, Tailwind obviously promotes a ton of repetition in the same way that using presentational attributes from the 90s and style="" does. This not only adds, again, burden to the CSS engine and DOM, but this "ease of copy pasting" that the author boasts about in the linked blog means you can easily end up with tons of subtle or not so subtle inconsistencies in your site's code and components, UI.
Copy pasting is easy. But there's a reason why we define classes, functions, modules, and reuse them, instead of copy-pasting our code everywhere. Copy pasting is a strategy for a quick start and a very short journey as you paste more and more variations of what you're trying to do around your site. Now change them all consistently. Oh shit, I guess... find/replace + regex? This works sometimes, but it's a deeply unserious approach to change management in an application/site at scale, and means your velocity and quality both will suffer.
I'm aware of the way to define custom classes as sort of "components" in Tailwind, but at this point... you're literally using Tailwind as you would CSS, but with a ton of indirection, gibberish, and very very unclear precedence/specificity rules.
You will also get many people complaining about compilation speed for larger sites. A problem that is quite bizarre to have for styling with a language that doesn't require compilation when you use it in a sane way (and SASS etc. are extremely fast and don't have this problem, there's even a Rust SASS parser I believe, that's even faster).
Tailwind also severely restricts your precision and expression. I probably don't have to explain the limitations of inline styles when those styles have to change from user interaction, or for different devices, and container size and so on. Tailwind makes all this extremely bizarre, if it addresses it at all. In "plain" CSS (and other more reasonable tools like SASS), it's trivial.
I haven't used Tailwind, or any other CSS framework, because I have never understood why I would want to, having attended a talk about a similar system back in the day where styles were turned into weirdly specific CSS classes, as if they were trying to reinvent font tags. The way you've described it is pretty much what I would expect from such a thing.
And yet it's oddly familiar, because all of the 'MVC' frameworks that I've been forced to use and hated[1] seemed to come from the same design philosophy: Throw a bunch of shit code together, then build a cult around it so that people use it whether it makes any sense or not. Laravel's a great example of this because if you search the web for it you'll mostly get results saying that it's "elegant" and "for web artisans", but none of them can explain why it's better than...not using it. They even have some class in there called "Illuminate", which is ironically not very illuminating w.r.t. what the heck it is or does. As if writing code that actually makes any damn sense is everyone's biggest fear and the solution is to acquire a magic wand from one of the Framework Gods that does away with pesky old logic and predictability.
"What do you want to do, write everything from scratch?", your coworkers will say, as if we were making computer programs by banging rocks together before Laravel/Rails/Spring/Django/etc came along, and give you a blank stare if you try to explain that writing regular old well-factored OO/functional code is a thing you can do and that slathering culty frameworky paste all over everything doesn't make life any better or your programs any faster, even if said goo has "good documentation", by which they mean lots of activity on Stack Overflow because nobody can figure out how they're supposed to do anything without copy-pasting from some example that mysteriously worked for somebody one time.
[1] I don't remember much about the ones I didn't hate, because they did very little and stayed out of the way.
But describing this as merely "both sides have equal merit" is really crude. Because more often than not, one side tends to be closer to the truth. Maybe Tailwind has some neat ideas. In fact I'm sure it has some neat ideas. Placed carefully somewhere in the calm eye, the dead center of this tornado of bullshit that is Tailwind overall. But then again, we can't ignore the tornado of bullshit.
I usually build websites to solve a problem, or to try out a business idea. The structure of the HTML and whether I am using a web framework are not important to me.
The main thing is, can I get this finished and looking great in a few days.
But then... I try to imagine how Tailwind allows you to style your site in a few days, but it'd take you, the same person, what... weeks, to style it with CSS? It's so ridiculous it's making me laugh out loud just imagining this somehow. As if CSS is this thing for rocket engineers that is way beyond a common man's grasp?
Seriously, how LOW is the bar, I don't get it? When is something as easy and basic as CSS... just easy enough? "property: value;" Or have you never given CSS a chance, and you were heavily gaslit by Tailwind marketing into thinking CSS is a scary monster and here comes the savior Tailwind? I can accept the latter, but this is also the reason why I find these fad frameworks such a harmful phenomenon. But I can't fathom the former.
All cascading styles are removed, so if you pull in a component you have already built on your site, it will be styled identically in the new location too.
You're on hacker news, which is pretty heavily focused on startups. Startups usually have a limited runway, wherein if they don't deliver they cease to exist. That seems like a pretty reason to ship faster?
Comparing "choose a framework that saves developer time and energy" to "choose porn over your family" seems a bit much.
My dear pot, you should meet my friend Kettle.
Really, this is a lot of text that sums up your personal preferences as to why you don't like Tailwind. Nothing concretely objective here. And, by the way, I agree with some of it! But you're also ignoring Tailwind is used by massive, engineer-first companies (such as Stripe), and the engineers in question actually like working with Tailwind. This idea that people who use Tailwind hate it is obvious nonsense, and it's always a significant tell that someone hasn't really produced anything with it when they start claiming that about others.
I think my critique was sufficiently detailed, but if you like Tailwind's approach you may enjoy it coming to your language of choice, where you can code by writing very long variable names in a highly specific way, which are then read by reflection and interpreted as code.
No need for Tailwind; in enterprisey Java land we already have Hibernate and Spring Boot for those who like long, magical method names. And if you want an extra layer of obfuscation, drop Lombok in there.
Ah, just like React!
If React dies I'll be sad. While most of React is BS, the "ReactDOM" component, the Virtual DOM model that is applied to the real DOM by "delta" diff, is a solid concept that deserved to live. Unfortunately we do tend to throw out the baby with the bathwater, when we decide something is uncool.
We're a very stupid species.
- Javascript evolved, so you no longer need some crazy long template to support simple sentence like class extends - TypesScript appears, and also benefit the js eco system with d.ts files. And it even become coffeescript's short coming - Editor evolved, the editing experience is far better than before. The time typing long keywords can mostly compensated by auto-complete
But what will be the pain point that react can't resolve, other framework can and out weight any other benefits? I don't see that as for now
Are there any CSS frameworks that are the opposite of this?
The alternative is not sanity, but simply unmaintainable madness.
1. It's works extremely well with the current component-focused UI frameworks (react, svelte, etc). Subsequently, the verboseness that is often a complaint isn't an issue at all, but a feature.
2. Does everything out of the box, and very easy to customize.
3. And, most importantly, it allows for easy art direction. Does one button need to be a slightly different size or color for this one specific element? Chuck an extra modular class on it. No need to build a complex cascasding or edge cases. (Shout out to `tailwind-merge`)
Point 3 for me speeds up production work immensely. Also, not being in JS has shrunk bundle sizes by a small amount, which is always welcome in this era.
2. Vanilla CSS too.
3. For designers with individual styling of components Tailwind is great, but not for app where elements have the same style or developed at component level.
CSS doesn't give the best toolset in order to do styling and organize styling. The locality of HTML structure and styling makes things far easier to work with.
I would also throw in that front end coding feels far more fickle and arbitrary. Tailwind allows me to define a set of rules and then apply them directly. It ends up being more maintainable when used in conjunction with component abstractions.
I mean, just look at it. You have to write all this crap in css just to achieve `class="my-4 mb-sm-5 mb-lg-6"`:
:root {
--breakpoint-sm: 500px;
--breakpoint-lg: 800px;
}
.foo {
padding: 1rem 0;
}
@media (min-width: var(--breakpoint-sm)) {
.foo {
padding-bottom: 1.5rem;
}
}
@media (min-width: var(--breakpoint-lg)) {
.foo {
padding-bottom: 2rem;
}
}I've seen Perl code that was more readable than this.
I don't know Tailwind but with Bootstrap it would be m = margin, y = y axis, b = bottom, sm/lg = screen size, 4/5/6 = size
Personally I think that's way better than putting padding & margin in your own css classes.
It actually cuts down a lot on the custom css you need to write and also helps having a uniform design.
import type { Config } from 'tailwindcss'
export default {
content: [],
theme: {
extend: {},
},
plugins: [],
} satisfies Config
(not arguing for or against TW here) 'sm': '640px',
// => @media (min-width: 640px) { ... }
'md': '768px',
// => @media (min-width: 768px) { ... }
'lg': '1024px',
// => @media (min-width: 1024px) { ... }
'xl': '1280px',
// => @media (min-width: 1280px) { ... }
'2xl': '1536px',
// => @media (min-width: 1536px) { ... }
That's from the docs. https://tailwindcss.com/docs/screensIf you don't want those specific breakpoints in your project, you can override the defaults in `tailwind.config.js`.
This is exactly the problem. Humans write code for humans, not for tailwind specialists and bots. It should be clear and easy to read unless there is a valid reason for weird code (optimisations, hacks that don't work otherwise etc). Tailwind introduces yet another convention where it is absolutely pointless to do so.
.foo {
padding: 1rem 0;
@media (min-width: 500px) { padding-bottom: 1.5rem; }
@media (min-width: 800px) { padding-bottom: 2rem; }
}There are some properties of CSS that are more static across screen sizes. Colors, borders, backgrounds, font-size (debatable!), animations, and maybe even some high level layouts (12 column grid, etc).
The rest of CSS is minute positioning via padding, margins, and widths. Often you need to customize those details to use slightly different values dependent on context within the application itself. This is where utility classes shine.
As for the media queries being hard/tiresome to write, don't we have IDE auto-completion for this exact purpose?
Being able to think "Hmmm, I want a rounded button, with a border and a blue background" and just typing class="rounded border border-blue-600 bg-blue-500" and it's done.
With lots of UI being components now, it doesn't really matter that it is verbose - I actually find that helpful. And even if you want to have a class that you use all over the place, just use @apply and create a custom class that you can use anywhere.
One place it can be hard to use, is if you have a specific design system - then yea at that point you either work with Tailwind and modify the config to match, or you just go with standard CSS - but at that point it probably makes sense.
I rarely think this. It's usually “I want a button that looks like all other buttons on my site”. Vanilla CSS is great for that.
So I still have to componentize my presentation layers to do tailwind "correctly", but instead of writing CSS in readable multiline chunks in a language every developer already knows, I need to use this cryptic one liner in any order that literally nobody can read?
What in the hell is wrong with this industry? Sometimes clever ideas aren't all that clever. Sometimes they're just dumb.
Classes are a tool for selecting markup to style. Sure, you can create a class for every single CSS rule you write, but just because you can doesn't mean you should.
button {
/* your styles here */
}
to set a precedent for all your future buttons.I'm not a frontend developer and don't really know much about these frameworks, but how is this different from just using style="actual css"? This just feels like inline styles reinvented for whatever reason.
And finally, when you did run into the IE selector limit, you could just split the style sheet in two (fairly trivial if you were using Sass), because the selector limit was per stylesheet.
media queries and pseudo-elements are impossible, just off the top of my head.
Tailwind's patterns for device responsiveness are actually the most intuitive I've tried
Also, though it’s lower-level than something like bootstrap, it does have a design system. Bootstrap is like building a model from a kit, plain css is like building a model from scratch, and tailwindcss is like building a model from lego.
style="border-radius: 5px; border: 1px solid #2563eb; background-color: #3b82f6"
Personal choice obviously, but I work with frameworks and components if I'm doing frontend stuff, so having things as a single name for something that is consistent across everywhere I use it makes it easier for me.
It's not for everyone, and that's cool.
If I can be blunt: I find this "argument" to be lazy as **. Sorry but "context switching" is just a fancy name for "having two files opened at the same time", which shouldn't be a problem, no?
PS: And almost all the other stated advantages of this approach seem to be as low value as this one considering the implied costs.
If you haven't experienced costly context switching working on FE then consider yourself fortunate.
It also is the kind of help/solution that should be implemented first, before any librairies or frameworks are added.
There's a lot that is easy and shouldn't be a problem when you get to define the scope and technologies and shared conventions used.
I may be wrong, though. Don't hesitate to correct me if that's the case.
But regarding one of your specifics, for example you said "the kind of help/solution that should be implemented first" before frameworks are added.
On the teams you've been on, was it easy for a developer (especially a junior) to say "Hey, we should really be implementing X, and we should have done it before I joined the team, can we restructure at this point?"
And, yes, I've had problems in the past with hunting rules as you say. But it's been a good long while since it happened.
These solutions to an old "problem" are lighter, simpler and easier to maintain in the long run.
If you're curious, I'll be pleased to give you more concrete examples!
As someone who just wants to hack together a responsive blog that looks nice, the things that are now “simpler and easier in the long run” have not been easy or obvious to come by when looking for resources, and while I’d love a deep knowledge of CSS, the investment in time doesn’t make sense given my use case. This is why I gravitated to Tailwind - learn the conventions of the utility classes (only took a few minutes) and the rest mostly just works.
I’d love something like http://vanilla-js.com/ but for modern CSS. Something that paints a crystal clear picture about what can be done, and how to do it without bringing in $framework.
And, because you are absolutely right, I'm working right now on something like what you propose.
The only way to convince people that CSS is a better (as in lighter, simpler, more efficient, etc.) solution than a framework like this, is to show and prove that it is. Arguments can only go so far...
So, as the saying goes, I'll be putting my money where my mouth is. Hehe.
Awesome of you to start a project like this.
If you are ok with sharing an email address or a website, I'll be sure to give you a heads up when the site is up and running.
Thank you for the kind and useful offer!
You mean you have to think about how the data you're styling looks while actually looking at the data you're styling? Sounds terrible. /s
To me, context switching is about changing what I’m currently looking at on the screen and going somewhere else to define something in some other context: a different source file, a different system, a config file, etc.
If you’re continually leaving the context of the HTML that will render your data in order to manipulate that data, that sounds like a different problem that can easily be solved by using mock data or by hooking up to a real data source. This is true regardless of CSS approach.
1) style encapsulation,
2) colocated presentation/content/behaviour and
3) a more minimalist mindset/habits when building UIs (e.g. relying on simpler styling hierarchies, native DOM elements, semantic HTML instead of div soup).
[*] not all, it doesn't mean that it doesn't make "senior" (whatever that means) devs more productive or that if you're using Tailwind you'll lose your 10x dev of the month badge. But, CSS is a misunderstood yet very flexible language which means it can be used or abused in a huge variety of ways.
Colocation of presentation? Why do you even need that? Presentation is abstracted into CSS by design.
Having presentation decoupled allows you to abstract around visual elements on a page at their instead of having to sufficiently wrap everything in divs classes just to the right level to make the CSs classes work.
HTML describes layout, not just content.
Your overall structure is going to be vastly different whether you use flex or grid. And if you don’t want to write overly clever CSS you’re wrapping your dt/dd pairs in divs or you put dummy elements into your sections to control where the anchor links scroll to etc. And don’t get me started on non-hierarchical layout relationships.
HTML is not flexible enough and CSS is not expressive enough for this theoretical separation to hold in practice. You would need a translation layer between pure content and layout for this to be true (like XSLT).
What I suggested was decoupling presentation (actual CSS rules) from structure, the blocks of html.
What I'm discussing here is if CSS rules should be inlined in html, whether through tailwind pseudo css or style tags the result is the same.
Further caveat, the article mentions that switching to a CSS file is a context switch. Put it in a style tags next to your html for all I care, colocation is great as a general rule, inlining CSS in html style attributes is not.
This is settled thinking at this point: inlining CSS results in short term benefits to productivity at the cost of long term costs due to brittle presentation that is expensive to change.
And given how low the cost of extracting reusable css classes is these days, I don't think tailwind will ever win.
The structure of your HTML is as integral a part of the presentation as your CSS is.
The key point here is that CSS exists precisely because html markup isn't enough on its own to style itself. If it was, CSS wouldn't exist.
The idea that something like tailwind can come in with a bunch of fine grained CSS classes and solve this inate complexity is laughable at best and wildly unprofessional at worst.
It just shows a complete lack of understanding about what html is and isn't and why CSS even exists in the first place.
Fwiw, I get it. Tailwind is a neat shorthand script you can use to pump out trash you'll never look at again. For the rest of us doing actual work on things that we'll need to modify 6 months from now I'd much prefer something readable that I can actually have a hope of modifying even if a teammate wrote the thing.
Umm... How? You have to know CSS and be quite proficient to understand how to map it to Tailwind. I don't understand this claim at all.
I believe I'm convinced that if an abstraction is leaky then it's garbage.
For instance, if I really needed to know say, jvm assembler to code Java then Java would be garbage as an abstraction layer because it would simply be creating problems where they need not be.
Java however is clean, which makes it useful. I don't need to know the next level down. C is clean. JavaScript is. PHP is.
Tailwind is not. Many frameworks are not. They promise benefits but deliver complexity and programmers get invested into the system and then can't see the reality because it's a classic cult effect of giving emotional salience to a lie.
Eventually it collapses and a new one is formed.
And for some unknown reason, this. Shit. Does. Not. Stop.
It's really exhausting. Been programming nearly 30 years. So sick of it.
It would be like if I did say medicine and every 3 months or so the medical community started tripping over itself by believing in the latest weird quack with orgone energies and magnets and started writing prescriptions to their patients about chakras or astrology and then being shocked, like actually genuinely surprised when it all collapses.
Why do people run around like a bunch of frenetic teenagers to manufactured hype cycles in programming? Can we please fucking stop. Honestly.
It hadn't occurred to me that people might be learning Tailwind as if it's a replacement for having to learn or understand CSS. If you treat it that way then you're bound to have a bad time, much like people who treat git as a series of commands to be memorised without any understanding of git's underlying data model.
I'll also admit that I've only ever used Tailwind on small-to-medium sized solo projects, so I don't know how it would hold up on a big team. But then the CSS has been an agonising, unmaintainable mess on every big collaborative project I've ever worked on even without Tailwind, so what is there to lose?
That's the other thing, tools are a really poor shortcut to competency and in practice just reflect the same level of mastery that caused the initial headache except with a different set of tools.
This isn't pure. Some things are genuinely less insane than others.
As an analogy, higher quality brushes, paint and canvases will make you a better painter but buying new brushes isn't going to be part of becoming the next Monet. Consumption isn't going to get you there.
The real competency as you point out, come at higher level coherency, which frankly takes about 5-10 years to get any good at. It's a cognitive mastery that's mostly independent of tools.
People want to seek out better tools as a proxy for the hard earned talent. It might get you further but at some point, knowing what you're doing is the only way to go.
It sucks. It's hard. It's frustrating. It's always changing and it's also unavoidable.
I grok flexboxes and responsive design through Tailwind more than I ever did in those years.
I could certainly learn more pure CSS but there's no need at this point. I am happy and productive in my ignorance.
I recently started a writing project, and found myself unhappy with choosing a standard blog theme, and decided to build my own.
For this purpose, Tailwind has been incredible. I don’t have plans to become a front end dev, and investing significant time in improving my CSS skills is not a good use of time for what will be a fairly small project. It gives me more flexibility than frameworks like Bootstrap while still offering a lot of the productivity benefits. It lets me explore concepts and ideas that I otherwise wouldn’t have the skills to play around with.
This thread reads like most $language/$framework/$os holy wars. There is an awful lot of hatred over a perceived lack of “purity”, or because of the perceived superiority of other approaches. Like most of these technology debates, the extreme binary positions really miss the value that can be found in the middle. Tailwind has been great for getting ideas out of my head to see how they look, and for staying focused on the content that I’m planning to write instead of getting stuck learning about browser edge cases.
If I start focusing more of my time on building UIs, I’ll invest more deeply in CSS.
I’m also fairly convinced that many of the negative comments filled with disgust at the resulting syntax have never tried it. After about 10 minutes, the conventions start to become obvious, and I can write visual elements mostly at the speed of thought. This is really quite enjoyable.
I’m also not suggesting it’s the right tool for every job. But the lack of nuance in much of the discussion here is pretty disappointing for the HN community.
I personally feel that the future of the (useful) web depends on more people choosing to do their own thing. Tools that lower the barrier to entry and simplify content creation will always be important.
* It removes the burden of having to come up with class names, and the mental overhead of deciding whether to create a new class or rely on the C in CSS. When writing plain vanilla CSS there's always a sense of friction and a need for careful planning (often resulting in me procrastinating it). That whole process is eliminated with Tailwind and I can just start styling the element immediately.
* The fact that you can see immediately how an element is styled. No hidden, detached or indirect styling whatsoever.
For styles that are reused a lot I just create small & composable components (which are also defined by the Tailwind classes so they match distances & colors). But there are typically just a handful of these in a project.
It's as modern as the style parameter is, and it's as reusable as a moving a dirt pile from one corner to the next.
You're not learning anything valuable by learning Tailwind. Learn CSS, that will stick with you for the next 20 years.
It amuses me when a library is implemented 'with tailwind', which means it's totally useless to the people _not using tailwind_, and excruciating to clean up.
Go ahead, downvote me to hell, I'll see you in 5 years.
Tailwind maps onto CSS in a very straightforward way. I think you'd have to go out of your way to "learn Tailwind" without also improving your knowledge of CSS.
I think I understand tailwind, but like the parent poster I'm really not a fan, because while CSS can be a footgun, it can also be quite clean when you use a sane DOM structure, CSS variables, and well thought out CSS selectors.
i’ve yet to witness a project without “!important” scattered throughout the codebase.
Simplicity is a skill and it's hard to do. There's a reason most people are not minimalists despite the almost universal western desire to "have less stuff".
I've yet to see a single project that doesn't fail on all three.
Truth is I've been spoiled on that front because I had the luck to work for many year in a company where the CTO was a very talented dude who lived and breathed HTML/CSS since the mid-2000's, and who was quite thoughtful about that kind of stuff, so I had a first-hand experience of a good codebase, mostly by avoiding external dependencies, using the standard browser behavior, and frequently consulting the MDN.
This is why it's a bit disheartening to see so many front-end framework working against the plateform, even even marketing against it, while CSS and browser tooling his so much more enjoyable and powerful than before.
Technology that makes it easier to make bad decisions than good decisions is not a good technology.
> This is why it's a bit disheartening to see so many front-end framework working against the plateform, even even marketing against it
None of the frameworks I know of do that.
I believe it's mostly due to the fact that CSS, just like SQL, is one of those technology approachable enough to fiddle with it and get somewhat far, while not really learning it, and thus overlooking the fundamentals.
> None of the frameworks I know of do that.
I would squarely put into this category all the CSS-in-JS frameworks, such as 'styled components'. Also everything that markets the 'cascading' part of CSS as being a mistake.
Also, all the frameworks that compiles CSS without generating the CSS sourcemaps, making the debugging experience way less efficient since all the applied CSS rules shows under '<style>' (eg: 'styled-components' again, who discarded it as being 'cosmetic' in the related Github issue).
In practice, they don't end up "quite clean" outside small personal projects.
This fall apart pretty quickly as soon as more developers join the project. Keeping consistency between multiple team members is hard without a reference point, which is what a framework like Tailwind provides.
Tailwind creates "stylesets", and is absolutely powerless to apply them. Quite like WYSIWYG text editors. So, yeah, anybody claiming you are learning CSS by using it doesn't really know CSS. But I disagree, that kind of thing can be useful on certain contexts.
1. You need to know CSS to use Tailwind
2. I learned and understood quite a few of things I rarely use thanks to Tailwind's amazing docs. Docs that are non-existent for CSS
3. I'm reasonably good with CSS, but I could never come up with a consistent and minimal design system that Tailwind offers
That said, to things everyone should read to up their CSS game is Every Layout https://every-layout.dev/ and Inclusive Components https://book.inclusive-components.design/
This argument boils down to: “But you don’t need Tailwind for that. You can do more work for a (almost certainly) worse result with a designsystem.css!” Sure you can! Why?
If you really want to, you can even use Tailwind's naming for you language file. The thing is, you add complexity to do a job that could be done in the same way without adding complexity and dependencies.
Shouldn't we try to justify added complexity through added value?
Because most frontend engineers cannot make something as visually appealing as Tailwind’s defaults and most designers cannot make frontend abstractions as ergonomic as Tailwind’s.
Now it seems like you’re suggesting just reimplementing Tailwind? Or yes you can have one of your FE engineers and one designer try to dream up your own Tailwind but again: why? Now you’re consuming two people for something that can be achieved by literally zero people and “yarn add tailwind.”
It is not at all my objective to “reduce complexity” that sits behind good abstractions. My goal is to ship product and to put as much complexity as possible behind good abstractions and ideally out of my team’s maintenance burden and Tailwind helps achieve all of those.
Sure, if Tailwind provided literally zero value I would say you shouldn’t add it to the codebase. But it provides a huge amount of time-value (the best kind!) in my experience, so “there’s a package from the internet” is hardly a consideration whatsoever.
Side benefits include that there is then no need to update any dependencies or library, no need to run a JIT server, no need for a new syntax, no need to wait for implementation of new CSS features, better performance possibilities, etc.
Or are you saying take their design system and use your own syntax for it (so it’s less complete than TW, less well-documented, and less transferable to/from the vast resources of the internet centered around TW)?
"blue-500" becomes --blue-500. That's it.
This is a far cry from using Tailwind as a whole while keeping the good-looking aesthetics.
Of course it's not "it".
Now in every class that needs it, you also need to add
{
... other styles...
background-color: var(--blue-500);
}
And then you need to apply that classAs for the class, it's the name of the component, the same name you give to the component file. Does it really add that much work?
Correct me if I'm wrong but as I see it, that's literally a couple of seconds of "work".
Or just use the extremely complete, well-considered, well-defaulted, well-documented, well-supported, always-improving set of classes that took you zero hours of initial setup and will cost you zero hours of maintenance outside of your own use/application until the end of time. And it has a name so when a new engineer joins your team, you can say "we use Tailwind, go to tailwindcss.com" and they are fully read into your setup in about 15 seconds.
And the IDE will help you autocomplete it all. The same is true for all the other properties you enumerated. If it's a Tailwind design token, it can be a pure CSS design token. No "whack-a-mole" needed here.
Still, you're right about having documentation. And there has been a loooot of these kinds of doc (BEM, SMACSS, ITCSS, etc.) in the last 15 years. Nonetheless, a more modern-oriented one is indeed needed. And that's why I'm working on something like this.
As for the "15 seconds", I mean, really? If so, I beg to disagree. There is a lot to take in. And that is why numerous colleagues still have to open the Tailwind docs to know how to write a class that's not 1:1 CSS.
And lucky you if you haven't had any update and dependency issues in the medium to long term. But I know we had.
> Or just use the extremely complete, well-considered, well-defaulted, well-documented, well-supported, always-improving set "of CSS features".
The sentence above is every bit as true as yours. Add a beautiful design language and you are in business.
not 20 minutes, more. Plus all the boilerplate around @media rules
> no need to wait for implementation of new CSS features
What CSS features are you waiting for with Tailwind?
> better performance possibilities
It's very hard to beat Tailwind's performance since it's a fixed set of css classes (and a very small set in production, since it only includes classes you actually use".
Any IDE can autocomplete 90% of any media query. And, on a sidenote, I was only talking about using Tailwind's default aesthetics in pure CSS, here. That's what the 20 minutes refers to. And I think it was a conservative estimate.
As for features, it took months before grid was included in Tailwind. New powerful and useful selectors aren't there. It took years for Tailwind to support "group hovers". And I can give even more examples if you're still not convinced. Or you can have a look at the changelog.
As for performance, can Tailwind split its compiled CSS so that only rules used in the displayed components are loaded? And that's not even considering the weight difference between the "tailwinded" HTML and the one needed to support pure CSS. These things matter if performance is a goal (as it should be).
If I'm missing something, go ahead and tell me, I'll be reading with great interest!
And, as I'm sure you know, milliseconds are important in our craft. You can easily shave or add hundreds of milliseconds with HTML or CSS.
And to be honest, I find your general line of inquiry here to be quite agressive and dismissive. I think, respectfully, a little more good faith could further our understanding of each other.
Outside of consumer apps I am struggling to imagine a case where the HTML/CSS perf delta would be more important to capture than faster development time. I suppose part of why that doesn't seem like a good faith question is because you don't believe Tailwind dev time to be faster, so the tradeoff that I'm trying to evaluate is totally inane.
As for the case in point, in fact, I think CSS can be as fast if not faster. But that's totally for me to prove. Hehe.
That's why I'm working on a set of simple rules for efficient styling with CSS. A website with documentation, examples and tools is in the works. If you're interested, I can give you a heads up when it's online.
Feedback from Tailwind users is important and would absolutely be welcomed!
PS: thank you for the explanation.
:root {
--gap-default: 2rem;
--gap-large: 4rem;
... 30-40 more vars ...
}
.component1 {
margin: var(--gap-default);
padding: 0 var(--gap-large);
... more styles like this ...
}
@media (min-width: 640px) {
.component1 {
padding: 0 var(--gap-default);
}
}
@media (min-width: 768px) {
.component1 {
... other overrides
}
}
/* potentially repeat for other breakpoints ...*/
/* repeat for all components */
/* repeat for some internals of some components */
There's a also a good (if contrived) example directly at Tailwind: https://tailwindcss.com/docs/utility-first> As for features, it took months before grid was included in Tailwind. New powerful and useful selectors aren't there.
No one stops you from using whatever CSS you need alongside with Tailwind. I do that for the excellent layout breakout I found here: https://ryanmulligan.dev/blog/layout-breakouts/
Can't see how this makes Tailwind "ant-CSS".
> As for performance, can Tailwind split its compiled CSS so that only rules used in the displayed components are loaded?
Tradeoffs.
Most existing solutions can't even detect duplicated CSS. So if your existing component already has `width: var(--some-var)`, and you load a different component with the same style... You will still load that style hidden in a different (often auto-generated unique) class name.
Meanwhile with Tailwind has a fixed number of classes that apply to all components equally.
So, if you have a complex app with multiple component variations, of course you'll need to split your CSS and only load relevant CSS for displayed components. Because your CSS grows with the amount of variations, and each of those variations becomes its own unique class.
For Tailwind though that growth slows almost immediately because... it's just a fixed set of classes.
Here are my thoughts:
In your code example, all that is in :root should be used from project to project. As it is Tailwind. Only values should change. Again, same as Tailwind. So I don't really see a problem.
For .component1, you would do the same in Tailwind albeit with fewer characters but as I said, your IDE should pick up the slack here.
mb<tab> --gap<tab> and it is done.
As for your duplicate width problem, it can be solved easily with a linter that prevents styling across files. I'll give you an example if you're interested. At the same time, you would be repeating "width" across components in Tailwind too.
So the duplication still exists, if I understand correctly. Same with the growth of CSS... In Tailwind you grow the HTML instead. Fixed clases or not. I don't see how it is better but, again, maybe I'm missing something.
As for the media queries, same as above: your IDE should pick up the slack.
BUT!
The thing is that by writing modern CSS, you would not need most of these media queries! Do you know "clamp()[1]"? It's magical
And unfortunately not supported in Tailwind at the moment
.component1 { clamp(var(--gap-default), 1vw, var(--gap-large)) }
the above will do what you want without media queries! clamp() solves a loooot of these use cases. Honestly I don't write much media queries anymore and yes, that's great.
And if I may, I think Tailwind here prevents you from thinking about better and simpler solutions like this one. If it ain't included in what you're using, it's normal to not think about it. But really, this is a game changer. And it's been available for certainly three years. That's a lot.
And in the end, I'd say using real CSS with Tailwind kind of defeats the purpose. You end up with different styling methods for different components. I don't think that's good. More like a "hack".
But really, your example above is right on point: by excluding new approaches, Tailwind disincentivize you from using them when they would solve many of your problems elegantly and simply.
[1] https://developer.mozilla.org/en-US/docs/Web/CSS/clamp
edit: the Tailwind example provided is bad CSS. As were the ones given in the first fundamental post by Mr Wathan. These are strawmen. If you're interested, I'll give you an example of good CSS producing the same output.
By the 30th variable I stopped. The fact that I had to write significantly more boilerplate in CSS classes on top of that, helped me stop, too
I thought a person had to be rational to become a developer but oh my, how wrong I was.
This is the paradox of popularity. The theory goes that if you have a large pool of X to select from, then you can select the best of the best, and the quality of your selection will be amazing.
But it's exactly the opposite. Small groups are self-selecting for quality and big groups are self-selecting for quantity. O_O
English, the universal international language. The one we're speaking here, right now. The worst translators in the world are English translators. Everyone feels qualified to speak it and translate it. Finding a good English translator is like looking for a needle in a haystack.
The more "easy languages" and "frameworks" we have, the more "programmers" we also have, and 99.999% of them have the faintest clue what they're doing, but they just keep hitting their keyboard with a hammer, and it compiles and produces interesting results, so they keep doing it.
This is also why social networks have an amazing set of interactions when they're new, and in an old social network you have hundreds of millions of users, but no one writes anything interesting, anyone barely reads, and it's full of scams, bots, clickbait and garbage.
There's safety in numbers, the saying goes. Not at all. If something is universally popular, and you choose to enter it, get ready for a shitstorm.
P.S.: Tailwind is garbage.
Meanwhile in Tailwind everything is grouped together, can be searched quickly and acts both as quick docs [1] and as quick reference [2].
I personally have become proficient with flexbox by playing with Tailwind classes.
[1] E.g. layouts https://tailwindcss.com/docs/display
[2] E.g. all the justify-content values https://tailwindcss.com/docs/justify-content
ultimately what is cheap and fast wins. the future is someone else's problem.
i think that's a good description for javascript too.
Thank you.
Slash
Ess
Am I more clear now?
The sad part is i don't even feel guilty for assuming, because this area of programming has a well deserved reputation.
Even if this thing doesn't use javascript, can you guarantee the generated CSS doesn't put the browser's layout engine in an infinite loop or something? Especially without knowing CSS, like the OP suggested it's normal?
Nope
the way TW aproximatively works is to collect a set of used class names from your code (e.g. flex, min-h-screen, bg-[url(/img/grid.svg)], absolute, etc.) and produce the CSS for those classes.
For the random 5 classes above it would produce:
.absolute{
position: absolute
}
.flex{
display: flex
}
.min-h-screen{
min-height: 100vh
}
.bg-\[url\(\/img\/grid\.svg\)\]{
background-image: url(/img/grid.svg)
}
By default TW also includes a CSS reset preamble and defines internal variables.Sometimes the generated css contains complex selectors but as far as I know it is not a common occurrence
.space-y-4 > :not([hidden]) ~ :not([hidden]){
--tw-space-y-reverse: 0;
margin-top: calc(1rem * calc(1 - var(--tw-space-y-reverse)));
margin-bottom: calc(1rem * var(--tw-space-y-reverse))
}
In other cases more css variables (custom properties defined in the preamble) are used .-translate-y-1\/2{
--tw-translate-y: -50%;
transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))
}
.shadow-xl{
--tw-shadow: 0 20px 25px -5px rgb(0 0 0 / 0.1), 0 8px 10px -6px rgb(0 0 0 / 0.1);
--tw-shadow-colored: 0 20px 25px -5px var(--tw-shadow-color), 0 8px 10px -6px var(--tw-shadow-color);
box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow)
}
I believe that CSS performance is mostly dominated by size in bytes of the stylesheet, number of properties, complexity of selectors, and frequency of updates. I suspect that TW improves most of these metrics in exchange of bigger html class attributes.Edit for the downvoters who don’t know how it works: there’s zero js being run at runtime, it’s a pure css framework that generates as-minimal-as-possible css files. And it’s not class lookups that cause whatever issues parent comment is talking about.
In that regard it is pretty similar to Sass.
The main effect on performance likely are bigger html documents (which can be optimized) and simpler CSS selectors.
In real world usage I would honestly guess that using simpler css selector (with far fewer propagating updates) is a net performance win.
(It was one of the showstopper for the :has pseudoclass, for a long time nobody knew of a way to implement it efficiently)
You all fight, but nobody says what exactly they develop. A webpage and Tailwind is absolutely fun. An app with reusable complex components, Tailwind is a pain. Themes, dynamic tailwind is a pain, static, tailwind is ok.
There are endless possibilities. The problem is, that some people think you can use Tailwind for everything and then they made simple things unnecessary complicated.
For static webpages (unless it is assembled by a static blog engine or something), I don't particularly enjoy it, because of the repetition.
With components+Tailwind you have as much duplication as you'd have with pure BEM.
All personal experience and opinion, of course.
I remember this being endorsed approached by Tailwind creator.
No complaints.
Let's say things how they are: Tailwind is a small catastrophe from an implementation, performance and maintenance point of views.
It got few things quite well in being a more modern bootstrap, had a stellar marketing and it's color palettes are really well done and leagues above the default material ones.
...that being said...
Tailwind's biggest pro is that it allows people that _don't_ know css that much to style stuff more consistently and easily. But that's where it ends.
Sadly there's a lot of issues when it comes to maintenance. Any small update in tailwind will break your application. !important s are shoved pretty everywhere, they will unavoidably clash, prompt you to override even more styles.
There's yet another complication with tailwind: the moment you want to do something more complex with tailwind or that it clashes with its own styles/rules you're in a bad corner where you need to know bot advanced css AND tailwind.
I know CSS very well and Tailwind is probably the largest productivity boost I’ve encountered since, I don’t know, learning vim? It’s way faster than SASS/SCSS which is itself way faster than raw CSS.
It also yields far more self-contained and more readily composable components than any other styling mechanism.
Your comment doesn’t resonate with my experience at all.
What is the value of reimplementing a bunch of this if it already exists? What's the value of having every developer learn some poorly-documented in-house system when we can use one that's already out there with full documentation, examples, references on StackOverflow, etc?
And to top it off, nothing guarantees your colleagues are actually going to use those instead of creating their own ad hoc “semantic CSS” or whatever their preference is.
If you decide you’re a utility-only frontend, then… there’s a great tool for that!
So now why on earth are you still plugging away at that utils.css?
I've been doing web dev since I was a kid in mid 2000's and I think tailwind is phenomenal in enforcing style, portability, speed, etc. I recently started to writing a single .html file proof of concept for something and it was shocking how poor the experience is of `style="..."` is in comparison, or making up classes as you go.
Tailwind finally throws in the towel on all of that and just brings the full functionality of CSS to inline styles and leaves reusability up to whatever framework and templating you're using on top of HTML/CSS.
When I walk into a project using Tailwind I spend way more time actually working on _the project_ and way less time looking at the browser devtools trying to disentangle and chase down the complex web of interacting styles that are somehow working on the markup. Everything I need to know is already in front of my face directly attached to whatever element it's related to.
It is another thing to learn but it's pretty darn straightforward and well documented. Coming from a solid CSS background it took in the manner of hours before it clicked in my head and I was productive. And that largely translates to whatever project I'm digging in to instead of having to spend a bunch of time learning each project's bespoke styling system.
Tailwind is way less technically elegant than CSS, but the technical elegance of CSS has always seemed more lofty and academic than anything.
If you understand CSS well and you’re using TW, you will ~never have to go chase down some crazy style cascade via the inspector.
No amount of understanding CSS can save you from that in a complex CSS/SCSS codebase, because it’s how CSS is meant to be used.
Maybe I just suck at CSS. I mean, I've been using it for decades, but maybe I'm too stupid to actually understand it. And maybe it's the same story for everyone else I've ever worked with and that's why my experience with it has never lived up to the ideals.
... but if that's the case then at this stage of my career, with vast and varied accomplishments behind me, I think that says more about CSS than about me.
I find tailwind just makes my life easier. Sure, it's not perfect, but I really don't enjoy giving every div and container it's own unique name and hoping none of the names ever clash with my colleagues unique names etc.
Also, I came to realise that websites never strictly follow the same design rules throughout. There are always exceptions. So you are constantly creating new style classes that are slight modifications of others. And keeping this all in your head is not easy.
I know a lot of people disagree and feel like tailwind is a problem, but for me I can just concentrate on making a great site rather than worrying about how a slight change to the styles inside .container might break some obscure part of my website.
Are tons of divs and containers needed? When I find myself needing containers I usually find out I've not been thinking about arrangement very well.
If for example Figma offered first-class support for Tailwind-like utility classes in the form of a modernised "styles" or "composite tokens" feature, then mapping from a design system to Tailwind-based code could be pretty simple.
But right now, it's anything but. In my experience, designers simply aren't aware of the Tailwind structure, and it's hell trying to map their mental model onto Tailwind. Figma is built to design things that map easily to CSS at the attribute level, not the class level.
The biggest pro for Tailwind is that it is exceptionally well designed. Aside from adding one single custom style to the Tailwind configuration, I have not needed to venture outside of the system it provides despite writing many bespoke components.
But i sincerely do not understand the performance one. If anything tailwind approach is mostly really good for performance, as rendering utility class directly on the element is still the fastest, by far, technique.
The only slight call here could be shadow dom scoped but that necessitate declarative shadow dom and create a lot of problem for performance until we get a fetch maps equivalent to import maps.
What have I missed?
1. Tailwind allows you to not learn CSS (not even remotely true)
2. Tailwind is hard to move away from (what?!)
3. Tailwind has performance issues (lol)I'm considering advocating for a move to TW at work. Most of the devs _don't_ know CSS well enough to style stuff consistently and easily. We have very complicated cascades, and sibling style imports, and "semantic" class names.
Sure, maybe the answer is "level up your teams' CSS expertise." But I'm looking for something more pragmatic than that. I don't know if TW is ultimately the right tool I'm looking for, but the underlying ideas it uses are very appealing for this use case.
I have never understood this claim. You need a good understanding of CSS to use Tailwind effectively because it is CSS.
It’s not an alternative technology, it’s essentially just an alternative syntax—one that naturally leads away from footguns that many teams end up battling, like fragile CSS that everyone is scared to change.
You could just as easily define the utility classes yourself every time you need one, it’d just be a lot more work.
You don't need it. Do devs these days even know about Web Components and shadow DOM? You can define per-component styles now with CSS selectors to target any child elements within the component and you can do it in such a way that the styles are contained within the component... And for cases where you want to inherit styles, you can just use the regular light DOM.
All these frameworks are re-inventing the wheel and making it worse.
It's like having a perfectly good car and then attaching a horse at the front to pull it because you don't want to learn how the car works...
I think unless there are massive improvements to the developer experience the best hope for web components is as an implementation detail for a higher-level framework.
For me, I've been bitten and I would pick web components over a fixed framework for a clean sheet project. I don't think many devs have really tried to work with web components or they might get the bug, too!
PS: I wrote an intro series on this topic on Medium[0].
[0] https://medium.com/gitconnected/getting-started-with-web-com...
That said, having taught some introductory web development courses in the past few years, I sense that new devs entering the industry are interested in simpler solutions and not particularly keen to get into React. The React learning curve is much steeper than it once was now that it has so meany features and the benefits are not so clear to someone who is starting from scratch.
I apologize.
I saw a video a few months back featuring a VScode plugin to hide tailwind styles.
If you have to use a plugin to manage your nuclear waste code by hiding most of it something is wrong.
https://marketplace.visualstudio.com/items?itemName=stivo.ta...
In one sense, it was always worse to use Tailwind because if you don't learn "real" CSS you won't be able to fix anything that's broken -- and with CSS, there's always a lot that's broken.
You can't use Tailwind without knowing (quite a lot of) CSS. There's nothing in Tailwind that makes CSS easier or that obfuscates the technical understanding you need to make things with CSS. If you want to make a horizontal flexbox layout knowing "display: flex; flex-direction: row; flex-wrap: wrap;" or "flex flex-row flex-wrap" are functionally identical. You need to know what either the CSS or the Tailwind classes are doing to use them, and there's a one-to-one mapping between them. If you learn one then you know both. It's literally just a shorthand notation, or in a few places the equivalent of a macro.
I don't imagine Tailwind is going to last another 20 years, but I do believe that people will use 'utility first' CSS libraries like it from now on. No one is going back to writing plain CSS unless they have no choice. CSS is becoming increasingly capable, and with that increasing complicated. People choose Tailwind because it affords you all the power of CSS with a somewhat less arcane syntax. Why would anyone stop using that?
I do have a caveat though: I actually think Tailwind is the CSS equivalent of jQuery. In 5 years or so a browser is going to add a Tailwind style notation to its engine, and people will be able to use it without needing an external library. In that sense, yes, Tailwind will die, because browser developers will see the benefit is so significant that they'll adopt it as well.
Today's CSS - if anyone would take the time to actually learn it as they do JavaScript - doesn't need something like Tailwind to make it powerful, scalable and manageable.
I write plain CSS today, which is then scoped to components or bundles of interactivity, and all of those point to major, top-level control sheets that help determine the mode (light/dark/high contrast) and the theme. We tweak small changes up high to effect large platform changes throughout, saving time, energy and headache of the hunt/peck exercise.
I don't understand the statement "no one is going back to writing plain CSS" because plain CSS today _is complex_. It is a beast. But it is still "plain" CSS. Yes, it has evolved, it has grown, and it meets today's modern needs with excellent results.
CSS nesting is coming up soon: https://caniuse.com/css-nesting That will more than likely allow me to migrate any projects I have with Sass still in play, to remove Sass. One more dependency removed. Done.
So there's really no need for Tailwind if you know how to build with modern CSS - with the one caveat that if a project _already_ has Tailwind in it, it is a bear to work with/alongside.
That to me is the biggest con with Tailwind: it gets in your way when you don't need it.
I do similar things with Tailwind, making global changes by updating a config file instead of a base CSS file. It's not hard and it works well. To be honest, it's not something that really comes up very often. I don't see this as a particular advantage of Tailwind or CSS. I care much more about the day-to-day dev experience.
Prior to using Tailwind I spent about 20 years trying every system you can imagine to manage styles across large websites/apps. I still use the skills I learned when Tailwind doesn't cover an edge case I need. It's fine. Before that I spent about 5 years doing the same with tables and font tags (Adobe Pagemill was awesome). Of all the systems I've used, Tailwind is the easiest to keep neat and tidy. Maybe I'm a terrible dev and other people find CSS really easy to manage, but having spent two decades talking about it with other frontend engineers I'm reasonably certain that's not a common skill. Tailwind makes life much easier for most people.
The cascade is where the value of CSS comes from! It’s an incredibly powerful concept.
I use and love the Inverted Triangle CSS (ITCSS) approach and write a fraction of the CSS code I used to.
Having a few utility classes, using variables for project-specific colors, breakpoints, spacing, using fluid typography, grid, and flexbox, make writing well-structured minimal CSS code a pleasure.
https://www.xfive.co/blog/itcss-scalable-maintainable-css-ar...
Tailwind styles cascade just like any other CSS rules. No one is ignoring it. The reason it might appear not to is because Tailwind uses layers (https://developer.mozilla.org/en-US/docs/Web/CSS/@layer). Technically it's a polyfill at the moment, but v4 will use the native @layer syntax.
If anything Tailwind is actually better at using the cascade than most plain CSS approaches.
And if you don’t think it’s reusable then you at least need to bring an argument for why that’s so because the docs, personal anecdote, and the opinion of LOTS of people is completely opposite.
So: - You ARE learning CSS, you’re just putting it where it belongs: on the element it affects - It’s modernity doesn’t matter at all - It’s literally as reusable as raw CSS
I can’t downvote you, but you’re definitely wrong.
So you’re not learning CSS. You’re learning Tailwind specific classnames that expand to non-cascading style rules.
So the cascade still happens, just in a different way.
Can you expand? I haven't used Tailwind, but from looking at the docs, it looks like a short-hand syntax for writing inline styles. Not exactly the same since it can take advantage of media queries and other things that you can't do with inline styles, but close enough conceptually.
Where is the cascade with Tailwind? Perhaps I completely misunderstood how it works, but I would say that it feels like it's purposefully trying kill cascading.
One is CSS style inheritance. So if I do this:
<div class="text-blue-500">
<i>hello</i>
<b>world</b>
<div>
The `text-blue-500` style is going to cascade down to the descendent elements. That's just how CSS works and there's no getting around it.The other usage of the term applies to a style of writing CSS that makes use of this cascade. So something like this:
.card {
color: darkgray;
}
.card .header {
font-size: 20px;
}
I think what people are referring to in this thread is the latter, which is not the cascade, but a particular approach to CSS.Cascading refers to the order stylesheets have priority when loaded by the browser. Going to have to update my definitions for the future. I always thought cascading referred to how specificity worked.
Edit: no wait, specificity is part of cascading, cascading refers to the entire process of determining which style applies, including specificity. Inheritance on the other hand is not part of cascading. My definitions were right, don't need to relearn anything.
[0] https://developer.mozilla.org/en-US/docs/Web/CSS/Cascade
The order in which stylesheets are loaded and it's origin is just part of the cascading algorithm. See the "Cascading order" section https://developer.mozilla.org/en-US/docs/Web/CSS/Cascade#cas...
IMHO the only important application of the cascade is in its original purpose: custom user defined stylesheets (today often via browser extension or adblockers), but you can add proper descriptive attributes to your markup for them.
https://developer.mozilla.org/en-US/docs/Web/CSS/Cascade
https://developer.mozilla.org/en-US/docs/Learn/CSS/Building_...
Custom properties are by default inherited by all descendant nodes (they also interact with the cascade, but it is less relevant) and this can be used with tailwind in a couple of different ways: https://stackoverflow.com/questions/64872861/how-to-use-css-...
All my "hard opinions" aside, I have anecdote that no amount of facts can change—I build things faster, more maintainably, that look BETTER than anything I did before Tailwind. Until those pillars stop being true—Tailwind will have my heart.
The amount of cargo culting going on right now is at an all time high. People do stuff all the time that makes no goddamned sense and is defended by, “well Google is doing it!” You are not Google and you never will be.
In fairness, CSS is such a mishmash of things that it lends itself to cargo-culting.
You can fit the number of people who are exclusively CSS experts in a van and still have room for their luggage. Everybody else is going "that's cool, how do I do that?" and then copy/pasting it.
I mean, hell, it was years before you could reliably vertically center stuff with CSS (that we were doing with table-based layouts since the 90s). And considering the number of wonky layouts I've seen in what should be professionally done mobile Web sites, it's clear that it's hardly a Done Thing.
The nerd in me really likes SCSS, because I can more or less wrap my mind around it, but I get the Tailwind way as well. As a developer, CSS is way down my list of things to know intimately. Whatever I have to do to keep things moving, I'm good with it.
CSS was meant to cascade; it's what the damn 'C' stands for, and if you cannot understand the efficiency of the cascade, at scale, you are most definitely missing the entire point of CSS.
I have personally built ui libraries for boutique firms and enterprise (Apple) firms and guess what we did _not_ use in any of those instances? Tailwind. Because it's an utter toddler to manage and very definitely not efficient in its application.
Styles applied by Tailwind classes cascade. The library just makes it (intentionally) difficult to define a class that will easily collide with others.
If you want to cascade all your styles all the way down, by all means go for it. However, I aim for readable / scalable styles rather than dogmatically "cascading" everything just because it's in the name.
TailwindCSS puts a bottom threshold to the low quality - it guarantees a minimal level, regardless of what the rest of the codebase looks like.
This comes at the cost of general (but limited) messiness and guaranteed lack of maintainability.
I don’t use it but if I was on a team where engineers don’t talk to each other I probably would.
In cases like this I get curious and try to understand: why? I do not do CSS enough to arrive at the verdict about Tailwind, but my best understanding aligns pretty well with TFA. That and the fact that people wanted some framework that is popular and can be easily reused for results that look reasonably well. Bootstrap was it for a while, but Tailwind came and looked more modern.
Taylor Swift - still beats me.
There’s no replacement for understanding the underlying technologies of frameworks, that’s true. Compared to some frameworks, tailwind is only a small layer of abstraction, one that does not obfuscate the underlying tech away. It does not prevent you from learning or using CSS. That’s why it’s so good.
I frequently drop tailwind into projects because I know the shipped code footprint is low and it accelerates design.
Tailwind is a pretty good framework for people who want to practice atomic CSS easily, and it is a bad framework for anyone trying to avoid that pattern.
The pros and cons of atomic CSS can then be argued about elsewhere.
https://hn.algolia.com/?dateRange=all&page=0&prefix=false&qu...
This also covers both scoping issue with css: the usual issues with the single global namespace for classes and the unlimited depth of the descendant selector.
That is even with scoped classes if your app has component nesting as <A id=1><B id=2><A id=3></A></B></A> then a selector like .A_box::hover .A_btn will select the class A_btn both in <A id=1> and <A id=3>.
Tailwind solution is to manually or programmatically apply the relevant style in your template.
The whole idea being that the unit of reuse is not the class name but the templating component.
But this idea that all styling should be done in HTML is antithetical to the whole reason CSS came to be in the first place, IMO. I can see why people like it to an extent, but I just don't really get the arguments that switching files to write CSS is "context switching" that makes things harder. If you need to see both your HTML and CSS at the same time then get a bigger monitor (mostly kidding).
I just still see that well crafted HTML and CSS work together, make sense, and especially with all the new tools available in CSS, just isn't that hard to get right. Well structured HTML is the biggest pain point I see for those that struggle against CSS. Learn that, the cascade, learn how to encapsulate styles (there are plenty of good patterns) and it will flow just fine.
It really shines for apps that are changing rapidly and are at risk for generating dead CSS, which has been a problem in pretty much every commercial codebase I’ve ever worked on. Tailwind adds a simple, straightforward, one-way-to-do-things approach that creates a much more maintainable experience in HTML templates that results in zero dead CSS code.
It’s absolutely not for people that need fine-tuned CSS APIs like animations, etc. But for building a product rapidly, it’s become a go-to for me.
I never try to be dogmatic about new things - so I'd try it again. I just haven't seen the benefits yet myself and so default to the cons I expressed earlier.
True, but those usually involve adding some sort of linter to ensure that your style sheets are clean, which is an additional build step, which is an opportunity for a build to fail. Tailwind gives me this out of the box and doesn’t require any sort of manual lifting because it does this automatically.
> Tailwind starts to break down for larger/complex apps also
This hasn’t been the case for us, I’m on a team of about 50 devs contributing to a 2 year old monolith and Tailwind hasn’t once gotten in my way.
For what it's worth, in SvelteKit CSS is per-component and you get warnings for unused CSS selectors.
Style classes are IMO the neatest way to inject styles, having elements get styles based on html structure makes code brittle and hard to reason about. If you need an example of this try playing with bootstrap forms.
<div class="unique-component-name">
<input class="unique-component-name-input" />
<p class="unique-component-name-text">Blah</p>
</div>
<div class="unique-component-name unique-component-name-variant1">
...
.unique-component-name {
...
The cascading in HTML makes the thing that should be easy, creating variants with slight tweaks the most painful thing.And I did not say to base styles on html structure - you are correct, that is brittle and actually one of the things I often ask about in FE interviews as a way of determining skill level. I said that good html structure makes CSS much easier, if your structure is bad, it can significantly compound the amount of CSS needed in order to achieve the desired outcome. So I believe there is a significant distinction in those two statements.
Tailwind is a massive improvement in terms of maintainability across teams and tooling. Thanks to Tailwind my team hasn't had to think about CSS resets and browser shims for over 5 years now, and any bugs where an application looks different in a particular browser can be forwarded to a team who will fix it, instead of us having to maintain an ever-growing pile of special rules and feature detection code.
There is, of course, no silver bullet, but for a team building applications from components with React or Vue, Tailwind is a maintainability dream compared to stylesheets, and easier to train new devs on too.
I believe both React and Vue have the capability to scope your CSS along with the components. Modular CSS has been much easier to maintain over years than fixing when Tailwind updates or finding (again) that one !important that happens to conflict with a new released component set.
I save my teams time and money by applying CSS in the manner that it should be; which means not as an inline style mechanic.
While that's true, it also means you need to propagate all of your exceptions for support of old browsers. And you still need a ton of global styles so your application can be re-themed or white-labeled according to your customer specifications. And god forbid someone applies a color directly in a component and you have to grep the codebase looking for the errant code.
After 5 years of tailwind on several complex applications, I can say that it's been easier to maintain, especially as engineers come and go, than any of the applications I worked on before. Frankly, every company I've ever worked for wound up with something like their own bespoke tailwind anyway, but instead of having it well-documented, every new hire had to learn whatever naming system whoever wrote the global design styles decided on.
> I believe both React and Vue have the capability to scope your CSS along with the components. Modular CSS has been much easier to maintain over years than fixing when Tailwind updates or finding (again) that one !important that happens to conflict with a new released component set.
In my experience that's empirically false. Maybe if you only care about Chrome, but CSS is hell to maintain when you need to keep support for browsers like pre-blink Edge.
Any remaining reusability can be handled with templates / components (depends on your framework).
The remaining potentially nice thing about Tailwind is that it more naturally constrains your options/syntax with utilities - when working with designers, this is probably a good thing. As always, the hardest problem of development is finding technology that best establishes the social contract.
I also don't think about it too much and sleep well at night ;)
For most uses, the only thing really wrong with the style attribute is the lack of breakpoints for responsive layouts.
I'm a backend developer, who works mostly in python. I'm probably never going to learn CSS but I can produce a user interface that looks like I'm competent by copy-pasting tailwind divs. In 5 years, I'll hire someone who knows CSS to fix it. It'll be cheap because webflow and squarespace are allowing graphic designers to build websites, which is squeezing the demand for CSS as a skill.
Tailwind as the "new bootstrap" makes a decent amount of sense.
These frameworks aren't an excuse to ignore and misunderstand the underlying technology. It's worth understanding CSS, but these abstractions can really speed up development time, especially if your job involves more than "front end development" (which is still true for many of us).
What do you mean? Bootstrap has not been affiliated with Twitter for more than a decade.
I edited that part out, thanks for pointing it out.
You could not pay me enough to learn CSS. Every time I have to debug CSS there go many valuable hours of my life. With an insane amount of trial and error and judicious use of Chrome's dev tools I can usually hack some garbage together, until the next time I have to figure out how to remove the background of a button.
In the literal 90s I was building fully-featured GUI programs by dragging and dropping buttons and text boxes and inputs onto windows with Visual Basic, and the window resized nicely. Thirty years later I have to do the same thing with gazillions of arcane style sheets. It's a disaster. How did it get this way?
Users were enamored by custom drawn UIs, so designers started demanding custom drawn UIs instead of native widgets. Most users don't understand what they lost and now pawing at interfaces to discover how they work is the new norm.
It’s called “progress” apparently, and older gray beards complained about it when we reinvented the mainframe through the same methodology.
For all of the re-use that us computer folks talk about, we surely reinvent the wheel an awful lot. I’m guessing that we have some sort of stubborn creative streak that causes it all. That’s my excuse at least.
I.e. programming is not supposed to be easy. So if one sticks to it, the problem has to be hard at least from the management point of view.
Modern web design is a mess, yes, but it's vastly more sophisticated than what was available in the 90s and I would not choose to go back.
I was skeptical at first too but after building several large and successful sites with tailwind I’ll now choose it every time. It’s the only CSS method I’ve tried that doesn’t turn into a hot mess at scale.
This attitude has become a pretty useful anti signal when considering who I want to work with though.
The key difference between Bootstrap and Tailwind is that Tailwind designs are distributed. So Bootstrap designs feel like Bootstrap designs, while for Tailwind you can keep having new and fresh designs from different sources.
Kind of the same with jquery (although it took quite a lot of new stuff...)
I feel like Tailwind won't get that
Components UI systems are not going away, even as we move back to static heavy sites and minimizing JS where ever possible.
Like in WordPress or React you can fiddle with Tailwind too. People like to fiddle.
You can make things easy, or fiddle, what did people do? Correct, fiddle.
Why you think so many huge overbloated frameworks have soo much success. Fiddle. Fiddle is the key to everything in development.
You fiddle hours and hours until it works, you feel like the greatest dev on the planet.
You fiddle it, you write a blog post over your fiddle and how fun it was, other read it and fiddle too.
It work and they feel great too. Fiddle continues.
Maybe, they're just superior in a dimension their critics don't care about.
Link: https://htmx.org/essays/locality-of-behaviour/
Discussion on HN: https://news.ycombinator.com/item?id=31454886
I personally find it easier to have information spelled out locally at the "call site".
I do constantly shudder though when reading a list of class names like this:
> fixed inset-y-0 right-0 z-50 w-full overflow-y-auto bg-white px-6 py-6 sm:max-w-sm sm:ring-1 sm:ring-gray-900/10
1. Find source file with class name. See the scss extension, dread rises a bit.
2. See scss file has multiple @import directives and uses multiple custom functions.
3. Open up 4 more scss files to see what those imports and functions do. See that those files also use @import directives. Find some Malort, take a shot.
4. Repeat step 3 until arriving at root of style hierarchy or pass out.
That's why Tailwind works. It may result in a very long line of small classnames to represent all the styles across many breakpoints, but at least you don't have to deal with somebody else's own little hellish adventure into perfectly reusable scss.Tailwind is seeing steadily increasingly popularity (and the accompanying backlash) because it is straight forward and does not require something like stylelint to keep you from hurting yourself.
Ultimately, it really is "a couple hours of thinking/configuring a linter vs. multiple layers of abstraction, complexity and dependencies added to the codebase."
Maybe I'm missing something (and be my guest if I do!) but there is an objectively better choice here.
I really dislike sass the way it's normally used. It was once a necessary hack, but it's mostly not useful anymore. Something that just concatenates your CSS @include on deployment would bring more value nowadays.
There's a default config, with only base rules, without the more opinionated ones. Then you configure/extend it as you would with almost any other tool. Isn't it the way most tools of this kind work?
Or am I missing something?
IMO, missing some rules is better than what most tools of this kind do, but something as plain and obvious as "did you enable debugging symbols on the development build?" should be there. And most people will blame the tool if it's missing.
As I see it, the problem was one of SASS code architecture. What do you mean then by "enable debugging symbols"? How does that solve the "chaotic file architecture" problem?
And now that I think about it, that would be a great exercise in fact! Yes, I'd really appreciate it if you have some in mind and would post them here.
I'm all ears (eyes)!
but once you got to the point where you open a file and see 20+ classnames stacked in every div, which makes them unreadable, its just a mess. Love-hate relationships with this tool, but the idea is very good and this article mentions biggest selling points - its easy and very fast to use.
I find that using tailwind's flex "aliases" (which is almost what they are) is more intuitive than using the god awful standard CSS property names.
CSS standards should not just look at adding stuff, but making new versions, like newer APIs where they take a good look and rename all the properties to make them more consistent.
https://csswizardry.com/2018/11/css-and-network-performance/
Progressive rendering of CSS is a great boost in performance. Tailwind can't benefit from this technique I think and as such, imposes an added cost on our users.
Correct me if I'm wrong!
The article describes a strategy for loading CSS in the most performant way given a variety of interconnected factors (mainly JS).
You could generate the Tailwind file, and then split it when the media queries start (they're all grouped in order of screen size) with a small bash script into separate files as a part of your build process.
You could have multiple build steps that analyze your component architecture and generate separate CSS bundles for each component. This is already done w/ most JS frameworks.
If your argument is one of the final CSS file size, that is not an issue. Tailwind only generates classes that you write in your markup. Most Tailwind bundles I have seen, are dramatically smaller than their CSS counterparts, and it makes sense when you think about how CSS is written.
Say you have a two UI elements; an article preview image and a user avatar. Say you want them to mostly display the same, but with some tweaks to the avatar to add a fancy filter on hover. Okay easy enough. Maybe you start with some sort of base mixin and then overwrite add behavior for the avatar. Over time, you add more and more tweaks to the avatar until one day, you get a call from the head of Design Department that the articles are getting their own special CSS filter. Okay, so now you extend the article. Over time the two continue to drift until you're overwriting anything that they originally shared in the beginning. The articles have different margins than the avatars and now marketing wants to allow users to upload images to comments. Does that extend the original mixin from 3 years ago? Maybe you think, "why do I even have this base class; can I get rid of it?" After some quick testing you remove the original mixin and go home for the day. Over the weekend, you get a call saying that the avatars showing user contributions from a fundraising event are all messed up. It turns out, the base mixin added `display: block` to the images, but when you tested, you really only looked at the logged in user profile photo in the navbar. Whoops.
Now take that scenario and multiply it by 100 devs on 20 different teams. We've all seen it. This is why CSS is often never deleted in large companies. Devs instead to continue writing ever increasing specific selectors or using techniques like BEM/OOCSS to stop the bleeding. It takes an insane amount of discipline to wrangle CSS on a sufficiently large project. Tailwind helps manage some of that complexity, and at least provides good guard rails for teams of developers by empowering them to know that a "small refactor" won't break an entire layout.
https://frontstuff.io/in-defense-of-utility-first-css
https://github.com/sarahdayan/utility-first-compression-demo
To reiterate: you can link and load CSS for a component just when this component is used instead of loading everything at first. So the first load of the page is faster. Same thing with media queries in link tags. Isn't that something Tailwind can't do? Tailwind will load every style, every time, right?
As for your example, I get your pain. I' ve experienced it too. But it isn't a reason for completely pushing aside CSS in favor of a framework and all that it entails. It is a reason to have good linting.
For example, no component should ever influence the "outside world". So no margins on components. Rhythm (gaps or margins) is better taken care of by the parent (a grid, a list, etc.). This is a simple linting rule in Stylelint that will prevent this development behavior.
As for the rest of your problem, I'd say the "mixin" approach is of disservice here. That and, the way you implement the filters.
Are filters to be arbitrarily applied on the whims of the designer? Creating filter classes to be applied in a singular way then may be a good approach.
Are there rules governing the usage of the filters? Then a systemic approach could be a winner, especially if you can talk with the designer.
There are simple ways of managing these issues/problems with native technology and a little linting.
PS: Sometimes the problem IS the design. If the design is irrational, the real, efficient solution is not to implement these irrational patterns but to talk with the designer and find a rational solution. I know this isn't always easy but that is the problem resolution we should strive for as it is the most efficient one.
> Isn't that something Tailwind can't do? Tailwind will load every style, every time, right?
Tailwind's only function is:
- Scan codebase
- Generate classes
- Save them in a file with the a .css extension.
Anything else that you want is outside the scope of the tool. It makes no assumptions about what your files are named, where they are, or how it's loaded in the browser. At the end of the day, it's up to the developer to write `<link rel="stylesheet" href="/path/to/my/generated/file.css">`
This is no different or made easier/harder by using Tailwind.
That's the part I'm not sure of.
And this is ignoring PostCSS which has over 60M downloads weekly. But I guess you can use postcss with tailwind.
Like... It has won nothing, its in the game though.
> It replaces a generation of sites built with Twitter Bootstrap.
Jquery was handling element selection, manipulation, behaviors, futures/promises, ajax calls etc.
Somebody came along in each of those categories and “specialized” such that jquery was left as the bloated old choice.
Bootstrap was awesome, but as component based libraries like react/vue etc came around, I don’t need component level css helpers as much.
And then tailwind helped fill in the gap of being quite a bit more explicit and granular.
It’s impossible to write a media query or target a child with inline styles. With tailwind, the first one is encouraged and the second is at least possible, and in some scenarios, encouraged (group hover).
While tailwind lets you write your styles in the same _location_ as the style attribute, it allows you to restrict what _values_ you can use. You can set up a colour palette so that when you say `class="red"`, it's the shade of red that you (or your designer) picked, and your colleague can't decide to pick a slightly different shade for their component.
There are far better ways of writing CSS than Tailwind… take a look at Stephanie Eckles, Andy Bell and others work on how little CSS you actually need for great designs
I find it ridiculous to attach so many classes to your HTML elements. I think it is obvious Tailwind gained popularity because people just didn't want to learn CSS. And I don't blame them, it took me years and I am still learning new ways to achieve things. In a way, CSS's flexibility is also its beauty: you can achieve the same thing multiple different ways.
You can do A LOT if you know CSS. With tailwind you can do what others have thought of you might need. This is the antithesis of programming. Programming is supposed to help you break the limitations of tools.
That’s why it won.
Modern front-end development heavily embraces small components, composability, clean abstractions, reusability, higher order state, decoupling of error logic, testability, and so on.
The natural consequence of this paradigm is that when your PM says "hey, can you make a small change to this online form?", you'll be context-switching between many files.
The idea that you currently can do "application logic" in your HTML/JSX is a gross misrepresentation of reality.
Tools get updated constantly, packages get updated constantly, breaking changes get made almost constantly. Five years from now, your packages probably won't work, and it will be almost impossible to work on a project -- unless you've been maintaining it over the past five years. If your product is your business, of course you're maintaining it. But if it's just a hobby you want to work on sometimes -- then you want to be able to abandon it and then come back later without the pain of figuring out why you can't compile your SCSS, javascript, or similar things.
Learning A can be pretty quick for some basics, learning B is a rabbit hole that can take ages to 'learn'. The good news is most of what you need is for something 'competent' is in A
To answer your points below:
1) Front load your design. The equivalent to Pseudocode for the Front-End is to wireframe. Consider all of your pieces, how they should be grouped, and why. There are some common patterns you'll run into in everyday life. If you find those patterns, draw them on a piece of paper (or your editor of choice, you could do it with mspaint if you wanna). Then you can write out your HTML/CSS. I typically work back and forth. All the HTML, then I CSS, then more html if needed, then more css. etc.
2) An effective Front-End is one which gets the user where they want to go with as little friction *as possible*. Emphasis on as-possible because, just like asap, it doesn't mean "yesterday" it means, "Please prioritize this task above other tasks". An effective FE has a clear idea of purpose and wastes no time achieving those goals. Also, see patterns above. This might not be useful yet but one pattern is to look at the shape of what you're trying to display and allow that to dictate the FE. As an example - almost all documentation sites have a left (or right, or floating) vertical navigation, it takes up maybe 10% of screen width, and then the content of that documentation fill the rest of the width with some amount of padding on the left and right. Consider flipping this pattern. Make the Nav horizontal and the documentation full width to get a feel for why most documentation looks the way it does.
2.1) Some terms to search, "Elements of Art and Principles of Design". I recommend everyone look them up - there are ~20 ideas that reference how we go about making something aesthetic.( Art - color, form, line, shape, space, texture, and value ; Design contrast, balance, emphasis, proportion, hierarchy, repetition, rhythm, pattern, white space, movement, variety, and unity )
3) Uh this is a bit more complicated than I can do in a single comment but maybe we can share discord names if you like the cut of my jib so far.
For anyone who has been in web dev for long enough I can assure you there's nothing cleaner and more maintainable than avoiding CSS frameworks.
My experience is that this is only true your CSS is written by a one man army.
I switched back to bootstrap for personal projects, where I make a few tweaks to the global theme, then write zero css and very little styling besides things like margins and alignment. It's way easier and enjoyable for me, though I admit that my apps all look pretty generic.
I also like that it lets you build anything and does not have a default look.
Heck people can even come together for a web framework let alone one tiny paid CSS tooling.
It does things in a brain dead way to protect you from other people’s idea of cleverness.
Also in corporate settings apps and sites don’t follow sensible rules, you think you’re gonna have a few sensible classes for a few different components?
Well marketing decided that they need 50 small variations of just one component, of course it makes no sense to you, but that’s the requirement so shut up and do it.
If you’re not using Tailwind you end up with 50 exceptions and your normal CSS quickly becomes unmaintainable.
Tailwind is the mad solution perfectly suited for a mad world, and only people who hate it are those who don’t have to deal with madness.
To me, this would be like saying writing a function in a React component and then writing the HTML for that same component is context switching. It just doesn't stand up to scrutiny. The tasks are related and in a similar headspace - even if they aren't connected 1:1.
> Switching to a CSS file to change styles is a costly context switch
It is?! I have an IDE with more than one pane. CSS-in-JS exists if you really don't want to switch (albeit with its own problems)
> you can just copy and paste a list of classes or an HTML block into your application
Well back in my day we called these "inline styles" and came with their own problems. CSS is copy-pastable as well, and easily composed with classes.
> Compare this to [..] CSS build systems like Saas
Tailwind requires a build step! Frankly, I haven't seen a sizeable webapp without a "build step" for incorporating even plain CSS
> The best way to write the least amount of CSS is to just compose basic styles
This feels like an argument against Tailwind? Utility classes are helpful but will never be enough to replace CSS entirely without long lists of classes on every element
I see loads of comments in here using things like `.mb-sm-3` (I presume it's `margin-bottom: 3` for small screens?) as an example for how readable the classes are, but with CSS introducing logical properties I wonder if Tailwind's syntax needs to update to accommodate those changes? Using logical properties, this same example would render to `margin-block-end: 3` and already you're moving away from the easy-to-remember shorthand Tailwind created. If Tailwind's syntax needs to update, isn't that a pain in the ass to maintain?
This is just one example, but CSS is introducing loads of new stuff every few months it seems and I would hate to be limited by the constraints of a CSS library when browsers are capable of achieving so much these days. I enjoy learning CSS, not Tailwind.
If you are in a design or product function in a enterprise company in non-tech industry, you steer clear from Tailwind. But, I appreciate its usefulness for developer's who just don't want to learn CSS or have the time to prioritise building their own design system — that comes with maturity.
In any case, Tailwind trades one CSS problem for another and it just illustrates that web development is not different than any other kind of development — it's all about managing compromises in technology and approach, based on your needs and future plans.
That means that the design/product requirements come first. The moment Tailwind's limitations meet design requirements, it'll take a back-seat.
It's basically the same reaction you'd encounter from saying "we'll build it in Bootstrap." If a company is investing in a new product or service, no one wants to be the guy that says "sorry our framework won't let us do that design" — at least, not in first year or two of a product life-cycle.
Tailwind's advantage — speed and accessibility for a range of developer backgrounds — isn't the same priority for large organisations vs. startups.
I'm very well aware of this because I tried to make it as efficient as possible.
With Tailwind, it looks like you design by writing HTML, which is the opposite of what CSS aims at. So if you wish to change your design, you'll have to update multiple templates instead of one CSS rule.
Every time I've had to work with Tailwind, it felt like a chore and it was an unpleasant experience.
You can use Tailwind on top level and it is easy. But as soon as you have complex components with sub-elements, the styling gets really complicated.
It was easier to add component specific classes and define the css within the component. You call then the component with the classname.
this comes up on every tailwind post and it isn't true. tailwind encourages you to not repeat yourself by making reusable components (or fragments etc) instead of reusable classes. that way if I want to see how the button both looks and works I only have one place to look
even if you don't do this, with tailwind you encode your design system (colours, spacing) etc in the config file so even copy pasting everything will get you something consistent
https://tailwindcss.com/docs/utility-first#maintainability-c...
The rendered output is crazy, yes. But this argument applies to every JS framework ever created.
Authoring the code is best encapsulated by components. If you look at the source files available for their paid templates, they are all componentized.
Maybe the issue is that the giant pile of JS mess has created such a disaster that adding Tailwind doesn’t feel like making anything much worse.
I can buy that.
For what HTML is for (documents, web pages, etc.) CSS makes sense and Tailwind seems crazy.
If you’re trying to code an application, for now perhaps React + Tailwind and a mountain of NPM dependencies does actually make sense.
Really I think going back to application coding via something like WASM surely has to replace all that though.
The web platform is not going to move away from current paradigm without an overwhelming shift in priorities or needs. Wasm still generates html and outputs it on the screen.
My biggest reason to use tailwind is maintainability. Having everything right in front of me with only the tiniest of abstractions, makes it really simple to refactor and maintain. I can confidently delete “CSS” and know it has no side effects. I can cut and paste a block of html and it will render EXACTLY the same. I don’t have to worry that Steve used a generic sibling selector in a CSS file 3 years ago that is screwing with my layout/design.
Is the HTML more bloated than if I had written “normal” css? Yes, but I think it’s worth the trade-off. It’s important that we can agree that their are trade-offs and then it’s up to each project to decide if those are worth it for their use case.
I’ll also mention the actual CSS file is crazy small as well since the tool only generates classes that are actually used in your project. No more ever-growing css that other people are afraid to delete for fear of breaking some legacy page!
Sure it can. More usefully to my point though, it can also use any of a number of C++/Rust/etc. UI libraries to render directly to a buffer or canvas, which is in my opinion a better long term solution for true applications (vs websites).
When you do that you get total layout control with no need for CSS or worrying about browser defaults.
As a random example here is the Rust egui library demo app running in a browser using WASM (no HTML): https://www.egui.rs/#demo
The speed and “native application” feel are hard to replicate in JS/HTML, as they are just not great tools for the job or rich desktop (or desktop-like) applications.
Although I have the sensation many people find hard to write CSS and even despise it (I've read people here in HN who seem to think we should've kept doing layouts with HTML tables and don't agree layout is the job of CSS!) I definitely agree having dozens of classes in your HTML is messy and weird.
div.height(maxVH).color(primary).hide()
It’s all stuffed in classes because that’s the limitation given and this information belongs in the markup.
The above is much cleaner to me than: div.class(“primary”). I need to go find primary. What is the parent class. What happens if this isn’t a div now etc. what happens if the parent isn’t a div?
Tailwind just spells it out for you right alongside the layout so that you have all the information in one place.
For me personally, I was able to do things in tailwind I could never do in raw css, but I bet I got better at css as a result.
The docs are also incredible for tailwind. As good as mdn is, you need to already know what you’re looking for.
``` (in CSS)
a.link {
border: red;
}
a.link:hover {
border: blue;
}
```
``` (in Tailwind)
<a class="border-red hover:border-blue">
```
It's much easier in Tailwind for me to see locally what's going on with that styling. If I lived in this code all the time, or I was good at structuring CSS, then maybe the first would be more appealing. But I'm a shit at CSS, it always turns into an unmaintainable mess, and I look after a lot of different projects that I might not touch for 6 months. So Tailwind's approach is easier for me.Suppose we want to change just one link? Would it be better to make a new class with all the same attributes except the color and apply that to the specific link.
Brittle.
> Suppose we want to change just one link? Would it be better to make a new class with all the same attributes except the color and apply that to the specific link.
Why copy the attributes? Just override the one you want to change. You can even use style="…" if you're sure that it's just one link.
2. Suppose you change the example to use named colors. Where does this name-to-color-value mapping live?
****
> I've noticed that moving the goalposts is extremely prevalent on HN, which makes for pretty frustrating conversations (or just reading). And then sometimes it's a tag team. E.g.:
> Person A writes their comment. Person B1 offers a rebuttal. Personal A offers their response. Person B2 offers a second rebuttal that abandons the premise behind B1's rebuttal, and may actually be at odds with it. Person A ends up either deflated or looking defeated.
> It's like the cross product of a Gish gallop and a DDoS.
Then again if your styles are abstracted to a component, your CSS framework is irrelevant!
Maybe it's some sort of lock-in feature.
This is not true in svelte, where a component file can have both a root tag for the component, and a <style> tag that the framework/compiler automatically scopes to this component (and a <script> tag for the code, since you don't have the JSX inversion-of-control principle).
In practice however I see a lot of copy paste in tailwind html so it doesn't work quite as well in reality.
As for the "git gud" school of CSS, should we also abandon React, Svelte and the like and revert to hand-cranking DOM manipulation like it's 1999...?
Sure, if you're manually editing a large volume of .html by hand, Tailwind is bad news, but given the plethora of static site builders out there (brief shout out to Astro which is excellent), manually authoring individual .html pages seems like masochism.
```
a.link
border: red
&:hover
border: blue
```https://webkit.org/blog/13813/try-css-nesting-today-in-safar...
a.link {
}
a.another {
}
<a class="another link">...</a>
It was easy to fix, but hard to scale the fixes over different codebases, timelines, and developers. That's the problem Tailwind solves for me.Who rolls the basic boring CSS classes like border-red or border-primary by themselves? People have been doing it for free for over a decade.
And when the designer change his mind and border-red should not be used anymore?
And what if you have small changes, e.g.
```
<button class="bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded">Button 1</button>
<button class="bg-blue-500 hover:bg-blue-700 text-white font-bold py-3 px-4 rounded">Button 2</button>
```
1. Not worry about it, it probably won't happen on the projects I'm working on. YAGNI.
2. OK, it's happened. Get some coffee, make all the changes. Can I use a regex? Make the changes incrementally? Delegate it to a junior?
3. This is going to change a lot. Let's make a re-usable component, a named colour like 'primary' (in Tailwind config), or re-usable class like .button-default. The right solution will depend on the requirement.
In styling, I'd rather have 1000 obvious changes than 1 difficult one. The risk of having the wrong shade of red is not high enough for me to worry about abstracting it.
I appreciate that good, full-time CSS devs have much better solutions for this, but those solutions involve being good at CSS as a starting point. I don't have that luxury.
It is an unpleasant chore if you use it by hand and I have given up on it but I can see that if it's just used in components and then html is not written by hand but made dynamically it could work better.
It's basically a CSS framework for JS frameworks and not for writing HTML.
Changing the CSS to apply site-wide changes sounds great in theory but after working in front-end since IE6, this almost never happens in practice. You're never certain how the styles cascade and indirectly affect things so you're afraid of changing the core CSS.
Styles isolated to components is a much more scalable approach in my opinion and then it doesn't really matter whether you use Tailwind, CSS-in-JS or scoped CSS (Vue etc).
…so let's solve that by making it completely never happen?
From my perspective, "almost never" and "won't actually happen" aren't that different. Both indicate that the probability of success is very low. It seems to be, if the probability is already really low, is not worth extending effort maintaining it.
I'm not the person you're replying to, but I'm in a similar position, and while I'm not in love with Tailwind*, it's successful because it's oriented around components rather than classes. In every project I've worked on, it has been far easier to manage the complexity of components over classes, because components link style and structure together, which usually end up very tightly coupled anyway. This limits the scope of the CSS you're writing a lot, making it a lot simpler to understand what any individual declaration is going to do - you know exactly where it's being used, you know exactly the HTML structure it's operating on, you can see exactly what it will do as a result.
* I use it a lot at work because it's very easy to get something written, but I find the pseudo-CSS DSL irritating if I need to write more complex queries. Something like CSS modules requires a bit more boilerplate to use, but you end up writing real CSS queries, which I find more natural. But this is personal preference.
How will I ever keep track of where I used px-6 and where md:px-4 in my templates and why, without semantic classes? Of course I can then build more solutions around that. Or I can accept that good css design is hard, just like any good software design is hard.
How will you track that in `.hero-text__sticky-container--primary` vs `.text-with-image__card-primary`?
And then it's still hard, because good css design is hard. Tailwind is not making that easier.
Then your DOM is too complex. You're formatting a text document; that shouldn't get you in a position where you lose track of what cascades where. If it is you have a bigger problem than styling.
CSS styles are also more reusable across different web sites. I can to some degree see that you can increase re-usability when using shared React components, but then you just create technical debt for those who want to test other frameworks
It seems to me that Tailwind is only a semi-scalable solution for those who use React components or similar. But as mentioned above, that causes problems when you want to make other webapps in another framework
- I generally dislike inline CSS styles, and the benefits of Tailwind is not enough to overcome that.
- Reusability across systems. At least in mature businesses, they often have CMS systems, different frameworks etc. Using Tailwind kind of encourages everyone to use the same internal React component library.
- Easier to read PR and git logs. Adding a single tailwind class to a component may mark the entire line as changed, and you need to figure out what has changed (including checking the code, because you don't know if that also changed).
- Designers can make changes in CSS without having to learn React.
But as someone who works on UIs built with react, it's nice to not have then need to leave my JSX components - html, js, and css (via tailwind) are all nicely colocated. Especially nice with the vscode extension that shows the css rules of the underlying css decleration.
I agree that fundamentals trump all, but tailwind is a nice css abstraction that hits my use case well.
I basically was squarely the target group of bootstrap, and used it for lots of projects in all versions. I didn't actually care much about their technical progess (float, flex, css-grid, whatever), I just copypaste from the available widgets and add in my data.
Just LAST WEEK I learned that my favorite web framework (https://phoenixframework.org/) now ships with Tailwind preconfigured by default. I also heard good things about it from trusted colleagues. So, for the next big project I decided to jump in. Still I kind of have concerns: I need "typical components" like cards/tables/grid/... to be only a copypaste away; and I need to allow some designers be able to tweak the overall look and feel, roughly like a theming file where fonts/colors/... are defined at a single place. I hope it will be smooth after all these years of bootstrap and the "muscle memory" of how to compose pages with it.
If you want a more Bootstrap like experience, look into something like DaisyUI. It gives you a high level primitive similar to Bootstrap, but built on the philosophy of Tailwind in regards to ultimate customization using utilities.
If/when you get more comfortable with the tailwind primitives, you can easily make your own component abstractions that work for your needs.
Instead of using a framework, I just rip other sections of website designs I like using my tool. The paid version even scopes the snippet and gets all responsive styles.
Theming abilities are on the roadmap and with AI being able to adjust my snippets eventually - I really don’t see the need for extremely verbose frameworks like Tailwind. But I could be wrong, I’m probably biased after having worked on it for a couple years.
We share a base layer in HTML, CSS, JS, but the incentives, requirements, job environments, team sizes, couldn't be more different.
I wonder about other languages and ecosystems. What would be a similar situation for e.g. C? Is there such a thing?
It's very frustrating to have to make a lot of decisions around standard component styling on each new project.
It also makes it so much easer to progressively update things to a new design, without worrying about 1 change in a CSS file potentially having an effect anywhere.
Don't you just have to worry about making sure your update is propagated to all the right class lists? Seems like trading one medium problem for 30 small ones.
I mean there are techniques to avoid that like BEM and co, but they rely on you and your colleagues following them, and in my experience are a huge ballache.
Its also sometimes hard to track styling issues down, looking through all of the properties etc. And if you get into SCSS and mixins it slowly gets out of control.
On the flip site with Tailwind, it's all there in front if you and easy to change. If you need to repeat something often, you can just create components / partials with reusable parts.
Then you realize you can just use the classes with css and forgo the tailwind Middleware.
Then we'll be back where we started.
No, Utility Classes Aren't the Same As Inline Styles
https://frontstuff.io/no-utility-classes-arent-the-same-as-i...
It has helped a lot of people - myself included - write more and better CSS but I don’t understand the vitriol here. If you want to write vanilla CSS or BEM or Sass or Less, I think that’s great.
I dislike Tailwind and would never choose it so seeing it presented as if it climbed to the top of some pile makes me laugh out loud and based on the comments there are a fair few people that agree. That said, use what works for you and I won't try to claim my choices as "winners" in some undeclared contest.
How do you get a basic Tailwind design running? It seems like you need a Bootstrap equivalent on it anyway.
Probably not granular enough for Tailwind fans though.
The top comments will always be negative.
Don't give too much weight to this when choosing what tech to use.
It's not a perfect replacement for vanilla CSS and I still fall back down to writing plain old CSS for stuff like box shadows or more interesting grid layouts, and using tailwind modifiers like different screen sizes is less than ideal with having to prefix every single CSS property with the same modifier.
The "default" (no css) look of HTML pages with black on white Serif text with default paddings / margins / spacing...must also have been picked at the time to make web pages look pretty (in a generic sense) out of the box? Just that we have now evolved in our sense of visual design tastes / whats possible has changed over the decades, maybe.
only thing worse than a comment made out of ignorance is one with that additional amount of hubris attached. this point somehow seems to always float to the top of every tailwind post. not surprising to see it as the top comment.
CSS + Tailwind will be my go-to stack for all my new projects.
With the 2 combined you can save a ton of time and still having a decent responsive design
It's true that, as the OP claims, many developers are not writing HTML/CSS, they are writing JSX (or similar) so maintaining a separate CSS file is a context switch. Point taken, and well made. Also, the original HTML/CSS split made more sense when one was writing documents, not applications, and the author and designer/typesetter were separate people.
However, svelte (my current favourite framework) gives you the option of putting a CSS block in a component source file, which is compiled to be local to the component. For example if you put "h1 { color: red }" in a <Warning> component, then effectively what you get is some kind of "h1.warning" rule. It just works in the background how you expect it to, doesn't interfere with anything else, and you don't have the context-switching overhead of separate files.
I know that svelte has a lower market share than some, and of course you can use tailwind together with svelte, but the claim that "writing CSS = switching files" is only true within the scope of e.g. React, not in general.