require-dialog-autofocus
Requires a <dialog> element shown via the show-modal command to contain a descendant (or itself) with the autofocus attribute.
When a modal dialog is shown via showModal(), the browser executes the dialog focusing steps. Without autofocus, focus falls back to the <dialog> element itself. While functional, this is not ideal for accessibility — screen reader users may miss the dialog content, and keyboard users may need extra tab presses to reach interactive elements.
Authors should use the autofocus attribute on the descendant element of the dialog that the user is expected to immediately interact with after the dialog opens.
Cite: HTML Living Standard: The dialog element
This rule uses the Invoker Commands API to statically detect modal dialogs: a <button> with command="show-modal" and commandfor pointing to a <dialog> element indicates that the dialog will be shown as a modal.
[!WARNING] Default severity is
warningbecause the HTML spec recommends (should) but does not require (must) the use ofautofocus. Withoutautofocus, the dialog focusing steps still provide a fallback that moves focus to the dialog element or its first focusable descendant.
[!NOTE] This rule relies on the Invoker Commands API (
command/commandforattributes). If your project does not use this API (e.g., you open dialogs viadialog.showModal()in JavaScript), this rule will not detect any violations. The Invoker Commands API reached Baseline support in early 2026.
Rule Details
❌ Incorrect
<button command="show-modal" commandfor="my-dialog">Open</button>
<dialog id="my-dialog">
<p>This dialog has no autofocus element.</p>
<button command="close" commandfor="my-dialog">Close</button>
</dialog>
⭕ Correct
<!-- autofocus on an input descendant -->
<button command="show-modal" commandfor="my-dialog">Open</button>
<dialog id="my-dialog">
<input type="text" autofocus />
<button command="close" commandfor="my-dialog">Close</button>
</dialog>
<!-- autofocus on a button descendant -->
<button command="show-modal" commandfor="my-dialog">Open</button>
<dialog id="my-dialog">
<button autofocus command="close" commandfor="my-dialog">Close</button>
</dialog>
<!-- autofocus on the dialog itself -->
<button command="show-modal" commandfor="my-dialog">Open</button>
<dialog id="my-dialog" autofocus>
<p>Content without interactive elements.</p>
</dialog>
Scope
This rule only checks <dialog> elements that are referenced by a <button> with command="show-modal". Other command values (e.g., close, toggle-popover) are not in scope.
Dialogs that are opened programmatically (via showModal() in JavaScript) or dialogs without a declarative trigger are not checked. If your project does not use the Invoker Commands API, this rule will not report any violations.
Non-dialog elements referenced by commandfor are also skipped. The command value comparison is case-insensitive per the HTML spec.
Known Limitations
- JavaScript-triggered dialogs: Dialogs opened via
dialog.showModal()in JavaScript without the Invoker Commands API cannot be detected by static analysis. - Dynamic
autofocus: Ifautofocusis added dynamically via JavaScript (e.g.,element.setAttribute('autofocus', '')), this rule cannot detect it. - Focus placement quality: This rule checks only whether
autofocusexists, not whether it is placed on the most appropriate element. For guidance on where to place initial focus, see the WAI-ARIA APG: Modal Dialog Pattern.
See Also
- Issue #689
- HTML Living Standard: The dialog element
- HTML Living Standard: Dialog focusing steps
- WAI-ARIA APG: Modal Dialog Pattern
- Invoker Commands API Explainer
- MDN: autofocus
Interface
{
"require-dialog-autofocus": boolean
}
Default Severity
warning