by csnover | 2026-01-05 18:57:42+00:00
It used to be the case that a web developer could be reasonably expected to actually learn and know pretty much all of CSS, but it has reached the point where it is actually not possible for a single person to “learn” CSS in the way you could in the 2000s or 2010s.

Just as one example, there are now, by my count, at least eight[0] layout models (column, anchor, positioned, flow, float, table, flex, and grid), plus several things that sit in some ambiguous middle place (the inline versions of block types, sticky positioning, masonry grid layout, subgrid, `@container`, paged media), each of which is different and each of which interacts with the others in various confounding ways. Flow collapses margins; table elements can’t have margins at all, but tables can have `border-spacing`, which is like `gap`, but different. Flex has a different default `min-inline-size` than flow, and `flex-basis` overrides `inline-size` if it isn’t `auto`, which is its initial value, until you use the recommended `flex` shorthand, at which point it becomes `0%`, unless you redefine it explicitly. Table layout uses a special shrink-wrapping algorithm, which the CSS authors noted back in CSS 2 might make sense to add a way to work more like a regular block-level element, and then that just never happened. Grid is a mix of implicit and explicit placements with competing ways to do the same things (named areas, number ranges, templates on the parent, properties on the child) and a bunch of special sizing algorithm keywords like `minmax` and `fit-content` which only work in grid, some of which also work in flex, most of which don’t work in flow, but some of them do now, but they didn’t before.

You can select your elements with the old CSS 3 selectors, or `:where`, or `:is`, or `&`, or `:has` (but not if they’re nested), or `@scope`, or `@layer`. Definitely don’t try to put trailing commas on your selector lists, though, since that’s not syntactically valid in CSS, until it is, in some future revision.

To make sure your site works correctly with all scripts, all the directional keywords now have logical versions with `inline` and `block` keywords now. Unless it’s a transform[1]. Or a gradient[2]. That’ll probably eventually be fixed, just keep checking the spec periodically until you have to re-learn something that used to be false is now true. Which is how “learning” CSS works. There is never an end.

I haven’t even started on the explosion of CSS units, colours, the whole animation engine, forms, pseudo-classes, pseudo-elements, containment, paints, filter effects, environment variables (yes, those are a thing), maths functions, overflow, scroll snaps, backgrounds and borders, feature queries, font features, writing modes, the different-but-not-really CSS of SVG, the half-forgotten weirdo things like `border-image`, or the half-dozen other major and minor CSS features which I am not even thinking of right now.

CSS doesn’t suck “because we don’t bother learning it”. CSS sucks because its core strength is its core weakness. It is infinitely flexible and extensible, and that means it has been flexed and extended in impossibly large numbers of directions to fulfil every design trend and address every edge case. Then it needs to support all of those things for forever. Making CSS do what you want as a web developer has probably never been easier, but “learning” CSS has never been harder.

[0] Please, for my own sanity, resist the urge to pedantically nitpick in the responses about whether everything in my list is actually a “layout model”. I am aware that some of these things overlap more than others. This is just my list. You can make your own list. It’s fine.

[1] https://github.com/w3c/csswg-drafts/issues/1544

[2] https://github.com/w3c/csswg-drafts/issues/1724