Is CSS objectively bad?

stereobooster profile image stereobooster Originally published at stereobooster.com on ・3 min read

Typical discussion on CSS around the web looks like this:

A: CSS is hard
B: It's not hard. You need to learn it
C posts Meme about how family guy struggles to open blinds

Which is not a constructive conversation. So my question: is there a way to show what is objectively bad about CSS and maybe try to fix it? Stress in this question on objectivity, so it should not be a matter of taste or depend on how you define things, or how you used to do things.

In the article, I try to point out some objectively bad things. Please post your comments with more ideas.

Not analyzable statically

Developers use linters (for example, ESlint), type checkers (for example, TyoeScript, Flow) to automate improve code quality. This is generally not possible with CSS, because how rules applied depends on:

  • in which order CSS files included
  • on HTML structures e.g. depending on nesting different styles can be applied
  • different browsers have different built-in styles
  • !important

Note: the only way to solve it is to use “CSS reset” and use only atomic styles (e.g. unique class names, no nested styles)

Tricky learning curve

Okay, I said objectively bad and now I use the word “tricky”. Wait for it.

You start learning CSS with selectors and basic properties like color, font, etc. It seems like it is the easiest language in the world. And you can get pretty far with this knowledge.

But then at some point, you need to center something or pull element in flexbox to right and there is no property for it. How to do it? Most developers just search the internet on how to do it and copy-paste snippets from StackOverflow. Next time you need to touch this code and you find that if you change something in one place something else is broken in different. And you get in the circle of doom when you change things until it works.

Or you decide to learn why it doesn’t work the way you expect and you immediately need to learn so many concepts to fix one small thing, like what is box model, how layout algorithm works, etc. All those implementation details are failing on you at once and this is just too much…

This is what I call a tricky learning curve. It becomes a wall at some point.

(It’s up to you to decide if this point is objective or not)

No debug tools

For a long time the only debug tool was:

* {
 border: 1px solid red;

At the moment there are a lot of great tools implemented by browser vendors, for example:

So things improved, but my point is those improvements come from browser vendors, they are not in CSS spec (or is it and I missed it?). People who designed CSS are never bothered about how it is gonna be debugged.

See also

Posted on by:

stereobooster profile



Hello, I'm a full stack web developer. Follow me on Twitter!


markdown guide

As much as I like CSS (and will continue to), you make very good points! Objectively speaking, it's not well-designed.

To quote Python creator Guido van Rossum:

If you find users are consistently confused by something, that's an opportunity for improving the language. Don't fall into the trap of thinking "oh, we need to document that better"!


Somehow I'm not confused by these things you guys claim to be confused about.


It's quite possible to get used to. Note that I never said I was confused about anything in it. But CSS making sense to you...or me...doesn't make it a well-designed language. Many developers are frequently confused by CSS, and it's certainly not easy to debug.

In design, one has to be careful not to confuse "it makes sense to me" with "it's well-designed".

Beginners are always confused by things at the beginning. If the issue is devtools, that's a separate thing from "the language is not well designed.

I didn't say beginners, either. ;)


This is the point of the article I'm not pointing out parts which are "confusing", which can be matter of subjectivity. I point out facts. CSS is not statically analysable. The only way to analyse it is at runtime e.g. having CSS applied to HTML.


I can’t help but think of the classical dev quote “the users are not using it right”.

User stories should apply to developer tools too! :)


First, I commend your attempt to seek objectivity in the matter.

The primary problem though is that the aspects of the language that are objectively bad are those which (a) cause real problems and (b) can't be fixed.

For example, from the "Incomplete List of Mistakes in the Design of CSS", there's the point that because comments can go anywhere, there's no way to represent them in the CSS Object Model. Because any definition of CSS must always work with the way CSS is used in the extant web, there's no way now to limit the location of comments.

But let's take the Tricky Learning Curve. I would contend that in any language, transitioning from script monkey to programmer is hard, which is what you are essentially describing. The remarkable thing is just how far CSS can take you in script monkey mode.

