Could we help you? Please click the banners. We are young and desperately need the money
The inert HTML attribute, when applied to an element, allows us to prevent user interaction with the element as well as its children. Specifically the following types of interaction are prevented:
Furthermore, inert elements are hidden from assistive technologies. This makes the attribute a convenient and effective method for preventing user interaction whilst retaining accessibility.
A basic application of the inert attribute is for preventing interaction with a section containing interactive elements, essentially disabling the section.
<div inert>
<button onclick="alert('This text will never be alerted')">
You can't click me
</button>
</div>
This basic usage of inert can be extended in combination with dialogs and modals where inert is used to disable elements in the background. This prevents the user from accidentally triggering something outside of the dialog or modal and assures that the focus remains contained.
<body>
<main id="page-content" inert>
Some interesting content
<button onclick="alert('This text will never be alerted')">
You can't click me
</button>
</main>
<dialog open>
Hello World!
</dialog>
</body>
The inert attribute can be toggled through JavaScript using the inert property of an element.
element.inert = true; // enables inert on element
element.inert = false; // disables inert on element
Inert is baseline available since April 2023. According to caniuse, over 90% of browsers in usage support it. However, if this support does not suffice for your needs, there are of course traditional alternatives that can be used over inert.
Applying the CSS property pointer-events with a value of none to an element will prevent users from interacting with it through the mouse.
#prevent-mouse {
pointer-events: none;
}
Applying the CSS property user-select with a value of none to an element will prevent users from selecting any contained text.
#prevent-selection {
user-select: none;
}
This one's more tricky to achieve without inert and requires us to do some manual focus management using JavaScript. The idea is that we have a range of elements within which we want to trap our focus. If the focus leaves the range, we force it back into it, ideally creating a "wrapping" effect. "wrapping" effect means that if the focus goes beyond the last element of the range, the focus is reset to the first element and vice-versa.
The following function takes a wrapper element and traps the focus within its focusable elements. The function returns another function that, if called, sets the focus free again (untraps it).
function trap_focus(wrapper) {
const focusable_range = Array.from(wrapper.querySelectorAll(
'a[href], button, input, textarea, select, details, [tabindex]:not([tabindex="-1"])'
));
const first_element = focusable_range[0];
const last_element = focusable_range[focusable_range.length - 1];
const handle_trap = e => {
if (e.key !== 'Tab') {
return;
}
if (e.shiftKey) {
if (document.activeElement === first_element) {
last_element.focus();
e.preventDefault();
return;
}
}
else if (document.activeElement === last_element) {
first_element.focus();
e.preventDefault();
return;
}
if (!focusable_range.includes(document.activeElement)) {
first_element.focus();
e.preventDefault();
}
}
document.body.addEventListener('keydown', handle_trap);
return () => {
document.body.removeEventListener('keydown', handle_trap);
};
}
Use it like so:
const untrap_wrapper_element = trap_focus(wrapper_element); // traps focus
untrap_wrapper_element(); // untraps focus