"inert" attribute



The inert attribute would allow web authors to mark parts of the DOM tree as inert:

When a node is inert, then the user agent must act as if the node was absent for the purposes of targeting user interaction events, may ignore the node for the purposes of text search user interfaces (commonly known as “find in page”), and may prevent the user from selecting text in that node.

Furthermore, a node which is inert should also be hidden from assistive technology.

Longer version

Check out the brief, yet comprehensive, inert explainer.

Try out the polyfill.

See it in action on a11ycasts.

What do you think?

My slightly biased opinion: this seems like extremely low-hanging fruit for keyboard accessibility. It’s easy to understand, not too difficult to implement on the browser side, bundles a bunch of useful functionality together yet remains primitive enough to be flexible. It solves a real problem which has existed for a long time and which today has no straightforward solution.

We’re explicitly looking for implementer interest from other browsers, but any feedback would be welcome. Developers: do you have questions/concerns? Is there more we can add (examples, edge cases, etc) to bolster the case? Browser representatives: is there anything technically blocking you from implementing this as outlined in the explainer?


This is so desperately needed. Thank you!

Using an attribute to make entire regions of a document inert is a huge effort- and time-saver. Without inert, one has to walk the DOM and set/remove tabindex on all focusable elements (while maintaining their original values). It’s both a heavy-handed technique and a difficult one for many web developers.

I like that you also noted inert should hide subtrees from assistive technologies since I was unable to tell from reading previous proposals whether that was intended. Hiding subtrees from AT would prevent both keyboard and screen reader users from accidentally navigating inert regions–where tabindex alone would only solve this for the former group.

One thing the inert-polyfill should do now is add aria-hidden="true" to inert regions–as of yesterday it did not.


Hm, the polyfill I linked to has set aria-hidden since the first commit. There was another polyfill floating around, also from Google, which did not - perhaps you’re thinking of that one?


Ah, yes–I must have used the wrong polyfill. The Google one that can be found on npm does not have that functionality. Thanks for the update!


How is this semantically different from the hidden attribute?


hidden affects the visual presentation/rendering; inert does not. Check out the demo page.


sorry about that Marcy! We just published our polyfill to npm: https://www.npmjs.com/package/wicg-inert


hidden affecting visual presentation / rendering is just a matter of applying a different CSS rule (it’s perfectly valid to set a non-none display rule on hidden, though it’s admittedly likely to conflict with the common author-side pattern of including a [hidden] {display: none !important} as part of a page’s base styles) than the suggested rendering by the user-agent; its semantic definition for interaction seems very similar to inert:

When specified on an element, it indicates that the element is not yet, or is no longer, directly relevant to the page’s current state, or that it is being used to declare content to be reused by other parts of the page as opposed to being directly accessed by the user.


Also, the terminology conflicts with the existing meaning of “inert” to refer to DOM content that is not evaluated beyond parsing, ie. the “inert” content of the <template> tag.


Since hidden is typically implemented only using CSS, if you override the CSS styles you also override its behaviour - there is no other behaviour defined in the spec.


A project is likely to use both hidden and inert alongside each other; overriding one for the purpose of the other sounds messy. Inert and hidden serve different purposes–hidden in my experience is a shortcut to CSS display: none, while inert is necessary to create a backdrop for modal dialogs, menus and offscreen contexts that don’t impact the visual design or allow user interaction. This distinction highlights the support gap we are looking to fill with inert.


What about just expanding the disabled attribute to be a global attribute that could be applied to any element, to denote these semantics?


I like this exploration, but I don’t think that’s a workable idea either. disabled form elements etc. have a specific meaning, and are also exposed to assistive technology.


See, that’s the part I’m not wild about about this proposal: it’s going to be equivalent to hidden (semantically) for assistive technologies - the only point on which it differs is for non-assistive use cases, which feels like it’s going to lead to misunderstandings of “oh, inert just lets me disable UI interaction on the element without hiding it” for devs who don’t recognize that there’s a web outside of pointers+screens, meaning that it’d be prone to misuse for elements with semantic importance, whose presence should not be hidden to AT.


Hm, interesting point. Is there a specific scenario you have in mind?


The (mis)use case I’m picturing here is basically anything where I’d use pointer-events: none and user-select: none, like a text-based popup or something else where I’m coding around UA features and think evt.preventDefault() is too much hassle. I discover that there’s this inert attribute, and I go "oh neat, an HTML attribute that’s shorthand for onclick="return false"".


Like, really, the biggest beef I have with this is just bikeshedding that the name inert is semantically bad, which historically leads to disasters around dev (mis)discovery. Like, if it were called something like inaccessible, I’d have less of a problem with it (though I still don’t like how it eats into the use cases for the already woefully-under-and-misused hidden attribute, exacerbating the problems hidden already has around devs not realizing it has aria-equivalent semantic implications).


“inert is necessary to create a backdrop for modal dialogs and blocking contexts that preserve the visual design (while dimmed), but do not allow user interaction.”

So, basically a modal <dialog>? Are there other uses for inert not covered by <dialog>?


The explainer has a few suggestions! https://github.com/WICG/inert/blob/master/README.md#use-cases


Well, to your point, looking at the described use cases, it seems like many of them have the same meaning as disabled form elements (ie. “Form content which is not currently relevant”), and as such, as far as I can tell, should be exposed to AT, the way that disabled form elements are now.