CSS is hard, such as it is, not least because layout is hard. Back in the mid-1990s, around the time that CSS was being born, I was trying to teach myself Java Swing layouts. The layout modes were undoubtedly clever, but I couldn't at that time understand why I couldn't or shouldn't just put each block at position x, y with fixed dimensions. And that was generally into an fixed 2D area. CSS layouts must contend with laying out on to a canvas that theoretically stretches from minus infinity to plus infinity in three dimensions.

We generally don't get a solid grounding in layouts. What are the problems that have to be solved, and what are the issues that potential solutions have in meeting those problems. All we have is a bunch of rules that we try to apply to get the look we want.

Learning those rules could certainly be easier, if our learning resources were better. The problem is that we start with a specification that's written for the benefit of browser makers. There's nothing wrong in that per se, but it doesn't make for something that web page authors can easily learn from. For one thing, a feature that might be very important for understanding an aspect of CSS, might not have many implementation requirements, and therefore only merit a few lines in the specification. Whereas a tutorial would ideally provide innumerable examples to hammer home the point.

For instance, take the Box Model. I often feel that the many descriptions of it, here on DEV and elsewhere, miss the point somewhat, because of the way the specification is structured. The opening paragraph of section 8 (Box Model) of the CSS 2.2 spec says:

"The CSS box model describes the rectangular boxes that are generated for elements in the document tree and laid out according to the visual formatting model."

The section then goes on to describe in great detail the dimensions of the rectangles, and the point that the box model is about the generation of boxes and how those boxes relate to one another is lost.

Guides and tutorials are by necessity less rigorous than specifications, but in the lack of rigour important points can often get lost, leading to frustration when things don't work the way you'd expect. MDN does a decent job of walking this tightrope, but inevitably can't catch everything. Other sources are far, far worse. One of the most common sources for learners in W3Schools, and the quality there leaves a lot to be desired. To this day, its description of what vertical-align:middle does is not just plain wrong, but not even close. This for a behaviour that almost every learner wants to understand, and has been present unchanged in CSS for more than two decades.

So these are the limitations in which we must work within when assessing whether CSS is objectively bad. CSS is built on the sandy base that HTML gave it, and I remain in awe of Håkon Wium Lie, Bert Bos, Elika J. Etemad (fantasai), Tab Atkins and the many others who, from that, built and continue to develop something sane, and that in truth has been wildly successful. And that's the key measure for me. For all its flaws, it's used successfully by millions of people, and that can't be bad.


For all its flaws, it's used successfully by millions of people, and that can't be bad.

Based on this logic I can produce list of things that can't be bad:

  • JavaScript (type coercions, prototypical inheritance, null and undefined, this)
  • C (manual memory management)
  • Java (easily eats all memory)
  • etc.

Maybe they are used not because they are good, but because of Lindy effect?

And there are a lot of new languages and a lot of new research. But CSS and JavaScript have monopoly over the web, that is why they still there. Lets wait till we get WASM


On the second thought (I haven't realized this before). I tried to find objective proof for a subjective matter. Categories like "good" and "bad" are subjective. For example, there are no good and bad things in math - negative numbers are bad and positive are good - nope.

What I meant to say is: what are design decisions in the language that leads to a lot of confusion and frustration. And do we have objective arguments for it?


I think that's definitely a better question, and you may want to take that to a new post. Even so, it might still be tricky to find objective reasons for what causes confusion in humans. But maybe you could look at the jumble of features wrapped up in the display and white-space properties, the seeming arbitrariness of which boxes form stacking contexts, the unique way text-decoration propagates to descendants, and so on.

Even so, it might still be tricky to find objective reasons for what causes confusion in humans

Well, this would bring us nowhere. People complained about manual memory allocation in C and now we have garbage collection (Go, Lisp, Ponylang, etc.), borrow checker (Rust), and whatever magic Zig is doing. Pointing out problems leads to a solution.


Layout is tricky, I find it really hard to make a judgement without any language comparisons. :/

We could look at how well I does what it is designed for, but then we need to define some stories first.

You come close with some examples, but I would love to see some formatted as, “when as z I do x I expect y”.

I totally agree that the language suffers from horizontal growth problems similar to JS.

That is, there are too many hyper specific features, making it likely that as devs we will not always use the best tool for the job.


Layout is tricky, I find it really hard to make a judgement without any language comparisons. :/

You can compare it to flutter or subformapp.


Nice, thanks, i will give these a look.
Giving them a quick initial look, i'm not sure they fill the same stories as CSS.

Which stories would you say they share with CSS?
Besides the obvious one being "as a developer i want to use a tool/text to define layouts".

Edit: Edited the story wording a bit

Flutter from my PoV has the same scope as CSS. They implemented material design in Flutter, for example.

(Not sure I fully understand the question)

I'm trying to establish if these are comparable by using UX theory on libraries/languages to see if the use-cases match.

It might be subject for a longer investigation, so lets leave it there for now.
Anyhows thanks again, these are good food for thought. :)


