html icon indicating copy to clipboard operation
html copied to clipboard

:focus-within edge cases with DOM mutation and focus moves from within blur/focus event listeners

Open emilio opened this issue 4 months ago • 4 comments

What is the issue with the HTML Standard?

Consider a simple test-case like:

<div id=parent>
  <input id=a>
  <input id=b>
</div>
<input id=c>

When moving focus from a to b, browsers (at least Gecko and Chromium) try to keep the :focus-within state of #parent. Problem is, however, that focus movement is not atomic. The blur event handler of a could move focus to c (so could focusout etc).

Both Firefox and Chromium deal wrongly with that case right now (and other similar cases), see Mozilla bug 1996182 and Chromium issue 454668198.

I'm fixing some of those issues in that mozilla bug, but I'm not super happy with the solution which amounts to basically fixing up the state after realizing that focus has moved.

It'd be good to define better how these pseudo-classes are managed. The obvious solution would be to update :focus-within atomically (like :focus), but that can actually cause problems too, because it's a common pattern to do something like:

.submenu {
  display: none;

  .parent:hover &,
  &:focus-within { display: block }
}

So if we update it along with :focus, there's an intermediate step when moving between the menu items where a forced layout update could hide the menu, see Mozilla bug 1361301 for an example.

So I think we need a reasonable model that defines when are these pseudo-classes supposed to match. What I'm doing in Firefox is not too hard to spec, but again I don't think it's super nice...

cc @annevk @mfreed7 @smaug----

emilio avatar Oct 27 '25 12:10 emilio

cc @whatwg/css @nt1m

annevk avatar Oct 30 '25 08:10 annevk

So for context, what I did on Gecko is: at the same time we try to focus b (after we've blurred a), if we realize we can't (because we have moved focus somewhere else), fix up the :focus-within state and remove it from parent if needed, see the patches in the bug linked in the OP.

emilio avatar Oct 30 '25 09:10 emilio

@emilio you had "write up notes on what you did for Gecko" as a followup from 10/30; not sure where we're going from here or whether this should be back on the agenda?

cwilso avatar Dec 04 '25 01:12 cwilso

Ah, thanks! So the patch is here and basically involves fixing up the focus if we fired the blur event and that changed (or removed) our target so that we don't need to actually focus it anymore.

emilio avatar Dec 04 '25 01:12 emilio