Skip to content

[selectors] Add pseudo-classes for being a drop-down box vs a list box #7422

zcorpan opened this issue Jun 27, 2022 · 30 comments

Comments

@zcorpan
Copy link
Member Author

zcorpan commented Jun 30, 2022

Is there interest in standardizing this pseudo-class (and make it also available to author CSS)?

cc @mfreed7

Via git blame of WebKit's html.css I found https://bugs.webkit.org/show_bug.cgi?id=220376 -- I think a pseudo-class as suggested here would be less prone to bugs like this (compared to attribute selectors). cc @pxlcoder

Via git blame of Gecko's html.css I found https://bugzilla.mozilla.org/show_bug.cgi?id=1643246 where attribute selectors were replaced with a pseudo-class. cc @emilio @heycam

@mfreed7
Copy link
Contributor

mfreed7 commented Jun 30, 2022

It certainly seems tricky to select this based on attribute selectors, so I'm supportive of trying to standardize a pseudo class.

Picking a name will be tricky. I'm not sure I like :select-list-box, since in my view, both in-page and pop-up

@zcorpan
Copy link
Member Author

zcorpan commented Jun 30, 2022

HTML's wording is "list box" for . However those terms are not web-exposed anywhere (prior to this pseudo-class), so they can be changed.

@bradkemper
Copy link
Contributor

I believe the select element has an aria list box role either way, so that could be confusing.

@zcorpan
Copy link
Member Author

zcorpan commented Jul 5, 2022

How about "list box" and "drop-down list box"? (Not sure about "list box" vs "listbox".)

@bradkemper
Copy link
Contributor

"Drop down" or "drop down list box" seem pretty clear (even though they are "pop up menus" on Mac). But just "list box" by itself is not clear, because I honestly wouldn't remember which one you meant without comparing it to the other term. I think if you had "multiple list box" (or similar*) and "drop down list box" as the two terms, then they'd both be clear, even in isolation.

  • similar:
  • List box multiple
  • Multi-select list box
  • no-drop list box (clear, but ugh)

@zcorpan
Copy link
Member Author

zcorpan commented Jul 6, 2022

It's not necessarily multi-select, though.

<select size=5>
  <option>this is still single-select list box
  <option>foo
  <option>bar
select>

@zcorpan
Copy link
Member Author

zcorpan commented Jul 6, 2022

We could define only a pseudo-class for the drop-down, and rely on the :not() function to match the not-drop-down state.

select:drop-down-list-box {}
select:not(:drop-down-list-box) {}

@dbaron
Copy link
Member

dbaron commented Jul 6, 2022

+1 to the idea of targeting the idea of having a dropdown. Perhaps something like :has-dropdown?

@bradkemper
Copy link
Contributor

@zcorpan works for me. I also like the @dbaron refinement. Though there should probably be another dash, like :has-drop-down, so we don’t repeat the nowrap mistake.

Also, would a native date picker or color picker be considered a drop-down, like input[type=date]:has-drop-down?

@bradkemper
Copy link
Contributor

I’m ambivalent about the extra dash, really.

@zcorpan
Copy link
Member Author

zcorpan commented Jul 7, 2022

Also, would a native date picker or color picker be considered a drop-down, like input[type=date]:has-drop-down?

Good question. I would say no. The date widgets are not guaranteed to have a drop-down or a popup, it would be conforming to have a control with only spinners, for example. The color well is specified to have a "color picker" that is separate from the color well, but nothing says it has to be a drop-down. Firefox on macOS opens a popup window for the color picker.

Since the need is specific to the select element, I think we should define it to only apply to select. Should the naming be different because of that?

@zcorpan
Copy link
Member Author

zcorpan commented Aug 8, 2022

A few names to consider

  • :has-dropdown
  • :select-has-dropdown
  • :select-with-dropdown
  • As above but with a dash in drop-down

Example usage:

select:has-dropdown { ... }
select:not(:has-dropdown) { ... }

select:select-has-dropdown { ... }
select:not(:select-has-dropdown) { ... }

select:select-with-dropdown { ... }
select:not(:select-with-dropdown) { ... }

or without type selector (when not using :not())

:has-dropdown { ... }
select:not(:has-dropdown) { ... }

:select-has-dropdown { ... }
select:not(:select-has-dropdown) { ... }

:select-with-dropdown { ... }
select:not(:select-with-dropdown) { ... }

It is probably better in terms of ergonomics to have two pseudo-classes for the two states, e.g.:

  • :has-dropdown and :no-dropdown
  • :select-has-dropdown and :select-no-dropdown
  • :select-with-dropdown and :select-without-dropdown

Since it will only match select elements it seems reasonable to include it in the name, as people may expect :has-dropdown to apply to other things with dropdowns and :no-dropdown to apply to almost all elements.

