Comment by ktpsns
12 days ago
CSS in 2025: Let's write html inlined styles as if it was 2005 and separation of formatting/representation was never invented. I talk of tailwind, of course.
12 days ago
CSS in 2025: Let's write html inlined styles as if it was 2005 and separation of formatting/representation was never invented. I talk of tailwind, of course.
The deadest horse in web development is the myth of “separation of concerns”
I was recently doing some very specific web scraping of some very public very static documents. About 25% of them use a soup of divs with hashes for class names. Not a <main> or <article> or <section> in sight. I am fine with the idea of what tailwind does but like at least using semantic tags where appropriate could be a thing.
There's also the issue that whatwg pretty much stopped adding new semantic elements; if I'm not mistaken, only <search> and <dialog> were added in the last decade, after the introduction of HTML5. <main>, <section> and <article> are increasingly being overloaded to the point of meaninglessness.
The most cited example of one that's clearly missing is <comment> for user-added content, but there are probably dozens we could add that could help deal with the div soup. By not adding any new elements, whatwg is essentially saying "You're not going to be able to use these the existing tags to fully add proper semantics anyway, so why try?"
You can grumble at web developers in general for things like div soup, but the hostility towards tailwind is misplaced. Hashed classes aren’t even tailwind, and the tools that generate them are not the problem either.
That's totally orthogonal to Tailwind though; there's nothing that precludes you from combining semantic elements with it. The only thing that would make a dev reach for <div class="m-2"> instead of <article class="m-2"> is the dev's own (lack of) taste. It's no different than writing out separate CSS or using inline styles.
I do sympathise as someone who has to scrape content from time to time, but that doesn't sound like a problem for the author of the content or something that impacts their intended user.
3 replies →
I'll add that writing userscripts became more challenging b/c of this phenomenon.
I'm pretty sure unreadable class names are a byproduct, but perhaps some people may also consider it a feature, of their particular build process.
so they may very well have semantic tags in their development environment. Of course debugging things becomes more difficult for the developer as well unless there is some sort of lookup table to tell them that class .uv.le in the browser maps to .user.name in their codebase, in which case it only becomes marginally slower for some cases.
Not defending it, but this is most likely a cause of using some enterprise CMS like Adobe AEM which is notorious for doing stuff like this.
Its not right, but a lot of times CMS's are horrifically bad at adding content without a slew of nested, auto-generated <div>'s.
Wait until sites start rendering to canvas. You will yearn for the days of div soup.
4 replies →
Tbh there's nothing really wrong with that. You don't need stuff like article or section if you set the right attributes. Often easier to just use divs to get the structure right, and figure out the meaning later.
10 replies →
It's a choice. The dominant paradigms choose not to.
I disagree. And that makes me the loser here
I agree, it’s a choice. So is the opposite. Complaining about other people’s choice of doing things on the web is the choice I’m actually tired of.
3 replies →
Another loser here to second you
2 replies →
I don't think "separation of concerns" is entirely dead. Ideally, the CSS is readable and maintainable, and that implies structure. If you have a bunch of (co-)related components, you don't want to find/replace tailwind class names when you need to change the layout. So you separate that part of the layout in classes based on (layout!) functionality. You can see that as "concerns."
Components are the tool you’re looking for. For the rest there’s CSS variables. Soon we may have @mixin.
I don't use Tailwind, it's a solution to a problem I don't have.
I can understand how it might be useful for certain types of web development, e.g. landing pages where the content and styles are tightly coupled.
So as a technology, it's OK. But my god its userbase is toxic and obnoxious.
Okay. I personally don’t care for anyone so chronically online that they think that their interactions with other similarly chronically online people is at all representative of the userbase of something as immensely widely used as Tailwind.
Whatever the professional equivalent of ‘touching grass’ is, I suggest you do that at your earliest convenience.
What an absurdly absolutist statement.
The majority of its userbase is no longer made of humans though.
You can separate concerns without violating locality of behavior, and that’s exactly what tailwind does.
It admittedly does not do a good job at being very DRY but I think that’s poorly applied to HTML/CSS in general, and the most DRY css is often over abstracted to the point of becoming nigh uninterpretable.
When I write CSS, I most often do not want the locality of behavior. I instead want uniformity of behavior, hence "semantic" styles. Even the trivial light / dark mode switching is pain with Tailwind, when classes like "color-gray-200" are routinely applied.
3 replies →
I can't believe this isnt better understood. Style definitions on reusable components are good. The idea that your css doesn't have to know about your html just creates tons of problems and complexity. Global themes and reusable styled are fine.
If we are talking about statically defined html then sure. make your global css files.
SoC is how all maintainable software is built. A function for A, a class for B, DDD-spec'd modules and features, databases on separate machines, API definitions, queuing systems, event systems, load balancing, web servers.
You don't even need to think of the web to see how content and presentation are different. Try editing a text file with hard line breaks in and you'll quickly understand how presentation and content are orthogonal.
Please don’t be so condescending. We all know what separation of concerns is.
The comment said “web development”, and it’s inarguably that in the history of web development there have been at least a couple of major misapplications of separation of concerns, which have had practically everlasting negative consequences.
Read what you’re replying to before you reply to it.
HTML vs. CSS is a separation of technologies. If HTML was really only about the content and the CSS was only about styling, we wouldn't have to write div soups to style our websites (.container-wrapper .container .container-inner { /* "separation" */ }) and we wouldn't have to adjust our HTML when we change the layout.
> we wouldn't have to adjust our HTML when we change the layout.
You don't have to: https://csszengarden.com/
Fine for a static site which is frozen at the first version forever.
So, so, painful for apps which need to change and evolve over time, which I'm currently experiencing. It's too easy to break the bits where you needed to get clever to make a layout variant work.
I did also did a Zen Garden on YouTube recently when they removed the list view option from Subscriptions, restyling their grid markup was a fun CSS exercise.
But for that designers should care about the limitations. But they don’t care. Not even about the more basic ones. I’m quite sure many of them don’t even know. Mainly, because their customers are not the one who code.
I got many designs for websites where customers told me that they want a pixel perfect version. The funniest one was when my boss who supposed to be a “senior” web developer told me this. Of course, there is no such thing on the web or really anywhere. Actually, I’ve never seen a design plan in which wildly different aspect ratios and sizes were really considered.
2 replies →
And if you read the CSS there, it's an unmaintainable mess of absolutely positioned elements
CSS Zen Garden is quite the opposite of a good example of your point. Even small changes to the original page layout would completely break most of the provided styles.
If I removed the .page-wrapper class it would be also nearly impossible for a different developer to reverse-engineer the issue from the existing Template and CSS files.
2 replies →
I find that most div soup is going away with CSS Grid. CSS Grid is often best when you lose wrappers and nesting. subgrid and display: contents help pop layers when you can't touch the HTML nesting, but now a lot of nesting feels unnecessary in the first place.
We only have to write div soups to style our websites, because people keep misuing a platform for interactive documents for an OS abstraction.
Having worked on teams that wrote bad (S)CSS and teams that wrote bad tailwind, I prefer bad tailwind.
With tailwind, I can guarantee that changing a style in one component will only change that component. With css, there is no such guarantee. So of course the (wrong) way many devs fix it that is to add a new class, probably doubly specific, sometimes with important, and then everyone is sad.
That’s separation of technology not concerns. The concern is the component itself.
Well put.
Are we still complaining about Tailwind? This ship has sailed. The world is so much better than the old BEM/LESS hell, it is wonderful. UnoCSS is even greater in empowering frontend developers.
BEM is actually not hell, since the whole point is to have classes with a specificity of 1, making precedence of CSS rules easy to figure out.
Non-BEM CSS with ids and multi-classes everywhere was hell.
Agreed. I owe a beer to whoever thought of BEM. It's saved precious brain cycles thinking of names. At first I was like what is this bem__opinion--rubbish but then it clicked and my workflow improved.
Yeah let's do that. You have everything related to your component on place instead of jumping between files.
Vue, Svelte, and Surface manage to do this without forcing you to inline all your styles
Jumping up and down in the file is not much better and you still need to come up with names for classes. I want to look at an element and immediately know how it's styled.
5 replies →
I worked with both. Scoped styles are nice. Tailwind is better - no naming of every element, no mental tax of jumping around in the file -
What stops you from doing the same thing in CSS? It is trivial to assign a specific CSS class to an element that is the root node of a "component" and scope rules under that.
Is jumping between files supposed to be difficult or something?
Colocation is a useful principle in component-based architecture.
6 replies →
Without a lot of discipline it is very easy to end up with a css with lots of unclear and hard to guess effects. Eg consider the case of <A type=1><B><A type=2></A></B></A> where A and B are complex templates. Any selector with the " " operator on A risk expanding to the inner A even if it was intended only for the outer. Similarly a :has selector might catch a descendant of the wrong element.
@scope fixes a lot of this, but it is a complex problem. With tailwind you mostly have to worry about inheritance
3 replies →
I find it to be more difficult. Especially if I can't pane the files in view comfortably (ie. beyond 2 or 3 it gets significantly harder to work across them).
Some frameworks or coding styles really lean into having lots of tiny files. That necessitates a more complicated directory structure for the project. Locating files eventually tends to requires search capability rather than being able to look through the tree in a sidebar.
None of this is "hard" per se but I find the opposite is nicer to work with typically.
Yes.
The problem is that the styles for something can be defined in multiple places, and that makes it hard. Especially with CSS and (potentially) having specificity issues if things aren't managed well. Having them as a part of the component means that problem goes away.
Is staying in one file supposed to be difficult or something?
8 replies →
You can literally command click a class to go into a styled components css file. I do not understand what the big issue is.
6 replies →
Also modern CSS is often written in a <style> tag either in a native web component or in a framework which supports single file component like vue or svelte.
I do not work frontend and yet, I always end up having to do some CSS here and there.
I have never been happy on how I manage CSS. With tailwind, I am still unhappy about my styles but I can make my ugly UIs faster.
Yeah. There is no need to obfuscate your code, just use Tailwind.
Obfuscate? I can learn tailwind and use it in dozens of projects. I can use tailwind in my project and onboard dozens of developers immediately. I can learn your CSS conventions and use them in exactly one project.
Why can you use CSS conventions in only one project?
4 replies →
If everything in your code is a React component, I get why you would just want to write the styles right there.[0] Then again, why write `<Button>` if you could just write `<button>` and style it with standard CSS.
[0]: https://mastrojs.github.io/blog/2025-11-27-why-not-just-use-...
> If everything in your code is a React component, I get why you would just want to write the styles right there.
Even for keeping the style close to the component, you can just use standard css.
Create a folder Button, create two files Button.tsx and Button.css in that folder, import the css file in the tsx file, add a class "button" on the first element the tsx file renders, start all the rules in the css file with ".button " to encapsulate the style.
People will say it's too much work, but it took me like 5 sec.
if you're not using CSS modules, why would you import the css file into your javascript? But anyway, I think we agree. Feel free to read the linked blog post ;-)
1 reply →
Because button is literally anything clickable. Not everything is a boxed button. You cannot just globally add a style to <buttton> and call it a day. For example, an upvote (^) button, a close (x) button, etc. A lot of clickable elements aren’t inside a [click me] box
button, .button { /* my button styles */ }
What if you need 3 levels of html tags?
Tailwind is not what you're describing.
Isn’t that what utility classes are? Shorthand for inline styles?
Not saying it’s good/bad, but it feels like that’s the use case
It's much more than that because it can make use of CSS pseudo selectors like hover, which is not possible with inline styles.
Under that definition any css class is a shorthand for inline styles
1 reply →
Media queries, pseudo selectors, extensible design system with sensible and practical defaults, and many more
Tailwind is a direct response to how the "C" in "CSS" actually sucks, so there's no surprise that it's so popular.
The "C" (Cascade) in CSS doesn't suck, the education about it sucks.
People don't know how it works, then things go wrong so they learn to work around it.
That's what led to things like div + class soup that you get with the BEM naming convention or Tailwind.
The cascade is actually awesome, super powerful and if you know how to use it, it can greatly simplify your code.
Education is the problem and the solution.
---
To anyone outside the CSS space, this is the closest analogy I can find:
In the American education system, there was a recent-ish change where children are "taught" to read using a method of just learning the shape of every word (e.g. "thermally" has a th at the start and ly at the end, so it must be the word "thermally", despite other similar looking words like thematically).
The method was disproven but the American education system still uses it.
Now illiteracy rates are climbing where almost 1/4 Americans (USA) can't read.
It's basically the same thing with CSS, where developers don't know what the code they're reading/writing is actually going to do.
It has nothing to do with education, software development is not learnt in a centralized way so you could hardly claim anything based on that.
Cascading simply fails to scale/work with web applications, especially when multiple people work in parallel.
HTML both describes content AND layout, so you simply can't separate the two. This was a nice dream when the internet was "markdown encoded in html", but the moment you write a nested <div> for layout purposes you lost. So HTML has to be written together with CSS, so we get no separation. Now what is it that you could meaningfully cascade? (If anything, variables are all that we needed)
Add to it that people are using third-party components as well, and now many "widgets" starts by resetting outside styling rules.
What do you think is lacking from CSS education?
I don't think anyone in this thread is arguing that inheritance or specificity is hard to understand.
My issue with cascading style sheets is mainly that namespace pollution (as every selector is defined in the same global namespace) means that short selectors (.separator, .highlight, .button) are likely to collide with completely unrelated parts of the application. BEM and tailwind are popular because they localize styles to specific components, preventing namespace issues. Today, most web frameworks deal with components, so it makes a lot of sense to localize the styles to the components. Scoped css in vue/svelte allows you to write short selectors, and have them only apply to the component they are written in, without needing to prefix them with a component name.
Reading word shapes comes from a place of good, studied intent. Reading word shapes is how people who read quickly read. It is in many ways an advanced way of reading. Trying to jump to it was a hope that you could shortcut some of the literacy curve. Unfortunately, trying and sometimes failing to read word shapes is also how some neurodivergent brains work naturally (the family of dyslexias as the big complex elephant in the room). If your brain jumps directly to word shape, and somewhat often gets it wrong, being forced to slow down, break words apart and start from smaller basic building blocks can be helpful.
It's a reminder that different people learn at different paces.
I think overall the additional details expand and perhaps better the metaphor: a lot of people want to jump directly to the advanced CSS stuff and skip the fundamentals. For some people that works and may be a shortcut. Other people need to spend more time breaking their teeth on the fundamentals, getting them wrong, learning from their mistakes, and getting rock solid on the slower building blocks before trying to do anything advanced.
Instead of assuming that everyone who has a different preference than you is ignorant, it might be helpful to look at the problems that each technology solves and the requirements they fulfill.
The cascade is a huge issue for teams need to be able to safely modify one area of a site without accidentally impacting others. Tailwind solves organizational problems by colocating the styles with the elements - allowing changes to be surgical, declarative, and predictable. Editing and removing styles is as easy as modifying the content of the page.
Yes, the cascade is super powerful, but it needs to be contained somewhat to scale to many developers and large codebases.
> 1/4 Americans (USA) can't read
Also even though your analogy has nothing to do with CSS, I have to point out that this absolutely isn't true (which in the context of your argument about education is pretty ironic)
> That's what led to things like div + class soup that you get with the BEM naming convention or Tailwind.
You could try and think why people end up with BEM or Tailwind. And the answer isn't "because people are not educated about cascade". Both BEM and Tailwind came form people who are very much aware of the cascade.
The problem is that cascade is very much a hindrance in quite a few cases. Especially when you deal with components and design systems.
> To anyone outside the CSS space, this is the closest analogy I can find
All analogies are bullshit.
The truth is that CSS is designed for documents, and for a few decades people have been trying to use it to design/build components: https://x.com/simonswiss/status/1664736786671869952 Cascade is good for the former, and is death for the latter.
And browser vendors have been surprisingly stubborn when it comes to making any improvements to the DX in this area. That's why instead of locally scoped CSS, CSS nesting, CSS mixins (and a bunch of other improvements from SASS and various JS Frameworks) we first got 15 000 JS-only specs around web components, of which 14 999 can be covered by improvements to CSS.
> where developers don't know what the code they're reading/writing is actually going to do.
Lol. Tailwind has made people more aware of what CSS does, with better documentation, than decades of bullshit articles and millions of words of existing docs.
I call it cargo cult developing. People develop bags of spells and tricks that they attempt to apply to a situation to solve a problem. Usually they can arrive at a solution by trying a number of these incantations, but not always. And never actually ask them what the incantation does
It's not just css either. At a job I've worked, we had a VPN client that would get into a weird state, where it needed to be killed to restart. An incantation that made use of ps, grep, awk, and xargs was provided, instead of just using pkill
I mean, the cascade really doesn't suck though does it. You really want to set font families and sizes on every p tag?
It really depends on the websites no?
If you're building a "webapp" where you think in terms of components, no point keeping the style sheet separate..
If you're building a "website" which is basically a list of hyperlinked documents with the same styling, having just one style sheet would make sense...
Of course, there's a lot of gray area in between the two...
At the end of the day, the most that most of us can really do is be annoyed at the quirks of these leaky abstractions in the large codebases that's thrust upon us.
If I may be so bold, the coding agents are really good at this stuff. Save yourself the pain of front end and make a clanker do it. Or at least make the clanker to the heavy lifting and just do tweaks yourself.
Yeah and it's a really good idea. You can't really 'separate layout from style.' The layout and the style are both parts of the UI. HTML isn't the content, it's the layout.
Even if you believe separation of concerns is the eleventh commandment, HTML and CSS are the same kind of 'concern' anyway. They're both at representation layer. Pretending you can decouple them is just burying the head in the sand.
Thank you. This just makes sense. In fact, seperating them into different files don't make much sense when you think about it.
Wait until you see React & JSX...
At least html and CSS are both presentation. React/JSX now confuses presentation and business logic.
> React/JSX now confuses presentation and business logic
React was originally designed to be the "V in MVC". You can still use it that way. React becomes very simple when you only use it as the V in MVC.
> React was originally designed to be the "V in MVC"
React was originally desingned to be php in the browser.
php5 -> HHVM -> Hack -> XHP -> JSX
1 reply →
What are the M and the C, and how do they talk to the V in this case?
17 replies →
I think you're confusing business logic with view logic.
React is great for MVVM indeed. Who is still using MVC in 2026?
MVVM was invented by Microsoft for 2-way syncing in WPF. Today we know 2-way syncing is a mistake.
Who uses MVC in 2026? Pretty much every framework out there, including Java frameworks and Python frameworks and .net
7 replies →
Adding to sibling comments, Phoenix. And it’s a damn nice experience at that.
Ever heard of Django? ASP.NET? Most UI frameworks, including ASP.NET Core, Spring Boot (Java based framework), Ruby on Rails, and Django (Python) are all based on MVC.
6 replies →
Separation of formatting/representation was invented? Where was I?
And thank god (or Adam) for that. Tailwind makes me much more productive.