CSS is solving the very hard problem of layout on an unknown canvas while also failing gracefully so that the content, which is the important thing, is not obscured by some error in the styling. You can off course mess up bad enough that this is not true, but the design is made so that you should be able to remove or add layers of CSS and still be able to read the content. A lot of clients will add it's own styles and remove styles that the author wrote. It's more free form and less mandatory than other languages.

It sure has it's quirks, but I think that it's pretty much a miracle that it exists and works as well as it does, all considered.


CSS is solving the very hard problem of layout on an unknown canvas

It sounds like nobody else is solving this problem. There are flutter and subformapp, for example. This is the result of a quick search, I guess, I can find even more examples.


You took one phrase out of a sentence and commented on it out of context. Sorry, but your reply does not relate to the statement I made.

I didn't mean it to come as offence or something. I just point out, that there are other systems doing similar task... Sometimes it seems like we treat CSS as some holy grail. It is so precious, nobody suppose to say bad word about it, because it solves so hard problem. Indeed it is hard problem, but this doesn't mean we can't do better. Right?

I did not mean to come off as though I took offence. And I take your point. It's just that the part that styling for many different screens is not part of the reason CSS behaves differently. It's the other stuff I mentioned that makes it hard to compare with other solutions. Flutter is compiled and can know the environment in which it's run completely, for instance.

Just wanted to add to the conversation that an enormous amount of stake holders have come together on a standard and that it might be easier to make improvements to it than to replace it.


My biggest gripe with CSS is that it’s designed as a Markup and not a programming language.
This works good for static webpages, but not the dynamic web applications we have today.
The lack of programmability means that’s some concepts are incredibly awkward to express.
I also don’t lock CSS lack of types. Everything being a box is to simplistic in my opinion.
My last big problem with CSS is the cascading nature. Sure it makes CSS easy to parse but other than that it’s just awful.
As for alternatives I really like Flutters widget approach.
It seems much less complicated and delivers more predictable results.


Side note: CSS is a programming language. It is declarative programming language, which makes it out stand from other PLs. I guess you meant to say lack of imperativeness, instead of "the lack of programmability".

Everything being a box is to simplistic in my opinion.

But this what Flutter layout engine does as well, isn't it? Everything is a box with min, max width and heights, but without position.


It’s not about imperativeness.
As far as I know CSS isn’t even Turing complete nor is it isomorphic to a lambda calculus.
But technicalities aside, CSS is incredibly bad at being a declarative language.
Look at the expressiveness functional languages like Elm or Haskell provide and compare that to how incredibly awkward it is to express even simple things in CSS.
In short it’s designed as a markup language not a PL.

Yes internally Flutter uses a box model that is very similar to CSS, but you rarely interact with it directly.
Instead you usually use typed widgets, e.g. a Padding widgets applies padding and an Alignment widget aligns it’s child.
In CSS on the other hand every property can be set on every selector.
For me that’s quite overwhelming.

As far as I know CSS isn’t even Turing complete nor is it isomorphic to a lambda calculus.

You make it sound as if Turing completeness has something to do with language being programming or not. I don't think this is the case. Typed lambda calculus is not Turing complete. Brainfuck is Turing complete, yet I don't think this is example of good programming language. Actor model can go beyond of what Turing machine can do. There is nothing specific in Turing completeness in terms of modern development (yet this is very important discovery for computer science and logic systems, the same way as Godel incompleteness)

But technicalities aside, CSS is incredibly bad at being a declarative language

