Moving away from Tailwind, and learning to structure my CSS
jvns.ca306 points by mpweiher 11 hours ago
306 points by mpweiher 11 hours ago
> I got curious about what writing more semantic HTML would feel like.
I've been teaching semantic HTML / accessible markup for a long time, and have worked extensively on sites and apps designed for screen readers.
The biggest problem with Tailwind is that it inverts the order that you should be thinking about HTML and CSS.
HTML is marking up the meaning of the document. You should start there. Then style with CSS. If you need extra elements for styling at that point, you might use a div or span (but you should ask yourself if there's something better first).
Tailwind instead pushes the dev into a CSS-first approach. You think about the Tailwind classes you want, and then throw yet-another-div into the DOM just to have an element to hang your classes on.
Tailwind makes you worse as a web developer from a skill standpoint, since part of your skill should be to produce future-proof readable HTML and CSS that it usable by all users and generally matches the HTML and CSS specs. But devs haven't cared about that for years, so it makes sense that Tailwind got so popular. It solved the "I'm building React components" approach to HTML and CSS authoring and codified div soup as a desirable outcome.
Tailwind clearly never cared about any of this. The opening example on Tailwind's website is nothing but divs and spans. It's proven to be a terrible education for new developers, and has contributed to the div soup that LLMs will output unless nudged and begged to do otherwise.
you're unfairly conflating things and putting the blame for a lack of care or understanding on tailwind vs on the dev themselves. nothing about tailwind forces you to build inaccessible or "div soup" apps
can tailwind be used poorly? absolutely. but that's true of any tool
i've been writing CSS for ~20 years and am quite capable with it, having used CSS, Less, SASS/SCSS, Stylus, PostCSS etc. the reason i have settled on Tailwind for the last few years is precisely because it enables me to build more robust application styling.
tailwind frees you from having to spend excessive time building abstractions of styles/classes that will invariably change. placing the styles directly into the markup that is affected by it reduces cognitive load, prevents excessively loose selectors affecting styles unintentionally and really aids in debugging. jumping into codebases with bespoke css frameworks is always more complex and fragile than a tailwind codebase for anything but the most simple sites/apps
add to that the ability to have consistent type, color and sizing scales, reduced bundle sizes, consistency for any developer who knows tailwind and a very robust ecosystem (and thus llms are very familiar with it) and tailwind is a really excellent choice for a lot of teams
tailwind is like most tools; it can be used well or poorly depending on who is using it
> tailwind frees you from having to spend excessive time building abstractions of styles/classes that will invariably change.
Abstractions like a hero image, a menu, a headline? Sure, it's easy to overthink things but most of the time, it's not that complex.
> placing the styles directly into the markup that is affected by it reduces cognitive load, prevents excessively loose selectors
In my opinion, it's the opposite. Besides the obvious violation of DRY and the separation of concerns, inline CSS can't be cached and it creates a lot of noise when using dev tools for debugging. It actually increases cognitive load because you have to account for CSS in two different locations.
Lots of people use Tailwind because they don't want to deal with the cascade, usually because they never learned it properly. Sure, back in the day, the web platform didn't provide much built-in support for addressing side effects of the cascade, but now we have @layer and @scope to control the cascade.
Tailwind uses a remnant of '90s web development (inline CSS) and built an entire framework around it. I get why it appeals to some people: it lets you use CSS while not requiring an understanding of how CSS works, beyond its most basic concepts.
To be honest, CSS had the cascade but also had horrible tools for actually managing the cascade for a long time.
If CSS had nesting, variables, media queries, the other nice selector queries like :has, and modules out of the gate, we likely would have not needed much of the tooling like tailwind that eventually got built to manage it all with less boilerplate. We built the tools because even when these features rolled out they came in fits and starts so you couldn’t adopt it without polyfills and whatnot.
Your framing assumes incompetence across the board which is unlikely to be true for a framework of its popularity. Consider instead competent people are working on projects with different needs and they’ve recognized there are trade offs to both approaches and still decided Tailwind makes sense in their situation.
I disagree with that conclusion. I see tailwind as a cleaner more succinct version of css that is much easier to manage and add features too.
Sure it’s not as dry, but I’ve been bitten in this regard because css framework and templates are so intransparent, preventing me from simply changing padding or margin.
CSS is too detailed and too verbose. Frameworks like bootstrap are too high level and don’t give enough control. Tailwind hits the sweet spot whilst allowing me to be detailed if I want to. It allows me to just get it done.
If a tool’s design makes it easy to cut myself, the response is not “people have been cutting themselves for years”.
There is such a thing as the ergonomics of the tool. Yes div soup has been around a long time. But also yes, Tailwind makes the wrong approach the easy one.
It’s ergonomics encourage adding div elements to support styles. It’s the core design loop.
You’re conflating “forces to” and “ergonomically encouraged”.
It’s just the most effective approach, in my opinion. If it’s wrong then I don’t want to be right.
I’ve also been writing CSS professionally for nearly 20 years and am a big fan of tailwind.
The ergonomics in my day to day work are quite nice. To me, the better boundary of abstraction shifted to components, rather than the html/css/js “separation of concerns” that some of the older folks still like to parrot.
However, take a look at the markup and styling for the https://maps.apple.com/ web property.
I can’t deny that it’s quite beautiful and easy to holistically understand. Especially when it comes to the responsive styling—which is when I tend to find tailwind most awkward.
It’s my favorite example of “traditional” CSS structure in recent memory that has given me some pause when it comes to Tailwind.
> can tailwind be used poorly? absolutely. but that's true of any tool
Can tailwind be a useful CSS framework? Absolutely, but that can be said of any of them.
Which is precisely why it makes sense to point out it's unique flaws, so that people can make an informed decision as to what works best for them.
If you have some unique feature to tailwind that you think makes it better than the rest, you should share that.
Everything you have listed is also accomplished by all the other CSS frameworks, so it almost sounds like tailwind is simply the main one you have experience with.
I REALLY hate those discussions because they're a negativity magnet, but since you asked:
Tailwind removes indirection inside the component. There's no longer a need to connect the style with HTML tag using a name (as in BEM, etc) or using an object (Styled Components, etc). The only indirection here is the utility classes, which are a real abstraction, as opposed to a mere indirection like with component-based CSS frameworks. Some of us prefers richer abstractions.
Like every abstraction it requires you to learn some new lingo and rules, but those rules are "global" and externally reusable, rather than "local" and single-use. For some of us, this is a better way of organizing code. Tailwind is similar to Semantic-HTML based CSS libraries in this regard: with semantic HTML you also have a very clear abstraction instead of an indirection.
Also, performance. The whole "Atomic CSS" school was created at Yahoo in the late 2000s/early 2010s to reduce the size of homepages. The goal was to have smaller CSS files but still be able to have components. While a Tailwind CSS can get fat if you're careless with standardizing, it can also be surprisingly lean.
Developer ergonomics are always something I see mentioned, but that obviously depends on the person.
I’ve mentioned this before here, but originally I was against Tailwind because it breaks the Cascading part of CSS, however I think a lot of websites lately work better with “locally scoped” styles as there are just so many different components that many things just dont need to follow a global style sheet. So now I usually reach for tailwind first, unless is a relatively simple vanilla html site
Global styles are like global state in software: They're best avoided.
Global state is bad because it’s mutable. Global styles are not mutable.
No.. that's not the only reason.
Global state is bad because it makes it hard to reason about your system. The global state can affect any part of it, or, focusing on the inverse which is probably better applied to global styles, any part of your system can depend on the global state.
It's also weird to say "global styles are not mutable" - you're right, they're (generally) not mutable, at runtime. But they are mutable in the sense that your developers (you, or your colleagues, or someone in 3 years maintaining your code) can mutate them, and if large parts of your system are implicitly dependent on the CSS cascading properly and so on, then those changes can have unintended consequences.
Of course, that can also apply to tailwind, to some extent. A developer can change a class (custom or otherwise) or the configuration - but at least it is very clear what is being changed and what parts will be affected (just grep).
With CSS unintended consequences are always problems of scoping things better. If I give semantically meaningful CSS classes to my semantic HTML and scope my rules to apply to their intended place in the pages, then unintended consequences don't happen. If I roll like: "Oh, I want this list to look differently, lets make a global scope ul/ol style!" then I am asking for trouble later on. When I write a CSS rule, I should always be thinking about the scope and whether my rules are truly something universally applicable to that scope.
> i've been writing CSS for ~20 years and am quite capable with it, having used CSS, Less, SASS/SCSS, Stylus, PostCSS etc. the reason i have settled on Tailwind for the last few years is precisely because it enables me to build more robust application styling.
I think herein lies at least part of the problem of the web these days: Most websites don't need to be applications, and are needlessly made to be applications, often even SPAs instead of simply being mostly informational pages, in turn putting different requirements for styling onto the project.
> [...] jumping into codebases with bespoke css frameworks is always more complex and fragile than a tailwind codebase for anything but the most simple sites/apps
There is no need for frameworks. Well structured and scoped CSS can handle it all.
> add to that the ability to have consistent type, color and sizing scales, reduced bundle sizes, consistency for any developer who knows tailwind
What if not that does CSS already offer? I don't see how normal CSS does not already do that. No additional thingamabob needed.
> very robust ecosystem (and thus llms are very familiar with it) and tailwind is a really excellent choice for a lot of teams
Tons of ready-made stylesheets out there to use for teams. What more of an "ecosystem" do I need to style a web page? Why do I need an ecosystem? Is it not rather a tailwind self-induced need?
> nothing about tailwind forces you to build inaccessible or "div soup" apps
Totally agree. I feel like this was more a by product of React. Not that React forced this either, but it felt like the rise in both went hand in hand for some reason.
While I think it's true that none of the current top FE technologies force the div soup, they don't discourage it either. It would be nice if what ever FE technologies catch on next did try to encourage better practices around things like accessibility. Make the path of least semantic HTML the path of least resistance and allow people to fall into the pit of success, ya know?
Nothing about programming forces anyone to do anything.
That's never been a valid argument to dismiss criticism. It wasn't with Dreamweaver, any it wasn't with visual basic, and it isn't with Tailwind.
Patterns matter. Best practices matter. Path of least resistance matters. Those are all choices you make when you develop a CSS framework. Some of those choices are good and some are bad.
If none of those things mattered, them choosing a CSS framework would not matter at all.
React encouraged this for years by requiring a single parent element being returned from all components. They also showed a div as the option of choice.
They fixed this later with Fragments but the damage was done.
While I agree I do think there's some "aspiration of purity/correctness" in your approach that I've long let go of.
I look at the royal mess that is HTML/CSS/JS as a necessary evil, required when we want to target browsers. To me it's "just the presentation layer".
In my work I put a lot more emphasis on correctness in the db schema, or business logic in the backend.
When it comes to the messy presentation layer I prefer to write a little as possible, while still ending up with somewhat maintainable code. And for this Tailwind fits the bill really well: LLMs write it very well, new devs understand it quick, and it's quite easy to read-back/adjust the code later.
I 100% agree a Tailwind project is not the best way for a new dev to learn HTML/CSS. But then I prefer the new dev to focus on great db schemas, intuitive APIs, test-able biz logic, etc. Fiddling with the mess that's HTML/CSS is not the place where I consider human attention is best spent on (or where developers pick up skills to become much better developers).
This isn't about "purity/correctness" it's about the real experience of a blind person. Accessibility means caring about the HTML.
Your comment only mentions developers as the audience of HTML authoring, as opposed to users, which is a common attitude and the core problem with Tailwind.
I use Tailwind and have all kinds of "screen reader" directives in my templates.
Not sure if it helps, but if we get our first blind user I will gladly make some admends to make it more usable for them.
It seems that Tailwind is now blamed for the mess that is HTML/CSS. Tailwind certainly allows for accessible designs; it may not be the ideal solution, sure, but what we aim for is "good enough".
> Not sure if it helps, but if we get our first blind user I will gladly make some admends to make it more usable for them.
I have heard "we don't have blind customers" argument many times before. Apart from ethical issues that this raises, ADA requirements, technically, don't care if you have blind users or not. Accessibility is still required...
> but if we get our first blind user I will gladly make some admends to make it more usable for them.
Isn't this slightly backwards? Why would blind users sign up if the platform isn't usable for them in the first place? It has to be usable for them for them to become users :)
> Not sure if it helps, but if we get our first blind user I will gladly make some admends to make it more usable for them.
How will you know if they are unable to use your site? They'll just leave.
It's not just blind people, but also people with reduced eyesight. As I'm getting older, I really appreciate good contrast and the possibility to zoom in without breaking the layout.
People always forget they're one unlucky event from losing their sight, hearing, dexterity, or more. Hell, like you say, even aging's enough to do it. Accessibility suddenly becomes a lot more important when you're on the other side of the "not a priority" talk.
And how does tailwind or the structure of the underlying html of the page change or affect that?
If Tailwind lends itself to using pixels instead of relative units for things that should be relative (like font-size, line-height, etc.), that's a problem. For those users, the HTML elements matter less unless they're savvy users who have custom user stylesheets to selectively adjust the appearance of content instead of changing everything on the page by zooming (e.g. make links, buttons, paragraphs, list items bigger and/or a different font or weight).
I mentioned blind but there’s lots of others. Folks sitting a desk whose eyesight are getting worse and are scared to say so for fear of losing their job, for example. This happens.
Side note: if you aren’t deliberately choosing semantic elements and instead dropping aria attributes onto a bunch of divs this is an anti-pattern.
if we get our first blind user I will gladly make some admends to make it more usable for them.
Not good enough. You have to be accessible before it is needed in order to avoid legal liability.
And how do you expect to get a blind user if they already cannot use your product?
None of the doctors I build web sites for are currently blind. I know this because I talk to them regularly. But I still build the web sites for the future, when HR might hire a doctor or nurse or other person who is blind, or partially sighted, or has trouble with their muscles, or has difficulty distinguishing colors.
Doing the right thing isn't that hard. Not doing it is just lazy.
You call it lazy. I call it "focus" or avoiding pre-mature optimization.
I find the "legal liability" claim hilarious... I do better than 95% of the web: as I said I HAVE some screen reader directives (just did not test it), and labels to make the app more accessible.
> You call it lazy. I call it "focus"
Is this to be read that disabled people and their needs, or more directly from the replied-to comment, "doing the right thing", are not a focus of yours, flossly?
A former coworker of mine opened a meeting saying "we are so good, we care about accessibility". I had been complaining for months and finally a customer had said "we won't buy your product unless it complies to the law".
I find the "legal liability" claim hilarious
You must have six million dollars laying around. Because that's the penalty Target paid for not having an accessible web site.
In 2008..
That wasn't even a regulatory penalty, but a class action by the National Federation of the blind.
https://en.wikipedia.org/wiki/National_Federation_of_the_Bli...
We use tailwind and are capable of building accessible websites without any issue. People could make all the same mistakes with CSS for accessibility. It’s the not knowing how to make accessible content that leads to inaccessible content, not the tool you use to implement the styling.
Sounds like you're kind of just talking your book though. Person who makes accessible sites suggests you need an accessible site. Blind people aren't the only ones who might need modifications. You could have an infinitely long list of adjustments for all kinds of disabilities, and tell me I'm lazy for not doing each of them. Why are blind people special?
You are lazy for not doing accessibility adjustments, because accessibility isn't for blind users. It's for the deaf ones, the ones with poor eyesight, the ones with mental deficiencies, the ones with motor issues like Parkinson's, the ones browsing your site shitfaced at 4AM, and so on and so on.
Accessibility isn't a checklist to cover your ass for a percentage of the population: it's for everyone. It literally makes your website less shit. You slapping an aria-label doesn't fix things.
Every moment you spend doing accessibility is a moment you spend not doing other things. You could argue it has a high RoI to do accessibility, fine, but that doesn't make it lazy _not_ to do it. Maybe I have even higher RoI/EV stuff to be doing.
> Maybe I have even higher RoI/EV stuff to be doing.
I mean, to readers of these comments, I think it's right there for you: 0x3f will take "higher ROI" over "accommodate and support disabled people".