Csswg-drafts: [selectors] Add :role() pseudo-class

Created on 2 Feb 2019  路  13Comments  路  Source: w3c/csswg-drafts

In https://lists.w3.org/Archives/Public/www-style/2015Jan/0004.html (Oct 2014 Santa Clara f2f), we resolved to add a :role() pseudo-class, to match based on ARIA roles easily:


minutes excerpt

TabAtkins: jcraig suggested a :role pseudo
hober: There's a few problems. One is the impl RA roles on the
elements. When you have multiple roles on one element, you
get all of them.
hober: For styling you may want to style that as a switch or a
checkbox. Right now that's difficult in CSS.
hober: There's also the case of wanting to simply style all the
buttons on the page.
hober: You want to be able to say :role(button) and be done.

TabAtkins: That's convincing. Is there anything outside that?
hober: We can always add more.

glazou: You mentioned implied role. So some won't need an assigned
role. We'll need to refer to HTML.
hober: In CSS we say the host language has that.

dbaron: It's :: or : ?
TabAtkins: It's a functional class. It should be an ident.
glazou: Can you have multiple roles?
hober: Syntactically you can,
hober: But only one is active.
glazou: So if you have multiple roles on one element, it's
whitespace broken?
dino: So if you do :role...
hober: You can do role=button and role="super button". Or we
separate in the list itself.
glazou: So the role attr is multiple but the :role() pseudo is only
one?
hober: Yeah.

dauwhe: dpub is working on adding things for role attr.
TabAtkins: Do you know if it will be consistent with this?
dauwhe: They haven't said. I'll raise that with them.

TabAtkins: So I guess that's simple. Objections to adding :role()
to selectors?
TabAtkins: So :role(button) would target anything that has a
button according to aria rules.
hober: It wouldn't match button role = checkbox or something crazy

dbaron: So people are okay with agreeing CSS won't do future
things to influence what the aria role is.
hober: It should be defined by pointing over there [to markup layer].
fantasai: We need to have another language that has CSS syntax for
that kind of stuff. Our stuff should be about styling.
fantasai: People keep asking us to put things in CSS that belong
in the DOM, because they want to use CSS selectors and
cascading to attach it to the tree.
TabAtkins: If someone would like to implement cascading attr
selectors in a browser shrug
dbaron: Having CSS do this side makes sense, but we can't do both.
hober: Should we have a note in the spec saying "you may be
confused"?
glazou: When we had selectors we didn't have a note. I'm not sure
we need a note.
hober: Okay.

glazou: So no objections?

RESOLVED: add :role() to selectors

glazou: Who is going to write the prose?
TabAtkins: I will.

I volunteered to write the text, but clearly never did. ^_^

Needs Edits selectors-4

Most helpful comment

That is the case, but Alice is correct that implementation proved significantly more challenging than expected.

Style parsing needs to happen before layout and rendering. In WebKit (and Blink, maybe more) the accessibility tree is computed based on the render tree. Since accessibility can change the roles (or refuse to change the roles of malformed nodes), current implementations could result in one of the following:

  1. A circular dependency (neither style nor accessibility can proceed until the other is complete)

  2. CSS rendering continues but when accessibility loads, it could trigger new layout and repaints.

We left off that path by determining that a non-trivial amount of WebCore Accessibility would need to be extracted from the accessibility-specific codebase and refactored for use prior to layout.

It鈥檚 not impossible, but it鈥檚 quite a bit more than anyone was willing to commit to.

A WICG incubator may be a good path forward for this one. You鈥檒l need implementor involvement and buy-in before the :role() selector can proceed.

All 13 comments

I really like the idea of this and was thus going to take a stab at writing some proposed prose here, but .... from my recollection, and the minutes (both of which may be flawed), it feels like the 'key' things mentioned here really hinge on this being based off the computed role - like what is the actual role that this is playing. But, in discussing this with @alice, this might actually be pretty tricky because what the computed role is sometimes involves fairly complex checking and tree walking.

I'd be interested to know what use cases @cookiecrook had in mind here.

I agree with @bkardell, it seems to be implied that this refers to computed ARIA-equivalent role (i.e. a <button> would match :role(button)), but that is not clear from the minutes.

Assuming that to be the case, implementing this could be quite complex.

That is the case, but Alice is correct that implementation proved significantly more challenging than expected.

Style parsing needs to happen before layout and rendering. In WebKit (and Blink, maybe more) the accessibility tree is computed based on the render tree. Since accessibility can change the roles (or refuse to change the roles of malformed nodes), current implementations could result in one of the following:

  1. A circular dependency (neither style nor accessibility can proceed until the other is complete)

  2. CSS rendering continues but when accessibility loads, it could trigger new layout and repaints.

We left off that path by determining that a non-trivial amount of WebCore Accessibility would need to be extracted from the accessibility-specific codebase and refactored for use prior to layout.

It鈥檚 not impossible, but it鈥檚 quite a bit more than anyone was willing to commit to.

A WICG incubator may be a good path forward for this one. You鈥檒l need implementor involvement and buy-in before the :role() selector can proceed.

@bkardell wrote:

the computed role is sometimes involves fairly complex checking and tree walking.