The problem here is that term declarative is overloaded and not clearly defined. Where is I mean declarative is when you describe what you want, rather how to achieve it. You refer to pure functional languages as declarative, because in pure declarative languages order of evaluation doesn't matter. Which is fair point, there is no clear definition of this term.

I meant "Descriptive declarative programming" according to this classification.

I feel like our discussion has drifted a bit too much into discussing definitions.

Set aside by what definition CSS is a PL or isn't I want to get back to strengthen my argument that CSS is a bad language in a different way.
Rather than looking at the language in isolation I want to look at how it's used and what that tells use about flaws in its design.
In recent years CSS in JavaScript has gained lots of traction despite its obvious drawbacks.
I think the fact that many people choose to rather write CSS generators than CSS is a strong indication that the language is not expressive enough.


CSS is awesome. Someone who tells you otherwise is probably part of the SPA hive.


Tell them. Most probably those c, java devs that can't just accept that Web dev is different from what they're used to. They should really stop hating on css and go learn it properly.


well how did you learn it properly?


I hate Poe's law. Tell me this thread is a sarcasm.


The biggest problem people have with CSS is that it's not strictly coupled with HTML. There's no contract saying that inside a div with class foo you're allowed to present a p tag but never an a tag. This isn't XHTML and there's no DTD here.

And there's no way to brute-force test every permutation. So QA are going to keep finding bugs, because they'll order the round of -99 beers at the bar.

It's not solved by making bigger and bigger frameworks which require you to restructure your HTML and to add more and more divs and classes into the soup.

It's not solved by splitting everything into components and adding your styles with Javascript, because while with one eye that looks like a reasonable separation, the other eye sees the mountain of change requests queued up in your future.

It is partially solved by sticking to semantic markup. It is partially solved by having a universal styleguide, and having your designers in on the deal, where they can make things consistent.

True story: once I built a site used by ~400k people where the designers made each page different - blue heading, all caps on white on one page, lowercase white on blue on the next, that sort of thing. They kept within their palette and so on but that was about it. I asked them why and they replied that they didn't want the site to look like it was using a CMS.

Objectively bad bits:

  • no DTD
  • Forcing manual or snapshot-comparison testing
  • HTML is a document, with flow, not a window manager - everything relates to everything else

I'd put the problems of things like box-sizing right at the bottom of the list.


The biggest problem people have with CSS is that it's not strictly coupled with HTML. There's no contract saying that inside a div with class foo you're allowed to present a p tag but never an a tag. This isn't XHTML and there's no DTD here.

I like your direction of thought. But at the same time, from layout/paint engine point of view, this is a bunch of rectangles to draw... The problem from my point of view is "global-ness" of CSS selectors (by tag name, nested selectors, specificity, inherited/not inherited properties).


With typical programming languages, there's good code and bad code (and a lot in-between). The difference mainly has to do with maintainability, which in turn largely comes down to this: if I need to make a small and specific change in a small and specific part of my code, can I be confident enough that it will not have unintended side-effects, without me first needing to go though all the code to try to figure that out?

With CSS, you don't have that guarantee even with good code, since lots of pieces push and pull at lots of others, as part of the (implicit) spec.


I guess this is due to globalness of specifiers. Imagine programming language in which every variable is global and mutable. Plus some properties inherited. Plus side effects from layout change.


Yes, the globalness is indeed an issue, but one that can be navigated to a degree. I was mostly referring to the ease with which you get layout side effects, e.g. adding a border to a top bar or changing its inner padding screws up the rest of the page, etc.

If you know enough about CSS, these things can also be worked around, but it makes the learning curve very very steep compared to most other programming languages (in the general sense), which is at odds with the straightforwardness of its purpose (i.e. defining layout).


I've always been very annoyed by the inconsistent naming of properties, for example:

Ah I want to make the background a color, okay that's fine, use background-color. Okay done! Now the text as well, I can just use text-color right? Ehh.... No.... that's....color. Just color.

I think there is just a lot of legacy still around and it hasn't been deprecated for some reason. They should really rectify this issue in CSS 4, just give everything a consistent name.


I just came here to write one thing: YES.