Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[selectors] :focusable pseudo-class #7269

Open
LeaVerou opened this issue May 11, 2022 · 13 comments
Open

[selectors] :focusable pseudo-class #7269

LeaVerou opened this issue May 11, 2022 · 13 comments
Labels

Comments

@LeaVerou
Copy link
Member

LeaVerou commented May 11, 2022

I was reading this article and I reached this gem:

const FOCUSABLE_SELECTORS = [
  '[contenteditable]',
  '[tabindex="0"]:not([disabled])',
  'a[href]',
  'audio[controls]',
  'button:not([disabled])',
  'iframe',
  "input:not([disabled]):not([type='hidden'])",
  'select:not([disabled])',
  'summary',
  'textarea:not([disabled])',
  'video[controls]',
].join(',');

Authors should not have to do all this just to target focusable elements (not to mention even this won't catch some…). Adding a pseudo-class for focusability seems like pretty low-hanging fruit (so low-hanging that I'd swear I've seen it discussed before, but I couldn't find anything so…)

@bkardell
Copy link
Contributor

I would also swear I have seen this discussed both in this context and probably linked to the focus metabug or related issues. One problem (I'm sad to write this) is "what does focusability mean" is not 100% clear. Things can be in sequential focus order, they can be focusable with a pointer, programatically focusable, that can vary by browser (one reason this might be nice to figure out) --- but even after that all of those things are just potential candidates, because whether something is actually focusable in any of those is ultimately determined by whether it is actually displayed too (and probably other things). So, it kind of seems to raise a lot of questions beyond just being a simple alias.... I'd be very interested in seeing some proposals around this sort of thing tho because focus is pretty messy.

@jimmyfrasche
Copy link

My (perhaps naive) expectation is that it would mean whatever is necessary so that if I called the focus method on a node that matches :focusable that element would then become the document.activeElement.

@bkardell
Copy link
Contributor

My (perhaps naive) expectation is that it would mean whatever is necessary so that if I called the focus method on a node that matches :focusable that element would then become the document.activeElement.

That would imply that something that was display:none wouldn't be returned by querySelector though right? In CSS, with that definition you could easily write "if you're focusable be hidden" (which makes you not match that definition of focusable)... But also, you can set the focus to any element if it is overflowed, and the rule could say "don't overflow". I feel like we'd need something a little more explicit and nuanced. It could be a simple alias, it's just that you'd need to know a lot more to use it because the candidates wouldn't actually tell you if they were focusable, necessarily, maybe.

@LeaVerou
Copy link
Member Author

LeaVerou commented May 11, 2022

FWIW, my expectation was similar to what @jimmyfrasche described above.

It could be a simple alias

It shouldn't. We already have proposals [1, 2] where focusability is affected via CSS properties.

@jimmyfrasche
Copy link

If it can't include/exclude everything then :focusable is a bad name and it should be renamed to something like :focusable-candidate.

Related, maybe 90% of my focus woes would be fixed by a javascript api that let me focus the element that the user would land on if they hit tab/shift+tab if focus was on a particular element so I could move focus off my component without having to know about the world outside its perimeter, something like document.focusNext({from: myComponentRoot})

@Loirooriol
Copy link
Contributor

This seems problematic due to circularities like :focusable { display: none }

Also, in Blink element.focus() inside content-visibility: auto forces style computation in order to determine if the element is focusable. Having :focusable do that would defeat content-visibility: auto.

So :focusable-candidate can be better but it's not clear how it should be defined.

@emilio
Copy link
Collaborator

emilio commented May 16, 2022

Yeah, also in all browsers visibility: hidden prevents focusability.

@emilio
Copy link
Collaborator

emilio commented May 16, 2022

(And scrollers are focusable by keyboard iff they are scrollable, so that would be another source of circularity)

@kizu
Copy link
Member

kizu commented Apr 18, 2023

In my practice, I would probably need to only be the “alias”, so something like :focusable-candidate would be very welcome.

It could be defined as something that could be focusable when there are no styles applied, basically, browser would need to only look at the HTML of an element, and don't do anything with styles.

More to that — in my use-cases the :focusable would almost always go alongside :hover or :active, as I often want to style something that is located inside an interactive hovered element (and not just any hovered element). We already can do this for focused elements, but can't for hovered.

@woody-li
Copy link

woody-li commented Aug 3, 2023

What about tabbable, the difference is negative tabindex cases.
According to the specification, focusable includes all non-null tabindex values.

The focusable almost equal to elements which can be focus by tab key.
So I suggest rename as tabbable, or both focusable and tabbable.

  • focusable contains all non-null tabindex.
  • tabbable only contains non-negative tabindex.

@LeaVerou
Copy link
Member Author

LeaVerou commented Aug 3, 2023

That's an interesting idea. Whether it's a good path forwards depends on the use cases for targeting focusable elements. Do we have a list of use cases?

@jimmyfrasche
Copy link

If this existed one thing I'd use it for would be quick debugging css (:focusable{outline:3px dotted hotpink}) but the main thing I'd want to do is find the next :focusable in js and focus it for when I need to manage focus exiting a complex component (cf my previous comment in this thread)

@woody-li
Copy link

woody-li commented May 17, 2024

In some cases, need custom tab navigation focus, so need to know which element is focusable.

A difficult case is the keyboard-focusable scroll containers.

It's hard to make it compatible with browsers support it or not.

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

No branches or pull requests

7 participants