Re: css3-selectors Summary of Comment

On May 14, 2009, at 5:48 AM, Henri Sivonen wrote:

> On May 8, 2009, at 03:02, Janina Sajka wrote:
>
>> We ask that there be support for ARIA states and properties [1] as  
>> pseudoclasses.  Many of these are similar to things that are  
>> currently supported as pseudoclasses, in that they can be set in  
>> multiple ways.  For example, "checked" can be set from an HTML  
>> attribute, from aria-checked, or by user action.  It is useful for  
>> a CSS author to be able to style all checked things the same,  
>> regardless of how they came to be checked.   Ask whether the CSS WG  
>> thinks it's better to make that part of the selectors spec, part of  
>> the ARIA spec, or something else.  Is there an extensibility  
>> mechanism for psudoclasses.
>
> Considering that all of ARIA state is in the attribute in the DOM  
> and, as a design principle, ARIA doesn't affect browser operation  
> except for the exposure of content to accessibility APIs, isn't it  
> sufficient and in accordance with the ARIA design principles to use  
> attribute selectors?

For most purposes attribute selectors are sufficient, but attribute  
selectors get tricky in a few scenarios. Take @lang, for example. CSS  
provides a handy pseudo-class:

	q:lang(fr) { /* angle quotes */ }

For non-nested instances of @lang (and ignoring @xml:lang), the  
following attribute selectors would be a sufficient equivalent of that  
pseudo-class.

	q[lang^="fr"],  [lang^="fr"] q { /* angle quotes */ }

But given a set of nested quotes, you may need to override the  
previous selector.

	<q lang="fr"> le foo <q lang="en"> the bar </q> </q>

	q[lang^="fr"],  [lang^="fr"] q { /* angle quotes */ }
	q[lang^="en"],  [lang^="en"] q { /* straight quotes */ }

Which then wouldn't work for the opposite nesting (It would render  
straight quotes on French inside English), and you'd need to have as  
many overridden rules as you could have possible depth in the DOM,  
multiplied by the number of possible languages your web site supports  
[1]. Instead, the browser does all that work on the author's behalf,  
and simplifies it into the :lang pseudo-class.

	q:lang(fr) { /* angle quotes */ }

With that example in mind, consider a menuitemcheckbox [2] that can be  
checked in a number of ways, and be nested in a series of menus, each  
of whose parent menu item may also be a menuitemcheckbox in a  
different "checked" state. The CSS attribute selectors would be  
extremely verbose.

Note: shorthand example uses role as tagName (e.g. <menu> might  
actually be <ul role="menu">)

<menubar>
	<menuitemcheckbox aria-checked="true">
		<span class="check"></span>
		<menu>
			<menuitemcheckbox aria-checked="mixed">
				<span class="check"></span>
				<menu>
					<menuitemcheckbox aria-checked="false">

						<!-- this element may represent the visual checkmark in a GUI  
browser -->
						<span class="check"></span>

					</menuitemcheckbox>
					…
				</menu>
			</menuitemcheckbox>
			…
		</menu>
	</menuitemcheckbox>
	…
</menubar>

Assuming the checkmark was always going to be a direct child of the  
menuitemcheckbox, the selectors may be somewhat terse.

	[aria-checked="true"] > .check { /* checked icon */ }
	[aria-checked="false"] > .check { /* unchecked icon */ }
	[aria-checked="mixed"] > .check { /* partially checked icon */ }

But a developer may want to figure out the checked state of an element  
no matter how deep it was nested inside the closest ancestor  
menuitemcheckbox. Even ignoring a host language equivalent of @aria- 
checked (like @checked) and given that the ancestors :checked states  
may be in any combination, you'd need CSS selectors at least as  
complex as:

	[aria-checked="true"] .check,
	[aria-checked] [aria-checked="true"] .check,
	[aria-checked] [aria-checked] [aria-checked="true"] .check { /*  
checked icon */ }

	[aria-checked="false"] .check,
	[aria-checked] [aria-checked="false"] .check,
	[aria-checked] [aria-checked] [aria-checked="false"] .check { /*  
unchecked icon */ }

	[aria-checked="mixed"] .check,
	[aria-checked] [aria-checked="mixed"] .check,
	[aria-checked] [aria-checked] [aria-checked="mixed"] .check { /*  
partially checked icon */ }

In this case, the UA could/should probably do the work of walking up  
the DOM and determining the closest element that set the checked  
state. It'd be much better to be able to specify that type of ruleset  
as:

	.check:checked, .check:checked(true) { /* checked icon */ }
	.check:checked(false) { /* unchecked icon */ }
	.check:checked(mixed) { /* partially checked icon */ }

Of course there isn't a need for pseudo-class replacements of all ARIA  
attributes, but there are several places where it may make sense and  
should be considered. 'checked' and 'selected' are probably good  
examples. 'required' and 'invalid' may also be worthwhile. There are  
even some special implicit value cases, such as 'aria-haspopup' [3]  
which is false by default but has an implicit value of true if left  
unspecified on an element with the role 'combobox' [4].

Footnotes:
1. Non-Engligh quotation marks: http://en.wikipedia.org/wiki/Quotation_mark,_non-English_usage
2. 'menuitemcheckbox' role: http://www.w3.org/TR/wai-aria/#menuitemcheckbox
3. 'aria-haspopup' property: http://www.w3.org/TR/wai-aria/#aria-haspopup
4. 'combobox' role: http://www.w3.org/TR/wai-aria/#combobox

Received on Thursday, 14 May 2009 23:03:58 UTC