Skip to content

[css-overflow-5]: resolving document.activeElement and focus event targets #12239

Open
@smhigley

Description

@smhigley

Current behavior

When tabbing and arrowing between the scroll-buttons and scroll-markers, focus events fire but the document.activeElement does not change. Even worse, event.target and event.relatedTarget directly reference the CSS pseudo-elements and do not match document.activeElement.

Problem

A common part of writing focus handling logic is comparing target and relatedTarget to activeElement in focus events; if overflow scroll buttons and scroll markers depart from how those are expected to work in all other focus-affecting user interactions, it will almost certainly both break existing focus management scripts and also make it either significantly harder or impossible to write logic handling UI that contains carousels in the future.

The other issue is that saving a reference to event.target and calling .focus() on it also results in a console error (since pseudo-elements aren't HTMLElements and don't support the .focus method). This is a very common way to handle saving the element to return focus to when something like a dialog, popup, or other type of UI opens and then closes.

I can't think of another instance where a focus event's target or relatedTarget would be an Element that is not an HTMLElement, but there could easily be an edge case I'm not thinking of. Even if there is, I'd lean against adding another one.

Possible solutions

I'm sure there are more potential ways to resolve this, these are just my initial thoughts:

  1. No focus events fire when focus changes between pseudo-elements
  2. Pseudo-elements are exposed and can be referenced by a selector in some way
  3. Focus events fire, but the event.target and event.relatedTarget are the same, and document.activeElement would not change

I'd lean towards (1), since it matches what happens in controls like <input type="date">, and presents the fewest high-level changes (at least that I can think of). The second option would require some pretty significant updates to the DOM Node interface, and the third would break a pretty longstanding assumption about how focus events work, with potentially wide-reaching and breaking effects on existing focus-related scripting.

With any of the solutions, I don't think it's a good idea for event.target and event.relatedTarget to continue directly referencing pseudo-elements.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions