Closed frivoal closed 5 years ago
I’m not sure if this is where you want this comment. But what I’ve been trying to get to in some of my other comments, is a way to specify, in CSS, that an element can be tabbed to or arrowed to (previously imagined as tab-index:0
and arrow-index:0
).
Maybe something like focusable: [tab | arrows | none]
.
I wasn’t clear from the prose whether spacial-navigation: active
was supposed to make an element navigable by arrows, or if it was something that applied to an ancestor. But if I was creating a component, like say, something that acted like radio buttons, then I would need to say when something could be tabbed to, and when something could only be arrowed to. So, something like this, I guess:
div.radio-group { spatnav-container: create; }
span.radio-button { focusable: arrows; }
span.radio-button.checked,
span.radio-button:first-child:not(:has(+ .checked)) { focusable: tab; }
(That last line only works declaratively if :has() is usable on the Web. Otherwise, would have to use JavaScript to track when there are no “checked” classes on the buttons, and set a separate class to indicate that on the radio group parent).
Is there some other way to achieve this using the spec properties?
Maybe something like focusable: [tab | arrows | none].
Or maybe focusable: [main | secondary | none]
, to account for keyboardless navigation.
@bradkemper it sounds like we had the same idea :) Did you see my comment?
@hugoholgersson I have now. Yes, seems pretty similar.
As someone who has recently been adding keyboard and AT usability to pop up menus, nav dropdown menus, light boxes, etc., my view is that being able to easily control WHICH elements are focusable or not (via CSS) is a more urgent problem than any of the rest.
@bradkemper This is not at all what I planned to be doing with this issue, but I wasn't clear, and this is more important topic than the original one :D
I wasn’t clear from the prose whether spacial-navigation: active was supposed to make an element navigable by arrows, or if it was something that applied to an ancestor.
It was meant to be applied to ancestors, so that's a separate thing. (and it's probably going to be dropped or pushed to the next level anyway, see https://github.com/WICG/spatial-navigation/issues/35)
I’ve been trying to get to in some of my other comments, is a way to specify, in CSS, that an element can be tabbed to or arrowed to (previously imagined as tab-index:0 and arrow-index:0).
Maybe something like focusable: [tab | arrows | none].
This issue has come up before in the CSSWG. I think last time the rough conclusion was that although selectors may be a convenient way to set this up, there was no strong coupling between focusability and style, while there was strong coupling between focusability and semantics (i.e. HTML/DOM) and between focusability and attached behaviors (JS/DOM).
The fact that this isn't about styling isn't a blocker in my mind, but and selectors are a nice mechanism. But the fact that it doesn't seem to be strongly coupled with style does make me question whether it belongs in CSS.
I think it would be very interesting if we could restart that discussion (here or even better in the CSSWG) base on use cases that support:
Since you've been working on that sort of things, do you think you could write these down?
Do we need to distinguish navigation methods? I doubt authors would like to disable one but not the other...
Perhaps focusable: auto | none
is enough to begin with? That should be future-compatible with whatever (spatial) navigation method we come up with next.
@frivoal let me get back to you on that, when I have time to be more complete. Mostly because it would be sooooo much easier and probably more performant to use the CSS engine and CSS rules, rather than complicated fiddling with adding and removing and changing tabindex attributes every time a key is pressed or focus changes. I know I’m near the boundary line at the edge of what CSS is for, but so is the 'resize' property, and so are the other things being discussed. I want to move the line, if needed, to be able to use CSS in this hugely beneficial way.
@hugoholgersson for component-like things, I want to be able to do what native elements do with keyboard control. Which means that when you tab to a radio button, menu, etc., then you can use arrow keys to move focus within it, or tab to exit the component. So, that is two different levels of focusing.
I agree there's a fuzzy border, and last time this was discussed in the csswg, I was the one pushing for it, so I'm sort of with you on that one. The questions I listed above are the ones that would help convincing me (and hopefully others) that we're on the correct side of the fuzzy border.
As for "2 levels of focusing" withing native elements, I'm still confused on this one (really, not pretending to be confused just to be polite while disagreeing): is that indeed a form of focusing that needs to respond to some keys but not others for usability's purpose, or is that something else than focusing ("selection"? that word is already used for text selection), somewhat more akin to changing the state of a control than changing which control has the focus? I don't have a good answer, nor a clear idea on how to get to an answer. Help figuring this out (possibly with copious amount of examples) much appreciated.
@frivoal I think it might be a distinction without a difference. The only interactivity difference I can see between changing focus between controls and changing focus (or whatever you’d call it) within a control, is what key you use to do it.
Pragmatically, when building a UI component, '.focus()', ':focus', and '.setAttribute("tab-index", "0|-1") are the tools I use now if I want to follow best keyboard practices for navigating controls like radio buttons, menus, tabs, trees, and the like, where the internal thing has to be focused before it can be changed. I’d have a hard time thinking of that as anything other than focus.
Please see this, if you haven’t already: https://www.w3.org/TR/2017/NOTE-wai-aria-practices-1.1-20171214/#kbd_general_within
That page also talks about aria-activedescendant, which maybe more in line with your alternative view of focus vs. “active” (as they call it there). In that method, the parent has the actual focus, and the descendant that is active gets the focus outline. But I consider that a much more awkward way of managing focus, compared to roving tabindex, especially considering things like radio buttons, which are typically siblings, not descendants of something with focus.
I also don’t know if aria-activedescendant has much support with browsers and/or screen readers, and so is probably not used much. Roving Tab-index is, and provides a good mental model for something like focusable: [main | secondary | none]
.
So, I’d like to say that I am a big fan of separating content from presentation. But a certain amount of interactivity is part of the presentation that the Web designer has to consider when designing. We should embrace that, and not be too hesitant about adding features to CSS that make it easy to add even more interactive control to the Web.
When designing and creating a menu bar, for example, one has to design and create the different states its menus can be in. The easiest and most powerful way is declaratively, using CSS selectors and rules. So, for instance, this is easy:
.menubar > button:not(:hover) ~ .menu { display: none }
It could be argued that this is more about interactivity than presentation. The display: none
is not really there to style anything. It, and the selector for this rule, exists entirely to make the menu interactive. In fact, I think it is likely that display:none
is used more for interactive behavior than for anything that could be strictly described as stylistic. It is often used in conjunction with :hover
and :focus
, which are only about interactivity, or with class names added via JavaScript that are only there to show or hide something, not to style it.
But thank God. If these all only existed in JavaScript, and not CSS, life for authors would be far worse off.
Note that display: none
also prevents focusing it or its descendants. That’s a side effect now, but an important one that is lacking in, say, opacity:0
or position: absolute; left:-100vw
. I want better control of that as a primary effect, without having to hide the element, and without having to resort to JavaScript (other than maybe using JavaScript to add or remove a class, sometimes).
Note that we have a pointer-events
property that can enable or disable the clickability of an element in CSS. Why not a property that can similarly enable or disable the focusability of an element, or set the level of focusability? Bring it on, I say.
These aren’t the only examples of CSS being used more for interactivity than for static styling of how it looks:
resize
property lets an element become resizable by the user, and there is not even any author control of what that resizing widget looks like or where it is placed. It is purely about enabling interactive behavior. will-change
property is more about performance optimizations than about visual style. overflow:auto|scroll|clip
is primarily about enabling or disabling interactivity of user scrolling. It is much more about interacting with the content than of visually styling it. user-select
is another behavior-altering property that doesn’t actually change visual style. It enables and disables the ability to select text or other elements on the page. Conceptually, it isn’t so different from my proposed property to enable and disable the ability to focus an element on the page. user-modify
, while not on a standards track, is supported by Safari, Chrome, and Edge. It is similar to thecontenteditable
html attribute, but somewhat easier to apply declaratively, because: selectors and the cascade. A read-write
value does make an element focusable, but it also, you know, makes it writable. And it can’t be used to turn off focusability of things like anchors or text inputs. Currently, supporting keyboard access by following ARIA recommendations for various component-like HTML constructions is not easy. It involves updating attributes, such as tabindex, on multiple elements at the same time, every time a key is pressed or focus is changed with that construction, based on event handlers that have to be added to those elements. These types of constant DOM updating can cause layout thrashing. It is also easy to sometimes end up with the wrong elements focusable/un-focusable, due to some tricky situations that the author’s code might not account for correctly, such as when the user clicks into another window and the blur event doesn’t have a relatedTarget, then the user clicks back in onto something else that takes the focus.
Also, when arrowing through a component-like thing, you want it to either stop when it gets to the beginning or end, or to wrap around to focus the last or first focusable part. So, a CSS focus-containment property that could be set on a parent or ancestor would make that a lot easier. This would be especially true if the user is using VoiceOver-keys or other means to advance the AT-focus to the next-previous element. In that case, there is no way to detect in JavaScript when the user has left the component, unless/until they advance to something that actually triggers a blur or focus event (using VoiceOver to advance to a paragraph that is non-focusable does not trigger any detectable events, AFAICT). But a focus-containment property could potentially contain that kind of pseudo-focusing too, replicating the way VoiceOver stops advancing when it gets to the last OPTION in a SELECT.
I agree with all the above, and will happily repeat similar arguments to any CSSWG member who disagrees.
I still have some doubts that makes we wonder if making things focusable in CSS is the right thing to do or not:
pointer-events
or display:none
can hide/deactivate things from CSS for clicking / focusing purposes. I haven't though too much about it, but for the reasons you list above, I don't think I would have an issue with a property that can remove focusability from things that have it. However, that's not what you're proposing. You're proposing adding focusability from CSS to things that don't have it.
I am more skeptical about that because I believe that adding focusability alone is generally not useful, and that you typically need to also add some event handler to do something useful when the now focusable element is focused / activated. That will be done in JS, not in CSS. So that makes me think that making things focusable should also be in JS, to avoid things getting out of sync.
For me, it is a matter of separation of concerns in the sense of putting together the things that are tightly coupled together, not in the sense of separating presentation from style.
However, if there is a reasonable use case for making things focusable and then attaching no additional behavior at all via JS, then it seems OK to have it in CSS.
@bradkemper Are you attending the Berlin F2F of the CSS-WG?
I don't think i am, but i can call in
On Thu, Apr 5, 2018, 3:18 AM Florian Rivoal notifications@github.com wrote:
@bkardell https://github.com/bkardell Are you attending the Berlin F2F of the CSS-WG?
— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/WICG/spatial-navigation/issues/25#issuecomment-378842735, or mute the thread https://github.com/notifications/unsubscribe-auth/AA1IZa-RFvvmICkDZRd3Ux27L1k9FZRwks5tlcU0gaJpZM4SH73N .
@bkardell Sorry for the noise, I meant to ping @bradkemper since he raised this issue, but your names start by the same letter and I wasn't careful enough with autocomplete.
Issue migrated to w3c/csswg-drafts#3379
Other specs (most likely HTML) will probably find it convenient if we define a hook in the "Handling key presses" section to let them define what a particular element does when arrow keys are pressed and that element wants to respond (e.g. the<select>
element changing which is the currently selected<option>
).EDIT: The discussion in this issue moved to a completely different, and more interesting topic. Repurposing the issue to talk about that.