Use the inert attribute to prevent unintended user interaction
Web design is all about making efficient use of the available space. You don't want to clutter the screen with too much content. This is the reason for common patterns like slide-in submenus, expansion panels, popups or dialogs.
Often, these elements are implemented as custom widgets with an insufficient hidden state. They use CSS code
like opacity: 0
or position: absolute; left: -10000px
to
hide the content only visually. But users can still access the content with the keyboard or assistive technologies.
What can we do about it?
Photo: © Roxanne Minnish / pexels.com
You can use the HTML attribute inert
to prevent any interaction with hidden content. A kind of
digital sloth, so to say. Let's take a closer look at the attribute that is now supported by all major browsers.
How the inert
attribute works
The inert property is a global HTML attribute that tells the browser to prevent any user interaction with a specific section of content. The HTML specification states:
The inert attribute is a boolean attribute that indicates, by its presence, that the element and all its flat tree descendants [...] are to be made inert by the user agent.
This means that all user input events for the element and its descendants are ignored, including focus events and events from assistive technologies.
For example: Let's say you place a registration form off-screen and let it slide into view
when the user presses a certain button. Adding inert
to the <form>
element ensures that a keyboard user cannot accidentally interact with the form elements while they're off-screen. The
content will also be hidden from screen reader users.
The native <dialog>
element also makes use of this. When you open a modal dialog
with .showModal()
, the browser will automatically render all other content inert.
Find out more in my blog post “Why you should use the Native Dialog Element”.
Use Case: Animated Navigation Menu
I've created a demo for an animated navigation menu that
uses the inert
attribute for its hidden submenus. It works well for keyboard and screen reader users:
The navigation menu is structured as an unordered list inside a nav element. The HTML code for a menu option and its hidden submenu looks as follows:
<button type="button" aria-expanded="false" aria-controls="sub_menu_research">
Research
</button>
<div id="sub_menu_research" class="subMenu" inert>
<ul>
<li><a href="/black-holes">Black Holes</a></li>
<li><a href="/climate-change">Climate Change</a></li>
<li><a href="/modern-way-of-work">Modern Way of Work</a></li>
</ul>
</div>
In my CSS code, I reference the inert attribute to also visually hide the submenu:
.subMenu {
overflow: hidden;
}
.subMenu[inert] > ul {
transform: translateY(-100%);
}
When the menu option is activated, the inert
attribute is removed and the submenu slides into view:
.subMenu:not([inert]) > ul {
transform: translateY(0);
}
The creation of the slide animation is pretty easy and straightforward using the transition
CSS property:
.subMenu > ul {
transition: transform 0.4s ease-in-out;
}
You can view the complete source code here.
Wouldn't display: none
do the job?
Some of you might be thinking: “Why should I use the inert attribute? I can simply hide stuff with
display: none, duh!” You're right. When you apply the CSS property display: none
to an element, it won't be rendered by the browser and is hidden from assistive technologies. The downside: You
won't be able to animate the element any more.
Using the inert
attribute gives you more flexibility. You can let your content fade in and out,
slide into view or create any sophisticated animation you can think of. Also, you'll want to use the attribute for content
that is visible but should not be interacted with. For example, the partially visible previous and next slide in
a carousel widget.
Browser Support
Firefox finally added support for inert
in version 112. This means that
all major browsers support the attribute now.
Yay! Let's go and build cool stuff with it.
Posted on