Progressive interface foundations
Control visibility with hidden and inert
Choose hidden for irrelevant content and inert for temporarily unavailable interface regions without creating ghost controls.
Not all unavailable content should be handled in the same way. hidden says an element is not currently relevant, so the browser does not render it. inert leaves a region visible but makes its flat-tree descendants non-interactive and unfocusable.
On the project board, a completed-task panel can be absent from the current view with hidden. During an asynchronous board import, the visible board can become inert while a status panel explains what is happening. This prevents a user from changing controls whose underlying state is being replaced.
<section id="completed" hidden>
<h2>Completed tasks</h2>
</section>
<main id="board">...</main>
<p id="import-status" role="status"></p>
<script>
const board = document.querySelector("#board")
const importStatus = document.querySelector("#import-status")
board.inert = true
importStatus.textContent = "Importing project…"
// After the import: board.inert = false
</script>
Do not use aria-hidden="true" on a region that still contains focusable controls. That can hide an element from an accessibility tree while keyboard focus still reaches it. hidden and inert change actual interaction behavior instead of only changing an accessibility declaration.
An inert region is also excluded from text selection and page find. That is why it is suitable for a short, controlled unavailable state, not a casual way to dim half of a document. Always expose a clear status outside the inert region.
A modal dialog already causes the rest of the document to become inert as part of the browser’s modal behavior. Do not add a home-grown inert loop around every sibling when showModal() is doing that job.
Tab through the board, set board.inert = true in DevTools, and Tab again. The board should be skipped while the outside status stays reachable. Toggle completed.hidden and confirm it disappears from layout. If a visible control inside the board still receives focus, look for a browser support issue or an element rendered outside that subtree.
Lesson completed