Does HTML `autofocus` only work on a limited class of elements?

57 Views Asked by At

I don't see any constraints listed at MDN.

However, despite putting autofocus on the second list item in this code, the document.activeElement on page load is <body>:

<ul>
  <li>1</li>
  <li id="two" tabindex="1" autofocus>2</li>
  <li>3</li>
</ul>
<button type="button" id="button1">First button</button>
<button type="button" id="button2">Second button</button>

By contrast, placing autofocus (exclusively) on the second button (button2) does cause that to be the active element on page load.

So, does autofocus only work on certain elements?

Is the only way for the page to load with a focus on the second list element through

document.getElementById("two").focus();
1

There are 1 best solutions below

2
Kaiido On

The issue is more likely that the focusing steps are performed after the load event is fired.

The relevant specs are at https://html.spec.whatwg.org/multipage/interaction.html#flush-autofocus-candidates.

From this we can derive that for the autofocus attribute to do something at page load, we need:

  • The document to be same-origin with the top-most document, i.e. not in a cross-origin iframe, and thus hard to show in an REPL here...
  • The element to be a focusable area, otherwise the closest such focusable-area will be chosen.

If we assume you ran this code in its own page, then you met both conditions and it is supposed to work.

Now, if you do log the activeElement in the load event, you may be before the next flush autofocus candidates which happens during the update the rendering steps of the event-loop and is thus unrelated to the loading of the document. To be sure to run after that initial flush, you can use requestAnimationFrame() which will queue a callback to fire a bit after that step.

As for why you saw it work when only the <button> had the attribute, I guess it was just a fluke.

Here I set up a glitch project demonstrating the issue, sometimes (needs a few refresh on my Chrome to meet it, Firefox reproes only on the initial navigation but not on refresh, and Safari reproes 100% of the time).