It's nice to read some positive content about CSS. I personally love CSS.
I see CSS as a massive toolbox full of awesome tools, some old, some new, some I use all the time, others I barely know they exist, but it's nice they are there when I need them.
It also has improved significantly over the years, it's quite remarkable; transforms, transitions, flex, grid, media queries, I could go on, we even have CSS vars!
I've written/styled UI in quite a few ways, and I still much prefer CSS. I even use it for design, I often find it quicker to write a few lines of css than doing things in graphics software.
> This is all a way of extending a big “thank you” to the CSS spec authors
Seconded! I am very grateful for CSS and everyone who contributed to it.
I genuinely hated using CSS each time I tried prior to ~2015. The point where that started changing for me was the introduction of Flexbox; the previously available layout models seemed to have no real coherence or logic behind them, depended on the memorization of disconnected tricks.
Even with Flexbox it's taken a number of years using CSS regularly to get to a point where I've now previously encountered most things I need to do which aren't straightforward derivations from the basic rules of behavior (e.g. even something simple like getting absolute positioning relative to immediate parent to work, or how to make arbitrary elements scrollable/non, or how to auto-truncate text with an ellipsis).
But at this point, it feels awesomely powerful. I've been awed in recent history at how rapidly I can create even novel/complex UI's; the experience is partly of hitting green lights over and over, improbably (which says something about the less fun stages I had to go through prior). But it's not just that; coming from working with desktop and mobile finite widget set GUI toolkits, the expressiveness via CSS is extensive by comparison (and, separately, the one-way-dataflow/functional-reactive style of development common in modern web dev feels excellent for connecting components to backing models).
It's also just quite a bit of fun. Combine the wide-ranging expressiveness with rapid-feedback workflows like editing from browser dev tools (or with HMR and live-updating through webpack)—writing CSS and watching sleek, novel UIs come together can be pretty enjoyable these days.
Could a better system be designed so that I wouldn't have had to go through the long journey I did, while still ending with something highly expressive and great for experts to use? I often wonder but haven't been able to think of an alternate design that would be a fundamental improvement.
Ah yeah good old floats. It was all about knowing the clear tricks, not sure I could still do it these days haha. Agree, it was a lot harder. But even that was a lot easier then making layouts with tables, or frames haha, so I didn’t mind, it already felt like a massive improvement. But yeah flex is great, I also really enjoy grid. Similar tricky to get started with but insanely powerful.
You describe it very well; that expressiveness is what’s really enjoyable, and pretty much impossible to find elsewhere.
I think it’s maybe just a professional tool, hard to start with but once you get over the initial hurtle it becomes very powerful. In that sense it’s not that different from learning any programming language. It’s a good question if it could be easier, I’ve also done that exercise of “how else” I think the problem might be the complexity and messiness of ui and layout, it’s not css, it’s the layout. I think it could and will be easier though, not as something totally different, but simply improving what’s there; basically continuing the path it’s already been on for the past decades. I’m truly enjoying it today and excited for what’s to come!
> that expressiveness is what’s really enjoyable, and pretty much impossible to find elsewhere.
I've often thought it's because CSS is lower-level, more like a tool for creating UI libraries (similar to writing e.g. OpenGL directly vs a higher-level scene graph lib built on top of it)—but when you want to make something unique, there's really no competition.
> I think it could and will be easier though, not as something totally different, but simply improving what’s there; basically continuing the path it’s already been on for the past decades.
Agree! I always liked CSS, it got better and better, and the real fun for me started when I found out all the different color names. For one little side project I forced myself to only use color names, it turned out pretty nice.
How do you keep your CSS in check so that it doesn't just feel like an append-only log of UI tweaks?
For this reason I tend to prefer CSS frameworks that give me CSS classes to use in my HTML, as ugly as it might be. I just never found a good abstraction/philosophy to keep my CSS organized. Or to centralize things like margin/padding so that I'm not creating ad-hoc margins/paddings as I need them on every component.
For generally append only prevention; Traditionally it was BEM or similar. Now I would use css modules, or an css-in-js like solution depending on the situation.
Basically you have to tame the cascading aspects of css and use them with moderation.
If you use Typescript you should also check out plugins that will generate type definitions for your CSS, makes it much easier to refactor and remove stuff.
As to margins/paddings, basically consistency, you need a way to define and manage your "design tokens" as they are known these days. That can be with SCSS, custom util classes, and/or CSS vars, or indeed util CSS frameworks. You could also use something like https://stitches.dev/.
I am personally not a huge fan of css frameworks as I have not had the best experience maintaining components with long strings of heavily abbreviated classnames everywhere, but I do see why people might like them, they can be very powerful.
Nowadays I don't do much professional webdev, so I don't deal with as big projects.
But I used to use a poor man's BEM, because my team didn't like the aesthetics of the whole double-underscore thing:
Every component (usually tied to a $WhicheverFramework counterpart, matching case and all) has a class for it, elements that are part of that component get a class like $Component-$part, and states ("modifiers" in BEM) do not need a prefix.
That, and striving to keep the tree small, moving decorations to pseudo-elements when possible, and using CSS grid instead of element-based ones like Bootstrap, means you might get some long CSS rule lists, but the actual amount of selectors is pretty manageable.
I wouldn't credit the CSS spec folks with the 100 to 900 thing for the font weight. I believe that comes from the usWeightClass field [1] of the OS/2 table in the TrueType (1991) and OpenType (1996) formats. The Win32 API also uses the same value range for selecting a weight when instantiating a font [2].
Furthermore, the CSS spec that the post linked to [3] even mentioned OpenType!:
> If the font family already uses a numerical scale with nine values (like e.g. OpenType does), the font weights should be mapped directly.
CSS selectors were carefully designed to have simple and performant implementations, cleanly separated from properties they set, and initially to be looking strictly forward and deeper down the tree, so they can be applied in one pass.
The flow model that gave CSS reputation for being unable to center things vertically was also deliberate to allow rendering in one pass (which was the model of early web browsers before dynamic HTML). It’s notable that the slowest and messiest layout algorithm in CSS is tables, which predates CSS, and CSS tried to resist for a long time.
Parsing model of CSS is pretty nice too. It can be implemented with a simple recursive parser, and the forward-compatible error handling is relatively easy in such parser.
These properties may seem unremarkable, but often it takes just one cool feature to break them and cause complications down the line.
- not supporting tables in CSS1, even though they were the dominant layout mechanism used at the time.
- `box-sizing: content-box` as original sizing model, which nobody has ever needed.
- `::pseudo-elements`, also used to convince people that having to add extra divs or spans to HTML is a horrible mortal sin to be avoided at all costs.
- the cascade / `!important`, causing endless rule precedence wars.
- `ems` as units relative to the parent instead of the root font size
- making flex-box alignment props the most confusing thing ever
- `display: none` to exclude elements, instead of an `exclude` prop, colliding with the display model
- `position: fixed` not making sense
- `text-overflow: ellipsis` not working in most cases where you'd want it to
"It’s easy, in hindsight, to critique things CSS got wrong or should’ve prioritized differently. But I want to take a moment to marvel at the things they got right."
If you are going to bring them up, it would be nice to also provide the modern CSS way of fixing those problems.
The text-overflow one really gets me every time... I would also add stacking contexts and margin collapse to this list. The rules for when they apply and when they don't are extremely convoluted and full of exceptions.
One note, there are "rems" which are ems relative to the root. I love ems and use them for almost every component because of the size inheritance actually. rems are used when I need to make sure something is always the same size regardless of the parent, but that doesn't happen often.
I have. I'd love to write JavaScript-free webpages that use (FP-pure) deterministic CSS techniques in more cases (like the ":checked-trigger" trick which enable limited interactivity in pages), but which are sometimes absolutely impossible just because sometimes it's impossible to move the hidden trigger input to the right-place to enable the selector to work.
With very limited exceptions[1], CSS selectors are strictly "forward only": a CSS selector could only match elements based on preceding ancestors and siblings in the DOM, but not on any subsequent siblings or ancestor's subsequent siblings.
For example; a selector can match a <p> element that's preceded by an <img> element, or a <ul> element that's a descendant of a <div> element, but you cannot select a <div> element that contains a <ul> descendant, nor an <img> element that's then followed by a <p> element.
I understand the original reason for being strictly forward-only was to prevent progressively-loaded HTML documents being re-styled (quite possibly quite dramatically) as it loaded over everyone's 56K connections at the time. Considering how bad FOUC ("Flash of unstyled content") still is today on poorly architectured websites despite our multi-gigbit home Interet connections I'd say it's a sensible restriction.
-------------------
[1] The exceptions are things like `:focus-within` and `:last-child/-of-type/-nth-last` - but also `:has()`...
...but the problem is that the `:has()` selector-function is so expensive to evaluate it can only be used inside JS's `querySelector()`,
`querySelectorAll()`, `matches()`, and `closest()` functions: i.e. it cannot be used in selectors inside stylesheets (both <style> and .css files). Since 2021 there is work being done to allow `:has()` in in stylesheets for limited patterns that aren't as expensive as allowing general-case selectors in `:has()`: https://chromestatus.com/feature/5794378545102848
I wish CSS was client-side only — a means for a user to decide what fonts, colors, and spacing to use. I do this, with great care, for terminal apps. Is it too much to ask for web apps? Why does every site need to guess my preferences for these important properties?
That's a great system for text only content, not dynamic mixed content. There is no magic "line spacing" variable when not every line is meant to be part of a block of text.
CSS actually used to have a bunch of system colors and fonts and so on but by far the most popular use was fake virus adverts. Nobody wanted to make a webpage that didn't know what system it was going to be opened on assume the styling of that system as it would immediately clash (and possibly be unreadable).
To some extent this problem even occurs in terminals with TUI and/or color enabled apps. The focus on being a block of text output makes it reasonably possible to fix. Most people don't use/want the web to just serve blocks of text, there are other protocols and tools that do that much better anyways.
> Why does every site need to guess my preferences for these important properties?
You are more than welcome to create a browser extension which disables all externally rendered CSS. Of course, even the semantic-html-centric would look like garbage, because what is "appropriate" for one site would look absurd on another.
A fair point, although wasn't there a thread on text-only news sites just today? Perhaps they wouldn't look like garbage.
I realize I'm arguing from a semantic-html world, now long lost. However, we _are_ left w/ a situation where straight text is rendered poorly (style du jour & out the control of the user), alongside user interface components that are a huge step backwards from prior models. Maybe in another few decades we'll sort out this pickle.
The article also misses that “JS imports” (script tags with type module) act as though they have the defer attribute by default, so they are not “render blocking” like CSS imports are. It is good that CSS always blocks the parser though to prevent flash of unstyled content. My main issue with CSS imports though is that they don’t encapsulate the style rules at all, which doesn’t give much advantage over inlining the CSS to avoid the extra network request.
However I do agree with the sentiment of the article that CSS did a pretty good job of enabling a huge amount of change in web design over the years despite the lack of good options for layout in the early days
CSS imports are not equivalent of JS imports and it doesn't make sense to blame JS. The source is just a series of declarations and no dependencies, and it's simple and clear how they override each other. CSS doesn't have namespaces or modules until web components, so when you import another source you cannot choose what symbols to include (or they just don't have symbols at first place). It's almost a syntax sugar of including another <link> tag in HTML. CSS imports and JS imports have the same name but they don't have anything more in common.
The thing CSS got right, first, is right in the first letter of its acronym: cascading. It’s rightly been and being revised to add boundaries to that, but ultimately the success of CSS begins with the fact that you can style some aspects of a thing and put it into other contexts without breaking the design.
Now the thing CSS gets most wrong: every new spec is a one off, it might introduce new syntax or new names for existing things or concurrent standards track projects. The language feels less cohesive every time something new is introduced. And that’s not even counting things which have precedent in other disciplines but CSS chooses different names or semantics anyway.
And tacking on to that: shorthand properties. They’re basically handwavy magic if you’re not constantly tethered to MDN.
Add stacking contexts (aka "why doesn't my z-index work") and margin collapsing to that list. Both have extremely long and convoluted logic for when they apply and when they don't.
using Roboto 600 is meaningless and should be an error.
Because the font designers have made specific decisions about how the font should change as it gets thinner or heavier. There is no continuum along which you can just choose how think you want the font.
I see CSS as a massive toolbox full of awesome tools, some old, some new, some I use all the time, others I barely know they exist, but it's nice they are there when I need them.
It also has improved significantly over the years, it's quite remarkable; transforms, transitions, flex, grid, media queries, I could go on, we even have CSS vars!
I've written/styled UI in quite a few ways, and I still much prefer CSS. I even use it for design, I often find it quicker to write a few lines of css than doing things in graphics software.
> This is all a way of extending a big “thank you” to the CSS spec authors
Seconded! I am very grateful for CSS and everyone who contributed to it.