As one example of this complexity, review AccessibilityTable:isDataTable() in the WebKit source.

In addition to hierarchical validation and well-formedness (<tables> do not get the table _role_ unless they have a valid grid of rows and cells), this method checks for a variety of style-based heuristics such as borders and zebra-striped row colors. It's determining layout-vs-data table based on the style characteristics, which then determine the role, and would only then affect the cascade for a :role() selector.

I have a strong feeling that distinguishing data tables from layout table is a special, largely historical, exceptional case, that should be not generalized as a rule. Tables were used for layout when there were effectively no alternative. Tables are probably the only HTML elements misused this way because of their default styling. There never were such thing as "Layout lists" or something. The "HTML is meaning, CSS is presentation" mantra is one of the first things that modern web developers learn. Many web developers try hard to make their markup meaningful for non-visual output (e.g. wrapping navigation links into list items) while presenting it visually as design requires (e.g. as a horizontal flexbox "ribbon"). When browsers deduce from this that the author "didn't mean" a list there, it feels like a huge disappointment with the very idea of the semantic markup (at least, I felt so).

I admit that there definitely might be other special cases where styling distorts the initial meaning of elements for sighted users and ATs have to convey this distortion, but they should probably be investigated and specified individually. The general rule should be that CSS doesn't affect the implied meaning of the content unless there is an absolute and consensus-approved necessity to do so. Similarly to what we have already decided in #2355.

So, :role() would be a bit like :lang() in that it can be inherited or inferred, while [role] or [aria-role] cannot. A pseudo-class seems appropriate then, otherwise I would have suggested special syntax as for IDs #foo and classes .bar, e. g. *@baz or %baz.

@Crissov can you explain that comment a little more?

@SelenIT - I think @alice or @cookiecrook can speak better to how unique that particular example is, but there's definitely additional relationships and complexity which I'm unsure even happens at the right stage right now to be considered in a selector. I believe some roles may actually rely on CSS application in order to determine their computed role, which would be problematic. I'm not suggesting that this isn't a thing that shouldn't be supported, and if we were designing all of the things fresh, this is a thing I would really want to keep in mind - I just wonder if we might not need to think about this a lot more and maybe work on some efforts to detangle - or maybe thinks about revise the ask somehow in a way that could be achievable but not just add confusion for developers about one more hard to understand kind of value?

@bkardell At first, I wondered how :role(foo) would be any different from [role=foo], but then I realized that attribute selectors work on explicitly specified values while pseudo-classes can work on implicit values. Also, IDs and classes are not predefined by an external body while ARIA roles and BCP47 language codes are.

Also, adding completely new special syntax might not work so well with https://github.com/w3c/csswg-drafts/issues/3264.

@SelenIT wrote:

I have a strong feeling that distinguishing data tables from layout table is a special, largely historical, exceptional case, that should be not generalized as a rule. [...] There never were such thing as "Layout lists" or something.

Here's the same concept for layout lists (a.k.a. "list-itis") versus semantic lists:
AccessibilityList::determineAccessibilityRole() in the WebKit source

"div-itis" is also a thing, though thankfully <div> doesn't get an important role by default. Other element types that my get this treatment at some point include <article>, <header>, <footer>, etc.

@SelenIT

When browsers deduce from this that the author "didn't mean" a list there, it feels like a huge disappointment with the very idea of the semantic markup (at least, I felt so).

Not to diverge too far off topic, but some additional threads on that are here:
https://twitter.com/pgrucza/status/1083835348671700992
https://twitter.com/cookiecrook/status/1084141791580905472

the same concept for layout lists (a.k.a. "list-itis")

@cookiecrook, thank you for these links. I completely agree with the Priority of Constituencies principle you cite. Hovewer, my point that there is _no such thing as layout lists_ still stands. The term "layout lists" is a misnomer. There is a huge difference between (mis)using specific elements _because of_ their styling and (mis)using them _despite_ their styling, making extra effort to "overcome" it. I'd rather call them something like "unobvious lists" or "cryptic lists":)

Indeed, sometimes the "listitis" makes a page too verbose for screenreader users, and they definitely may feel _some_ of the extra list-related info redundant and removing it can look helpful for them. I agree with this intent, but one premise of the issue 134187 seems wrong to me:

Chances are that they are just presentational lists using the elements for the sake of a styling hook.

How big are chances that someone uses a specific element not caring about its meaning and _makes extra effort_ removing its styles, while there is much easier-to-use alternative (div)? There are probably more chances for the purely presentational (e.g. WYSIWYG-generated) markup that uses graphic markers just for decoration to pass the existing heuristics.

I'm pretty sure that the primary reason for overusing lists (instead of divs and other much easier to style elements) is intent to convey extra _semantics_ (e.g. "this is a list of 5 horizontal navigation links" or "this is a 15 items portion of the catalog list ordered by price") that sighted users can usually deduce from the visual context (how the items are grouped together, which common decorations distinguish them from other elements on the page, etc.). And I'm not sure that hiding this intended meaning that authors _did_ put into the markup from the non-visual users really serves the users' priority. Indeed, some heuristics to treat different type of lists differently could be useful, but styling is probably not the best criterion for this.

Was this page helpful?
0 / 5 - 0 ratings