@mfreed7
Copy link
Contributor

mfreed7 commented Aug 8, 2022

It seems to me that if this is only ever going to apply to comes with a drop-down. Somehow (and I'm not sure why) but :select-has-dropdown sounds to me like it should apply only when the dropdown is open. Like it currently has a dropdown.

Interesting side reading on "drop-down" vs "dropdown": https://www.chicagomanualofstyle.org/qanda/data/faq/topics/HyphensEnDashesEmDashes/faq0153.html. Perhaps we should use "menu" instead?

@zcorpan
Copy link
Member Author

zcorpan commented Aug 8, 2022

I don't think "menu" distinguishes . The name here is also "for developers", so we're good per the Microsoft Writing Style Guide. :-)

:not() indeed allows the same expressiveness, but it's a bit more cumbersome compared to using a direct pseudo-class. Compare with

:link { ... }
:visited { ... }

vs

:any-link:not(:visited) { ... }
:visited { ... }

@tabatkins
Copy link
Member

tabatkins commented Aug 8, 2022

+1 to "put select in the name" - it means we don't have to figure out whether this also applies to N other things, and verify if new things need to have it, possibly in only certain UAs, etc... Plus the general argument that if it only applies to 1 thing now, people will rely on that fact and use it on its own (without a tagname selector) with the intention of targeting selects specifically, and that code will then break in the future when we apply it to more. General policy: never use a generic name that could plausibly apply to many things unless there are at least three things that it already applies to.

Relying solely on :not() for the non-dropdown case is slightly unfortunate, as it requires you to use the tagname in the selector as well - select:not(:select-with-dropdown) - since just :not(:select-with-dropdown) will target random elements too. I think we should come up with a name for the other state. I think listbox is fine - even if it's a little unclear on its own, since it'll be contrasted with dropdown I think it's reasonable.

Or if we're pretty sure that select only has two states in this axis (which I think is a safe assumption, given 20+ years of history), :select-with-dropdown and :select-no-dropdown might work.

@zcorpan
Copy link
Member Author

zcorpan commented Aug 8, 2022

Since the dropdown menu is called a listbox in APG and Open UI, it's plausible people will assume listbox means the dropdown menu.

The

@zcorpan
Copy link
Member Author

zcorpan commented Aug 9, 2022

So it sounds like :select-with-dropdown is the winner for the "with dropdown" state.

For the other state, we have:

  • :select-no-dropdown
  • :select-without-dropdown

In https://drafts.csswg.org/indexes/ I see several "no-" but no "without-", so the former seems more CSS-y and is also shorter.

Thus, I suggest we go with :select-with-dropdown and :select-no-dropdown.

@zcorpan zcorpan added the Agenda+ label Aug 9, 2022
@bramus
Copy link
Contributor

bramus commented Aug 23, 2022

In https://drafts.csswg.org/indexes/ I see several "no-" but no "without-", so the former seems more CSS-y and is also shorter.

Looking at that list, I see that these no- properties/values are (mostly) prefixed version of other ones that do not have a prefix. For example no-clip is the antonym of clip; not has-clip or with-clip.

Working my way back from the suggested select-no-dropdown, it should go hand in hand with select-dropdown then?

If select-dropdown does not make sense, and we do want to keep select-with-dropdown, its antonym – in similar fashion as clip/no-clip – should then become select-no-with-dropdown? From a linguistic POV the latter doesn’t make sense at all, and it would become select-without-dropdown.

tl;dr If we have select-with-dropdown, select-without-dropdown seems like a better opposite to me.

@tabatkins
Copy link
Member

:select-dropdown strongly reads as selecting the dropdown itself, so I'd rule that out.

no-with-dropdown is definitely out, yeah. ^_^

I don't think we need to stick with pure English rules for this; we're not writing a sentence. no-wrap is similarly slightly awkward if read as normal English; it would be doesnt-wrap or something if we were shooting for that.

I think sticking with no-dropdown is fine/preferable, both for its length and its consistency.

@nt1m
Copy link
Member

nt1m commented Sep 7, 2022

Might be good to reuse the well known CSS appearance values, as vocabulary:

select:menulist and select:listbox

@zcorpan
Copy link
Member Author

zcorpan commented Sep 7, 2022

I think only :listbox is not great because there are other listboxes other than " is also called a listbox). The appearance values are also legacy in favor of auto.

@tabatkins
Copy link
Member

Yeah, and I wouldn't really consider them "well-known" either. I couldn't tell you what appearance values exist, for example, besides auto and button.

@zcorpan
Copy link
Member Author

zcorpan commented Sep 8, 2022

