
Should We Even Have :closed?
Should We Even Have :closed? êŽë š
For the past few months, Iâve been writing a lot of entries on pseudo-selectors in CSS, like ::picker() or ::checkmark. And, in the process, I noticed I tend to use the :open pseudo-selector a lot in my examples â and in my work in general.
Borrowing words from the fine author of the :open entry in the Almanac:
The CSS
:openpseudo-selector targets elements that support open and closed states â such as the<details>and<select>elements â and selects them in their open state.
So, given this:
details:open {
background: lightblue;
color: darkred;
}
We expect that the <details> element gets a light blue background and dark red text when it is in an open state (everywhere but Safari at the time Iâm writing this):
But what if we want to select the âclosedâ state instead? Thatâs what we have the:closed pseudo-class for, right? Itâs supposed to match an elementâs closed state (w3c/csswg-drafts). I say, supposed because itâs not specced yet.
But does it need to be specced at all? I only ask because we can still target an elementâs closed state without it using :not():
/* When details is _not_ open, but closed */
details:not(:open) {
/* ... */
}
So, again: do we really need a :closed pseudo-class? The answer may surprise you! (Just kidding, this isnât that sort of articleâŠ)
Some background
Talks surrounding :open started in May 2022 when Mason Freed (mfreed7) raised the issue (w3c/csswg-drafts) of adding :open (which was also considered being named :top-layer at the time) to target elements in the top layer (like popups):
Today, the OpenUI WC similarly resolved (openui/open-ui) to add a :top-layer pseudo class that should apply to (at least) elements using the Popup API which are currently in the top layer. The intention for the naming and behavior, though, was that this pseudo class should also be general purpose. It should match any type of element in the top layer, including modal <dialog>, fullscreen elements, and ::backdrop pseudo elements.
This sparked discourse on whether the name of the pseudo-element targeting the top layer of any type of element (e.g., popups, pickers, etc.) should either be :open or :top-layer. I, for one, was thrilled when the CSSWG eventually decided on :open (w3c/csswg-drafts) in August 2022. The name makes a lot more sense to me because âopenâ assumes something in the top layer.
To :close or :not(:open)?
Hold on, though! In September that same year, Mason asked whether or not we should have something like a :closed pseudo-class to accompany :open. That way, we can match elements in their âclosedâ states just as we can their âopenâ states. That makes a lot of sense, t least on the surface. Tab Atkins (tabatkins) chimed in:
I love this definition, as I think it captures a concept of âopennessâ that lines up with what most developers think âopenâ means. I also think it makes it relatively straightforward for HTML to connect it to specific elements.
What do folks think?
Should we also talk about adding the corresponding
:closedpseudo class? That would avoid the problem that:not(:open)can match anything, including things that donât open or close.
And guess what? Everyone seemed to agree. Why? Because it made sense at the time. I mean, since we have a pseudo-class that targets elements in their :open state, surely it makes sense to have :closed to target elements in their closed states, right? Right??
No. Thereâs actually an issue with that line of reasoning. Joey Arhar (josepharhar) made a comment about it (w3c/csswg-drafts) in October that same year:
I opened a new issue about
:closedbecause this doesnât have consensus yet (#11039 (w3c/csswg-drafts)).
Wait, what happened to consensus? Itâs the same question I raised at the top of this post. According to Luke Warlow (lukewarlow):
Making
:closedmatch things that can never be open feels odd. And would essentially make it:not(:open)in which case do we even need:closed? Like we donât have a:popover-closedbecause itâs the inverse of:popover-open.
There is no :closed⊠for now
Fast forward one more month to November 2024. A consensus was made to start out with just :open and remove :closed for the time being (whatwg/html).
Dang. Nevertheless, according to WHATWG (whatwg/html) and CSSWG (w3c/csswg-drafts), that decision could change in the future. In fact, Bramus dropped a useful note in there just a month before WHATWG made the decision:
Just dropping this as an FYI: :read-only is defined as :not(:read-write), and that shipped.
Which do you find easier to understand?
Personally, Iâm okay with :closed â or even using :not(:open) â so far as it works. In fact, I went ahead swapped :closed for :not(:open) in my ::checkmark and ::picker() examples. Thatâs why they are they way they are today.
But! If you were to ask me which one comes easier to me on a typical day, I think I would say :closed. Itâs easier for me to think in literal terms than negated statements.
What do you think, though? Would you prefer having :closed or just leaving it as :not(:open)?
If youâre like me and you love following discussions like this, you can always head over to CSSWG drafts on GitHub (w3c/csswg-drafts) to watch or participate in the fun.