inert

Background

The inert attribute was originally specced as part of the <dialog> element specification. <dialog> required the concept of inert to be defined in order to describe the blocking behaviour of dialogs, and the inert attribute was introduced “so you could do <dialog> without <dialog>.

The attribute was later removed as it was argued that its only use case was subsumed by <dialog>. However, later discussion on the original bug proposed several use cases which could not be handled, or only handled poorly, using <dialog>.

Spec

The spec for the inert attribute, with the existing definition of “inert” already specified, is extremely straightforward:

The inert attribute

The inert attribute is a boolean attribute that indicates, by its presence, that the element is to be made inert.

When an element has an inert attribute, the user agent must mark that element as inert.

</div>

By default, there is no visual indication of a subtree being inert. Authors are encouraged to clearly mark what parts of their document are active and which are inert, to avoid user confusion. In particular, it is worth remembering that not all users can see all parts of a page at once; for example, users of screen readers, users on small devices or with magnifiers, and even users just using particularly small windows might not be able to see the active part of a page and may get frustrated if inert sections are not obviously inert. For individual controls, the disabled attribute is probably more appropriate.

Spec gaps

The case for inert as a primitive

Developers find themselves in situations where they’d like to be able to mark a part of the page “un-tabbable”. Rob Dodson lays out one such example in his article “Building better accessibility primitives”:

One problem: to [achieve a performance optimisation for animation] we must leave the drawer in the DOM at all times. Meaning its focusable children are just sitting there offscreen, and as the user is tabbing through the page eventually their focus will just disappear into the drawer and they won’t know where it went. I see this on responsive websites all the time. This is just one example but I’ve also run into the need to disable tabindex when I’m animating between elements with opacity: 0, or temporarily disabling large lists of custom controls, and as others have pointed out, you’d hit if you tried to build something like coverflow where you can see a preview of the next element but can’t actually interact with it yet.

inert would also allow slightly more straightforward polyfilling of both <dialog> and the proposed, more primitive blockingElements API. See Polymer Labs’ blockingElements polyfill, based on this polyfill, for an example of how inert may be used for this purpose. Currently, since there is no way to express the “inertness” concept, polyfilling these APIs requires both focus event trapping to avoid focus cycling out of the dialog/blocking element (and thus as a side effect may prevent focus from walking out of the page at all) and a tree-walk (usually neglected by developers) to set aria-hidden on all sibling elements of the dialog or blocking element.

On the implementer side, the vast majority of work involved in implementing inert is a necessary pre-cursor to both <dialog> and blockingElements implementations, so by implementing inert first, implementers may get useful functionality into the hands of developers sooner while still laying the groundwork for one or both of these more complex APIs.

Use cases

Wouldn’t this be better as…