RFC: Initial CSS Level Categorization · CSS-Next/css-next · Discussion #92
A proposal to retroactively classify additions to CSS in order to put more meat on the bones of the term “modern CSS”.
A proposal to retroactively classify additions to CSS in order to put more meat on the bones of the term “modern CSS”.
I love libraries. I think they’re one of humanity’s greatest inventions.
My local library here in Brighton is terrific. It’s well-stocked, it’s got a welcoming atmosphere, and it’s in a great location.
But it has an information architecture problem.
Like most libraries, it’s using the Dewey Decimal system. It’s not a great system, but every classification system is going to have flaws—wherever you draw boundaries, there will be disagreement.
The Dewey Decimal class of 900 is for history and geography. Within that class, those 100 numbers (900 to 999) are further subdivded in groups of 10. For example, everything from 940 to 949 is for the history of Europe.
Dewey Decimal number 941 is for the history of the British Isles. The term “British Isles” is a geographical designation. It’s not a good geographical designation, but technically it’s not a political term. So it’s actually pretty smart to use a geographical rather than a political term for categorisation: geology moves a lot slower than politics.
But the Brighton Library is using the wrong label for their shelves. Everything under 941 is labelled “British History.”
The island of Ireland is part of the British Isles.
The Republic of Ireland is most definitely not part of Britain.
Seeing books about the history of Ireland, including post-colonial history, on a shelf labelled “British History” is …not good. Frankly, it’s offensive.
(I mentioned this situation to an English friend of mine, who said “Well, Ireland was once part of the British Empire”, to which I responded that all the books in the library about India should also be filed under “British History” by that logic.)
Just to be clear, I’m not saying there’s a problem with the library using the Dewey Decimal system. I’m saying they’re technically not using the system. They’ve deviated from the system’s labels by treating “History of the British Isles” and “British History” as synonymous.
I spoke to the library manager. They told me to write an email. I’ve written an email. We’ll see what happens.
You might think I’m being overly pedantic. That’s fair. But the fact this is happening in a library in England adds to the problem. It’s not just technically incorrect, it’s culturally clueless.
Mind you, I have noticed that quite a few English people have a somewhat fuzzy idea about the Republic of Ireland. Like, they understand it’s a different country, but they think it’s a different country in the way that Scotland is a different country, or Wales is a different country. They don’t seem to grasp that Ireland is a different country like France is a different country or Germany is a different country.
It would be charming if not for, y’know, those centuries of subjugation, exploitation, and forced starvation.
British history.
Update: They fixed it!
When I wrote about my time in Amsterdam last week, I mentioned the task that the students were given:
They’re given a PDF inheritance-tax form and told to convert it for the web.
Rich had a question about that:
I’m curious to know if they had the opportunity to optimise the user experience of the form for an online environment, eg. splitting it up into a sequence of questions, using progressive disclosure, branching based on inputs, etc?
The answer is yes, very much so. Progressive disclosure was a very clear opportunity for enhancement.
You know the kind of paper form where it says “If you answered no to this, then skip ahead to that”? On the web, we can do the skipping automatically. Or to put it another way, we can display a section of the form only when the user has ticked the appropriate box.
This is a classic example of progressive disclosure:
information is revealed when it becomes relevant to the current task.
But what should the mechanism be?
This is an interaction design pattern so JavaScript seems the best choice. JavaScript is for behaviour.
On the other hand, you can do this in CSS using the :checked
pseudo-class. And the principle of least power suggests using the least powerful language suitable for a given task.
I’m torn on this. I’m not sure if there’s a correct answer. I’d probably lean towards JavaScript just because it’s then possible to dynamically update ARIA attributes like aria-expanded
—very handy in combination with aria-controls
. But using CSS also seems perfectly reasonable to me.
It was interesting to see which students went down the JavaScript route and which ones used CSS.
It used to be that using the :checked
pseudo-class involved an adjacent sibling selector, like this:
input.disclosure-switch:checked ~ .disclosure-content {
display: block;
}
That meant your markup had to follow a specific pattern where the elements needed to be siblings:
<div class="disclosure-container">
<input type="checkbox" class="disclosure-switch">
<div class="disclosure-content">
...
</div>
</div>
But none of the students were doing that. They were all using :has()
. That meant that their selector could be much more robust. Even if the nesting of their markup changes, the CSS will still work. Something like this:
.disclosure-container:has(.disclosure-switch:checked) .disclosure-content
That will target the .disclosure-content
element anywhere inside the same .disclosure-container
that has the .disclosure-switch
. Much better! (Ignore these class names by the way—I’m just making them up to illustrate the idea.)
But just about every student ended up with something like this in their style sheets:
.disclosure-content {
display: none;
}
.disclosure-container:has(.disclosure-switch:checked) .disclosure-content {
display: block;
}
That gets my spidey-senses tingling. It doesn’t smell right to me. Here’s why…
The simpler selector is doing the more destructive action: hiding content. There’s a reliance on the more complex selector to display content.
If a browser understands the first ruleset but not the second, that content will be hidden by default.
I know that :has()
is very well supported now, but this still makes me nervous. I feel that the more risky action (hiding content) should belong to the more complex selector.
Thanks to the :not()
selector, you can reverse the logic of the progressive disclosure:
.disclosure-content {
display: block;
}
.disclosure-container:not(:has(.disclosure-switch:checked)) .disclosure-content {
display: none;
}
Now if a browser understands the first ruleset, but not the second, it’s not so bad. The content remains visible.
When I was explaining this way of thinking to the students, I used an analogy.
Suppose you’re building a physical product that uses electricity. What should happen if there’s a power cut? Like, if you’ve got a building with electric doors, what should happen when the power is cut off? Should the doors be locked by default? Or is it safer to default to unlocked doors?
It’s a bit of a tortured analogy, but it’s one I’ve used in the past when talking about JavaScript on the web. I like to think about JavaScript as being like electricity…
Take an existing product, like say, a toothbrush. Now imagine what you can do when you turbo-charge it with electricity: an electric toothbrush!
But also consider what happens when the electricity fails. Instead of the product becoming useless you want it to revert back to being a regular old toothbrush.
That’s the same mindset I’m encouraging for the progressive disclosure pattern. Make sure that the default state is safe. Then enhance.
Heydon does a very good job of explaining why throwing away the power of selectors makes no sense.
Utility-first detractors complain a lot about how verbose this is and, consequently, how ugly. And it is indeed. But you’d forgive it that if it actually solved a problem, which it doesn’t. It is unequivocally an inferior way of making things which are alike look alike, as you should. It is and can only be useful for reproducing inconsistent design, wherein all those repeated values would instead differ.
He’s also right on the nose in explaining why something as awful at Tailwind could get so popular:
But CSS isn’t new, it’s only good. And in this backwards, bullshit-optimized economy of garbage and nonsense, good isn’t bad enough.
A handy resource from Paul:
Find inspiration for naming things – be that HTML classes, CSS properties or JavaScript functions – using these lists of useful words.
A great reminder of just how much you can do with modern markup and styles when it comes to form validation. The :user-invalid
and :user-valid
pseudo-classes are particularly handy!
Let’s be rational here. If I were to imagine a job that was a perfect candidate for replacement by AI, it would be one that consists of measurable tasks that can be learned—allocation of capital, creation and execution of market strategy, selection of candidates for top roles—and one that costs the company a shitload of money. In other words: executives.
The logic is sound. However…
The CEOs will be spared from automation not because they should be, but because they are making the decisions about who is spared from automation.
A collection of stylesheets that don’t use class selectors. Think of them as alternatives to default user-agent stylesheets.
I feel like I’m starting to understand how the CSS :where
pseudo-class works and why it’s useful. The cogs are slowly turning in my brain.
This is supposed to be a defence of utility classes …but it’s actually a great explanation of why classes in general are a great mechanism for styling.
I don’t think anyone has ever seriously suggested using inline styles—the actual disagreement is about how ludicrously rigid and wasteful the class names dictated by something like Tailwind are. When people criticise those classes they aren’t advocating for inline styles—they’re advocating for better class names and making more use of the power of the class selector in CSS, not less.
Anyway, if you removed every instance of the word “utility” from this article, it would still work.
This would be such a great addition to CSS—a parent/ancestor selector!
With the combined might of :has()
, :not()
, nth-child()
, and calc()
, CSS has become a powerful language for specifying rules to account for all kinds of situations.
Flash, from the very beginning, was a transitional technology. It was a language that compiled into a binary executable. This made it consistent and performant, but was in conflict with how most of the web works. It was designed for a desktop world which wasn’t compatible with the emerging mobile web. Perhaps most importantly, it was developed by a single company. This allowed it to evolve more quickly for awhile, but goes against the very spirit of the entire internet. Long-term, we never want single companies — no matter who they may be — controlling the very building blocks of the web.
A really lovely unmonetisable enthusiasm:
All 2,242 illustrations from James Sowerby’s compendium of knowledge about mineralogy in Great Britain and beyond, drawn 1802–1817 and arranged by color.
You can dive in and explore or read more about the project and how it was made.
It reminds me of Paul’s project, Bradshaw’s Guide: the both take a beloved artifact of the past and bring it online with care, love, and respect.
I decided to implement almost all of the UI by just adding & removing CSS classes, and using CSS transitions if I want to animate a transition.
Yup. It’s remarkable how much can be accomplished with that one DOM scripting pattern.
I was pretty surprised by how much I could get done with just plain JS. I ended up writing about 50 lines of JS to do everything I wanted to do.
Notes on the old internet, its design and frontend.
Monica shares the little snippet of handy CSS she uses at the start of any project.
I understand less than half of this great talk by Meredith L. Patterson, but it ticks all my boxes: Leibniz, Turing, Borges, and Postel’s Law.
(via Tim Berners-Lee)
Some very smart ideas in here for resetting default browser styles, like only resetting lists that have classes applied to them:
ul[class],
ol[class] {
padding: 0;
}
I select only lists that do have a
class
attribute because if a plain ol’<ul>
or<ol>
gets used, I want it to look like a list. A lot of resets, including my previous ones, aggressively remove that.
Books in the public domain, lovingly designed and typeset, available in multiple formats for free. Great works of fiction from Austen, Conrad, Stevenson, Wells, Hardy, Doyle, and Dickens, along with classics of non-fiction like Darwin’s The Origin of Species and Shackleton’s South!
Don’t miss this—a masterclass in SVG animation with Cassie (I refuse to use the W word). Mark your calendar: August 20th.