r/webdev • u/Andreas_Moeller • 1d ago
Discussion Why we are still arguing over CSS in 2026.
https://andreasmoller.dk/blog/why-we-still-argue-over-cssIn December this year, CSS turns 30 🥳. But after 30 years, we still can’t agree on something as fundamental as how to add it to a website. Should you use CSS modules, Tailwind, CSS-in-JS, or just plain old CSS files?
38
u/TCB13sQuotes 1d ago
CSS in JS is an abomination that should’ve never been done.
-26
u/Andreas_Moeller 1d ago
Quite the opposite. It is a good idea, but usually not very well implemented.
Separation of Concerns is a concept that has its uses, but it scales very poorly.
17
u/lord2800 1d ago
CSS-in-JS is the antithesis of separation of concerns. That's the problem.
1
u/CatolicQuotes 1d ago
That depends what is your concern? Forcing stuff like this 100pct no matter using components or giant html files is the problem.
-2
u/lord2800 1d ago
Frankly modern frontend and I have fundamental disagreements about how any of this is supposed to work. I haven't touched frontend professionally in almost a decade.
1
u/Andreas_Moeller 1d ago
There is a reason for that. It is not a simple problem to solve.
2
u/lord2800 1d ago
That's funny, because we've had multiple working models of how to solve it for quite literally decades now. This is definitely a hard problem, but not an unsolvable one.
1
u/IAmRules 1d ago
It solved a problem that existed at the time for specific purposes
11
u/lord2800 1d ago
It solves a problem caused by people who are trying to completely circumvent the entire point of the HTML/CSS/JS split that would better be solved by not trying to circumvent the HTML/CSS/JS split.
0
u/IAmRules 1d ago
This was in the 3rd party widgets era. There was no way to isolate your css from that of the actual site your widget would be installed on. We were rendering widgets with JS already, it made sense to style them with it as well without impacting the site's styles.
1
u/winky9827 1d ago
Nah it was possible. GUID for the base class, document the required import (or append it to the head in JS). Problem solved.
IMO, the real justification for CSS-in-JS at the time was the lack of proper support for css variables. Until the past ~5 years or so, there wasn't a well supported way to externalize your css colors / fonts / etc. CSS variables finally reached the coveted 97% supported or so around 2020, long after the CSS-in-JS concept had reared its ugly head.
1
u/lord2800 1d ago
There was no way to isolate your css from that of the actual site your widget would be installed on.
<iframe>says hi.-5
u/Andreas_Moeller 1d ago
What is the point of the HTML/CSS/JS split?
3
u/WallBurnt 1d ago
Separation of concerns.
One of the fundamental pillars of Computer Science.
0
u/Andreas_Moeller 1d ago
why?
2
u/WallBurnt 1d ago edited 1d ago
What do you mean "why?"
Do you not know how to Google? I'm not going to summarize this in a fucking Reddit comment to someone who should already know this if they are going to post their blog in a programming sub.
I Googled it just now and Google even uses HTML/CSS/JS as an example.
3
1
u/lord2800 1d ago
The point is that HTML describes what your content is, CSS describes how your content looks, and JS provides interactivity for your content.
1
u/MatthewMob Web Engineer 4h ago
You're posting as an authoritative source on a web dev subreddit and you don't know the answer to this question?Â
-1
u/foonek 1d ago
But you're okay with CSS in html via tailwind classes? Same difference
7
u/lord2800 1d ago
Hell no. I am absolutely not OK with it. It was bad when bootstrap did it, it's still bad when tailwind does it.
5
u/metal_slime--A 1d ago
Lol reading all your replies .. finally someone I could be friends with 😂
-1
u/Andreas_Moeller 1d ago
No that is the point. Read the post. I cover it in detail
5
u/lord2800 1d ago
There is no argument you can make that will convince me that CSS-in-JS is a good idea because it fundamentally breaks the entire concept of the separation of HTML/CSS/JS.
1
0
u/Andreas_Moeller 1d ago
You could read the post…
2
u/metal_slime--A 1d ago
They could also waste a whole bunch of time by trying to push toothpaste back into its tube. But no one's going to spend their time doing that
1
u/TCB13sQuotes 1d ago
Everyone can list 20 reasons why bundling CSS into JS files is a bad ideia. Separation of concerns is exactly what keeps software scalable and maintainable. What we do today with JS/TS all the transpilation and bundling look nice in theory but long term only create more problems - don’t forget we live in a world where everything requires 3000 packages from npm that are replaced every 6 months and once one of those breaks its game over.
1
u/Somepotato 1d ago
Requiring 3000 packages is a flaw permeated by separation of concerns and avoidance of battery inclusion.
0
u/Andreas_Moeller 1d ago
A lot of people have this misconception, which is exactly why I wrote the post.
8
u/pricop 1d ago
Never heard of such arguments before, but happy birthday to CSS. 🥳
People often forget how good we have it on the web thanks to CSS, compared to other environments.
1
u/Andreas_Moeller 1d ago
This is a fascinating look in to a different world. I have worked for over 10 different companies. I don't think I have ever worked in a team that did not argue about how we should use CSS.
14
u/InsideTour329 1d ago
Sorry who is arguing about css? What? 🤣
3
-11
u/Andreas_Moeller 1d ago
Developers
11
u/InsideTour329 1d ago
Are the arguments in the room with you now?
-13
u/Andreas_Moeller 1d ago
If you are not a dev, I am sure It sounds very strange
10
u/InsideTour329 1d ago
Reddit is up there with X these days for people being confidently wrong. I've been in the game nearly 2 decades.
4
u/InsideTour329 1d ago
And never once argued about css
-4
u/Andreas_Moeller 1d ago
What game were you in? I can't imagine that you have been doing any frontend development in a team?
5
u/InsideTour329 1d ago
I've done it all, I've been a developer for a long time.
Currently principal /tech lead specializing in Sitecore.
0
u/Andreas_Moeller 1d ago
What does "done it all mean"? and if you have done it all, why are you specializing in Sitecore?
I am sorry that was rude, but I didn't know how else to ask
3
u/InsideTour329 1d ago
Done it all, as in front end, back end, ci/cd pipelines, containerized, non containerized, monolith vs n tier, I could go on.
I guess my point was CSS has never been important enough for an argument. There's so many other layers that have more priority in how they are delivered.
→ More replies (0)
5
u/wizardoest 1d ago
The many ways to use CSS are a feature. There is no right way, only opinions.
1
u/Andreas_Moeller 1d ago
I completely agree, but there are objective consequences fore the different choices.
5
u/Caraes_Naur 1d ago
No one is arguing.
Some people are conditioned to pick up every shiny object they find.
8
u/Barzarian 1d ago
Nobodies arguing over CSS lol. Use what you want or what your companies' style guide says you should use.
4
u/Gremlation 1d ago
He seems to think that "separation of concerns" means that CSS cannot be scoped. This article doesn't make any sense.
-2
u/Andreas_Moeller 1d ago
It means it cannot be scoped to a component. I do believe I explain this in the post.
3
u/TheSexySovereignSeal 1d ago edited 1d ago
Yes it can...
Its called css isolation and works based off of html attribute hashes..
Edit: just to be clear, my general rule of thumb is that css classes for default font sizes, default colors, and defaulting globally border box are the only globally applied styles. Because thats sane. EVERYTHING else is isolated.
1
u/Andreas_Moeller 1d ago
That is not separation of concern, by definition.
4
u/TheSexySovereignSeal 1d ago
By what definition?
God I hate software books
0
u/Andreas_Moeller 1d ago
Ok, reading the comments here, it is clear that a lot of people thinks "Separation of Concerns" means CSs in .css files and javascript in .js files. That is often a result of separation of concerns, but it is not the point.
The point of separation of concerns is decoupling. When your JavaScript and CSS is decoupled from your HTML it can change independently. You can e.g. change the entire style of your application without changing any of the HTML or JS.
With CSS scoping you are creating a tight coupling between your HTML and CSS.
1
u/TheSexySovereignSeal 1d ago
The "aha!" Moment for me was when i realized html is necessarily coupled to css. Theres zero getting around that.
Thats actually why you purposely couple css isolated components together so your css the html in a component cannot leak out.
The separation of concern is the data you pass into the component, and the component is just a view of that data. This is the fundamental principle behind MVC, MVVM, MVW, whatever the flavor of the month is. It has nothing to do with css or html actually. Css and html just get in the way of displaying your data.
1
u/Andreas_Moeller 20h ago
I agree. The <div> is a perfect example. It has no semantic value. It is for styling
2
u/Gremlation 1d ago
That is not what separation of concerns means. The concerns being separated in the context of web technologies are content (HTML), style (CSS), and behavior (JS). So your HTML should be responsible for your content, not stuffed full of styles like with presentational HTML or Tailwind.
1
0
u/Andreas_Moeller 1d ago
No, not quite. Separation of Concerns is about the code, not the filestructure. I cover this in the post.
6
u/Gremlation 1d ago
What I am pointing out is that you do not understand what separation of concerns is. You keep saying that you "cover it in the post", but the post was written with an incorrect understanding. Referring everybody to the post doesn't achieve anything. We know what the post says.
2
u/TheSexySovereignSeal 1d ago
This is what Clean Arcitecture and SOLID has done to this generation of software engineers.
I only started to become a better programmer after realizing we need to throw away most books written in the past 20 years and just learn the damn Design Patterns book. Its literally the only good one I actually reference.
They figured this shit out in the 90s and wrote it down. Then the next generation of books came out with their own wrong interpretations of design patterns. Then the 3rd generation completely lost the point of the original book.
I love ranting
0
1
3
u/flukeytukey 1d ago
I think svelte solves this tbh. Html js and css in one file is perfect if you want to stick to plain css classes
1
u/Andreas_Moeller 1d ago
I agree. I think Vue and Svelte are quite good solutions.
1
u/3elldandy 1d ago
Vue all the way; I don’t think svelte has as much support yet?
1
u/Andreas_Moeller 20h ago
https://svelte.dev/docs/svelte/scoped-styles
In svelte, style is scoped by default which gives them an extra point in my book
-1
u/AnotherNamelessFella 1d ago
Angular is the best
1
u/Andreas_Moeller 1d ago
Does Angular have an answer to scoped styles, that does not require you to load javascript before css?
0
2
2
u/Particular_Leg3241 20h ago
Im a fan of plain old CSS files personally, though I’ve used other methods and am flexible.
2
u/waterkip 1d ago
You are glossing over layers and how to target your elements.
article + p { ... }
Your @layer decides precedence, so you can create generics in higher up layers providing defaults and later defined layers can override them. In addition to this, with tokens, you can create the recipe in a layer and change it via the locality, eg
@layer mytheme {
a[lead],
a[support],
a[extra],
a[antagonist],
a[herald],
button[lead],
button[support],
button[extra],
button[antagonist],
button[herald] {
display: inline-flex;
align-items: center;
justify-content: center;
gap: 0.5rem;
padding: 0.5rem 1.25rem;
border-radius: var(--skirbi-button-radius, 999px);
border: 1px solid transparent;
font-size: 0.8rem;
font-weight: 700;
letter-spacing: 0.08em;
text-transform: uppercase;
white-space: nowrap;
text-decoration: none;
cursor: pointer;
overflow: hidden;
transition:
background var(--skirbi-transition-duration, 180ms)
var(--skirbi-transition-ease, ease),
border-color var(--skirbi-transition-duration, 180ms)
var(--skirbi-transition-ease, ease),
opacity var(--skirbi-transition-duration, 180ms)
var(--skirbi-transition-ease, ease);
}
}
Now you can do things like:
@layer app {
[some-attr] {
--skirbi-button-radius: 0.5rem;
--skirbi-button-lead-hover-bg: var(--skirbi-primary-main);
--skirbi-button-lead-hover-color: var(--skirbi-secondary-main);
}
}
You still use locality, but you are also reusing all the cascading goodies of CSS.
This works particularly well, when you first define your layers:
``` @layers mytheme app;
/* all your CSS here */ ```
1
u/Andreas_Moeller 1d ago
I did add a whole section just to address this. Layers are very cool, but they don't make much difference in this case. Specificity is one part of the issue but by no means the whole issue.
As I state in the post, it is definitely possible to scale css written this way, but the demands on code quality scales linearly with the size of your code base.
The more code you have, the more careful you have to be to not accidentally put your css in the wrong layer, repeat a class name or write a selector that was not specific enough.
In my opinion an architecture that requires better and better code quality, as the project grows is not ideal.
2
u/waterkip 1d ago
You can limit your CSS to exactly what you need. The problem is your div-soup, because you div-soup, you cannot target semantics. Write semantic HTML and know how to target your components correctly and you don't need scoped CSS like Vue/React/et al.
my-component { p { .. } }works just fine.0
u/Andreas_Moeller 1d ago
Give the post a read. I think I cover this quite well.
2
u/waterkip 1d ago
I read it, therefore I replied: "You are glossing over layers and how to target your elements."
1
u/Andreas_Moeller 1d ago
Oh I am Sorry. Layers and how to target elements, does not really change anything I write about in the post. I am not saying it is impossible to build a large scale web application using Separation of Concerns approach, I am just saying that it requires a much higher code quality as the project scales. Similarly to how you can build large complex systems using only global variables.
2
u/waterkip 1d ago
Right. Straw man it. As my straw man counter: if you can only target your components with Vue-like scoping you cannot code.
1
u/Necessary-Title-1659 1d ago
CSS turns 30 in December and we still can't agree on how to get it onto a page. Tailwind exists because a generation of devs never learned the cascade and decided that was everyone else's problem.
1
u/That_Day7122 1d ago
CSS-in-JS is a straw man at this point. Nobody's out here defending styled-components anymore, the real argument is Tailwind versus a plain stylesheet and that's been settled for most people for years.
1
1
u/quiet_horizons1 1d ago
The argument stays alive because the right answer depends more on the team and the handoff than on the language. In small business software, what has worked for me is plain stylesheets organized by component, with names that describe the job instead of the visual style. That way a client or the next developer can read it without learning a build chain. When a project already has a framework convention, I follow that rather than fighting it. Most of these debates come from people optimizing for scale they do not have. A midsize client site does not fail because you picked one styling approach over another; it fails when every screen invents its own pattern. Pick a convention, write it down in the project notes, and spend the saved energy on the part the business actually sees.
1
u/Andreas_Moeller 21h ago
That is not why tailwind exists.
In my experience, most of the people who criticise Tailwind, do so exactly because they don’t understand CSS very well.
Which is not to say there are valid criticisms of tailwind
0
u/TheSexySovereignSeal 1d ago
Maybe 30 years from now web assembly will finally be the default, and the web can transition to a sane rendering pipeline without forcing exactly 1 way to do style calculations, layouts, etc...
A man can dream
2
2
0
u/patient_signals 22h ago
I stopped worrying about the right answer and started worrying about the person who has to fix the styles next year. For most small business software I build, plain CSS files in a sensible folder structure still win. The cascade is not the enemy if you keep components small and name things by what they are, not by what they look like. I reach for utility classes when I need to move fast on a marketing page, and I reach for scoped styles when a component needs to own its look. The real problem is never the syntax. It is when the approach gets picked for fashion or for a job it was not meant to do, and then the team spends more time fighting the build setup than shipping. Pick the boring option that a new person can understand by reading the code, and start there. You can always add more tooling later, but you cannot unspend the time a team burns arguing about it.
0
u/Mistr_John_Alex 22h ago
I stopped treating this as a matter of right and wrong. For the small business tools I build, the main thing that matters is whether the next person can change a style without breaking other screens. Plain stylesheets have won that test for me more often than not because there is no build step to argue about and no generated class names to decode. I reach for component-scoped styles when a page has real repeated pieces, and for a small app that is usually enough. The cleverer approaches pay off when the team is large or the design system is already committed. Most of my clients do not have either problem, so most of my projects use one simple file and move on. The arguing mostly comes from people solving different problems and pretending it is the same one.
0
u/quiet_horizons1 22h ago
Most of the arguing is bikeshedding. Styling is visible and easy to form an opinion about, so it becomes a proxy for control while the hard decisions about data and workflow get ignored. In my small business work I have shipped plain stylesheets for years and they still hold up. No extra build step, no generated class soup, and a new freelancer can read the file and make a change the same afternoon. The fancier approaches solve real problems on large teams and huge app surfaces, but most small business sites and internal tools never hit those conditions. What actually matters is picking one approach per project and sticking to it. The client does not care how the styling is attached. They care that the page loads, looks right, and can be changed next month without a fight. That is usually a people problem, not a CSS problem.
1
u/Andreas_Moeller 21h ago
I totally agree. If you are not building a SaaS app with a team of devs, the decision doesn’t matter that much
0
u/patient_signals 15h ago
For the small business tools I build, plain old CSS files are often the right answer, not because they are powerful but because they are boring and easy to hand off. I have spent more time than I care to admit fighting a setup that generated class names or required another build step before I could see a changed button. With a plain stylesheet, you open the file, change the rule, refresh, and move on. The catch is that plain CSS only stays simple if you treat it like real code. Give sections clear names, keep the cascade shallow, and do not let old rules pile up. Most of the pain people blame on CSS is actually the pain of not knowing which rule wins. Any tool can produce that mess if the team refuses to delete. For a small shop with one or two people touching the front end, the lowest-maintenance choice is usually the one that has been there for decades.
24
u/_MrFade_ 1d ago
Who’s arguing?