I should be able to remotely attend the TPAC CSS meeting either Thursday or Friday, but only before lunch. cc @astearns

@bramus
Copy link
Contributor

bramus commented Sep 12, 2022

Sidenote: If authors had the ability to numerically compare attribute values, they would be able to select those elements using this snippet:

select[size>1],
select[multiple] {
  /*🎉 */
}

This, in turn, would make a lovely custom selector as well:

@custom-selector :--with-listbox [size>1], [multiple];

select:--with-listbox {
  /*🎉 */
}

@zcorpan
Copy link
Member Author

zcorpan commented Sep 12, 2022

@bramus not sufficient for the UA stylesheet, at least, since browsers need to get cases like

@zcorpan
Copy link
Member Author

zcorpan commented Sep 12, 2022

@astearns is it possible to move this issue to some time before lunch (either Thursday or Friday)?

@css-meeting-bot
Copy link
Member

The CSS Working Group just discussed Pseudo-classes for drop-down vs list box for
github: https://github.com//issues/7422
zcorpan: Proposed pseudo-class for -specific
emilio: using select:listbox and select:not(listbox) would be nicer
zcorpan: I think that's an okay outcome, biggest difference is you need to include a type selector to match the :not() state, whereas with pseudo-classes can only use the pseudo-classes
fantasai: we need to consider that we keep adding pseudo-classes
... if we don't really need a pseudo-class
... it's better not to have it
... so that there's less for people to memorize
q+
zcorpan: agreed
ack heycam
fantasai: if we can do this with integer parsing and it's not too tricky maybe that's a better way around it
In particular, if this is -specific, not generic. Probably means it needs a "select" in the name. But then it's just awkward to have to specify select again, like `select:not(:select-with-dropdown)`
heycam: I'm not strongly against adding pseudo-classes, but wondering if really that useful to expose to authors
heycam: if WebKit wants to fix compat issues, they can have an internal pseudo-class like other engines
heycam: but for authors, thinking whether they are using listbox or dropdown, is something they know ahead of time
heycam: I think it's rare for pages to switch between the two, so don't know how useful it is for authors to have different styles depending on this
heycam: or need to rely on the flexibility of how HTML parses these attributes, vs knowing through the DOM already
+1
zcorpan: for cases where dev controls both markup and CSS, but that's not always the case
zcorpan: maybe you're writing a stylesheet for a design system, want to apply to all WordPress pages
zcorpan: you don't know what HTML they will use
ack emilio
zcorpan: so that's why pseudo-class makes sense
emilio: Was going to make similar comment to heycame
emilio: we should encourage use of multiple attribute, it's easy to write selectors for that
emilio: rather than relying on parsing of size attribute
emilio: if you're making design system, ask them to use that
emilio: but I'm on the edge on whether it's worth having a pseudo-class for this or not
zcorpan: multiple is a semantic difference
emilio: sorry, yes, you're riht
s/riht/right/
zcorpan: you can have a listbox that's not multiple
fantasai: doesn't seem to me like the selector for this would be that difficult if we had number parsing
... is [multiple] plus size parsing as an integer >1
... the details of how to parse invalid size attributes is a concern for implementors but not authors
zcorpan: type out the two selectors?
`select[size > 1], select[multiple]`
... people usually don't write junk in their size attribute
`select:is([multiple], [size]:not([size="1"]))` is probably close enough in practice today
`select:not([size>1],[multiple])`
ack dbaron
dbaron: One, I tend to agree that if you're building a design system, you probably want these sorts of things
dbaron: I think part of the reason we don't see much demand is that select is so hard to style, don't run into this problem much
dbaron: if styling select worked more reliably, they would want on this more
+1 to what dbaron just said, styling select is a pain
dbaron: Quoted HTML, which defines the display size of a select element
dbaron: condition for a combobox vs listbox is display size being equal to 1 or not
zcorpan: or multiple attribute being present or not
dbaron: There's a few reasons the selectors above are wrong
dbaron: one is that you need to test for size being zero
dbaron: because HTML applies rules for non-negative integers
dbaron: you want a valid size that is zero or 2 or more
dbaron: or the multiple attribute
q?
dbaron: it's doable if you had HTML non-negative integer parsing
dbaron: but might be worth having this pseudo-selector anyway
TabAtkins: fantasai's point was that dealing with invalid things is the sort of things that UA needs to care about, but page author doesn't
TabAtkins: if they're putting random trashi in their size attribute, that's their problem
+1 to if we do have a way to do this, would rather a specific pseudo-class rather than a general integer parsing selector
TabAtkins: but HTML UA needs to deal with all kinds of random trash
dbaron: As you go further down the stack to style sheets meant to apply to more and more pages, get closer to needing to match implementation
dbaron: bootstrap might get bugs on this
TabAtkins: Bootstrap can say, "don't write random trash in your size attribute and this will work correctly"
TabAtkins: if we were stricter in parsing this earlier we wouldn't have this problem for UAs
TabAtkins: but even widely-used library, nobody needs to deal with this much trash
TabAtkins: put a number here, and it works. Put a non-number here and it'll not work
fremy: Authors shouldn't have to read the spec to figure out the conditions
fremy: of course they can copy some weird code, but not very understandable
fremy: you will copy and paste it, but not clear what it does at first sight
fremy: if already implemented in engines, have this pseudo-class
fremy: that sounds useful so why not
fremy: why are we wasting time discussing if it's just removing a prefix in the code, seems silly
ack fantasai
astearns: We started with what we called a pseudo-class, and now discussing maybe not having pseudo-class
astearns: with arguments presented so far, anyone convinced we should have it?
heycam: me
astearns: Should we try to resolve to add pseudo-class?
fantasai: I'd like to hear from Rachel Andrew and emeyer
fantasai: if they are like, "Yes, we should definitely have this!" then great
FWIW this is how Gecko used to implement this with attribute selectors: https://hg.mozilla.org/mozilla-central/rev/13062d9979d254481851c0f8c9d9e608d91f6ae3
fantasai: If not, I'm skeptical
there has been a lot of research about styling select in openUI, does anyone know if this topic was discussed?
emeyer: It's hard for me to say, a pseudo-class mostly feels correct here, but fantasai is correct, we have so many pseudo-classes now
emeyer: even more than I realized until recently
emeyer: So I'm not sure I'm 100% convinced that it's best
emeyer: Some way of doing this is good
emeyer: but whether it should be a pseudo-class or ???
fantasai: We would add number-based attribute selectors, and you would make a selector
astearns: It would be a copy-paste incantation
fantasai: still have to do that if it's a pseudo-classs!
Another interesting edge case is `size=""`
emilio, similar but not exactly the same as the current WebKit UA style rule selectors
TabAtkins: Who is asking for this? In the UA is one thing, but do other people need it?
emilio, yes that is exactly the difference
zcorpan: reset stylesheets use it
q+
zcorpan: incorrectly, usually
fantasai: They are copy-pasted, so they can write a proper selector
ack emilio
zcorpan: but used in lots of pages, should get all the cases correct
https://github.com/sansotmon/asistencia-salvarte/blob/50dde64556294e8e42dbb2f7950f1b9c078ebef7/web/core/themes/olivero/css/components/form-select.css
Importantly - if they're not getting it right, *is this causing problems for people*?
emilio: empty size attribute is another case
emilio: also slightly more efficient to do a pseudo-class
```[dir="ltr"] select[multiple] { padding-left: 9px }```
Are they getting bugs and ignoring them because parsing numbers via CSS is hard? Or are they just not getting bugs?
emilio: pre-parses faster than other random attributes
^ this is wrong, first hit on github
emilio: If ppl feel this is useful, then maybe it's not worth copy-pasting a weird incantation
q+
ack rachelandrew
rachelandrew: I think in terms of being easier to explain and less error-prone, pseudo-class is good
rachelandrew: but do ppl actually want to do this, is also a valid concern
rachelandrew: if people aren't asking for it
rachelandrew: I like things to be straightforward
rachelandrew: but we also have a lot of pseudo-classes, and have to teach people
rachelandrew: so I don't have a strong feeling, but like emeyer I'm on the fence
astearns: Then what I want to do is to close off the discussion in this meeting, take back to issue, have whatever the actual correct integer and multiple check would be
astearns: so we have something to compare
astearns: and come back to this issue on a telecon
zcorpan: OK
astearns: any other questions on this?
fantasai: do we want to add integer attr selectors?
... generally speaking, do we want a proposal for that?
astearns: I dont' think we can decide that r/n
astearns: not decide right now
select[multiple], select[size] { height: auto; }
in bootstrap

@lukewarlow
Copy link
Member

lukewarlow commented Apr 10, 2025

Based on the fact we now have ::picker(select) which exists for dropdown select but not for in-page select. Could we do

select:has-picker(select) as the new selector? Question would be does this match in non-base appearance mode?

If it does match then select:not(:has-picker(select)) works for listbox. If it doesn't work then that's trickier. You'd have to do listbox styles and then potentially undo them?

I haven't read the full discussions from before but it's possible the assumptions no longer hold true.

For example if we were to change multiple to be a dropdown when in base appearance mode, in some cases you couldn't always target just based on attributes alone.

@lukewarlow
Copy link
Member

Adding this to the agenda as it would be useful to resolve on something. This is a soft blocker for base appearance listboxes.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

10 participants