HTML inert is a relatively new property, but it is supported in all major browsers since April this year.
When you set inert
on an element, the browser will ignore all user events on it, including tabbing into elements. It will also hide it from screen readers. I like to think of it as a "reversed focus trap". But we can use it to create focus traps for modals by setting inert
on the main content.
This div has inert
property set and if your browser supports it, you won't be able to interact with the button and link below.
React fallback component
Before I learned about inert
, I built a relatively simple component to achieve the same result.
Now I prefer to use the native solution, but on most projects, we still have to support older browsers. My approach is to handle it in the wrapper component, which finds all focusable elements and sets tabindex="-1"
. After mounting, the mutation observer starts listening and re-sets the tabindex when content is changed.
The wrapper itself has aria-hidden="true"
, which hides it from screen readers.
You can try it out on CodePen and see the source code below:
Drawbacks / edge cases
The component uses a pretty simple approach, and it doesn't handle some edge cases:
- The component doesn't check if elements already have the
tabindex
explicitly set. - When the mutation observer triggers, it goes through all of the elements again.
- Depending on your needs, you might need to update
focusableElementsSelector
.
All of that is by design. I wanted to keep it simple to make maintenance easier. I think it is easier to alter specific details on a per-project basis.
For the same reasons, I won't publish it as a npm package. Releasing it as a package would require covering all of these cases and figuring out a flexible public API. I just don't think it is worth the effort. But I do hope you will it useful!