Prompt and setting
The modal must behave as the active surface while the background remains visible but unavailable. The implementation should preserve the opener, support escape and close controls, and avoid relying on a positive tabindex maze.
What the interviewer tests
- Understanding what the
inertattribute blocks and what it does not configure. - Combining native dialog semantics, focus management, and accessible naming.
- Handling nested portals, animation timing, browser support, and reduced motion.
Clarifying questions before answering
- Is this a modal dialog or a non-modal popover that allows background interaction?
- Which element owns the dialog, and where is the portal mounted?
- What should happen to focus on open, cancel, submit, and close?
- Is a browser baseline available, or is a fallback required for older clients?
30-second answer framework
I would use a native modal dialog where possible, move focus to its labelled heading or first meaningful control, and mark only the outside application shell as inert while the dialog is open. I would restore focus to the opener if it still exists, provide Escape and an explicit close button, and test keyboard and screen-reader paths. inert prevents interaction with the background; it does not replace dialog naming, focus restoration, or state management.
Step-by-step deep dive
1. Choose the right semantic surface
Use the native dialog element with showModal() for a true modal when the browser baseline permits it, and provide an accessible name through a visible heading or aria-labelledby. A non-modal disclosure should not make the entire page inert because users are expected to move between surfaces.
2. Isolate the background
Apply inert to the application container that is outside the dialog, not to a common ancestor that also contains the dialog portal. The browser removes the inert subtree from focus navigation and prevents focus events; it also prevents normal user interaction. Do not scatter aria-hidden on ancestors that contain the focused dialog.
3. Manage the focus lifecycle
Capture the opener before opening. On open, focus a stable heading or the first task control rather than an arbitrary close icon. On cancel or successful submit, close the dialog, remove inert, and restore focus if the opener remains visible and enabled. If the opener was deleted, choose a logical nearby target and announce the result.
4. Handle portals and transitions
Render the dialog in a top-level layer so clipping and stacking contexts do not trap it. Set inert before exposing the modal state to interaction, and delay focus until the dialog is mounted. Coordinate entry and exit animation with reduced-motion preferences; never leave the background inert after an interrupted transition.
5. Test the failure paths
Test Tab and Shift+Tab, Escape, close-button activation, validation errors, nested dialogs, route changes, and screen-reader announcements. Verify that clicks, programmatic focus, find-in-page behavior, and pointer events match the browser’s inert behavior. Add a fallback only when the supported browser set requires it, and remove it when native behavior is reliable.
High-quality sample answer
“For a true modal I would use a native dialog, focus its labelled heading or first task control, and set inert on the outside application shell rather than on a portal ancestor containing the dialog. I would capture the opener, restore focus after close, support Escape and an explicit close button, and keep naming and validation semantics separate from inertness. I would test keyboard, screen-reader, portal, animation, and route-change paths, including clearing inert state after an interrupted transition.”
Common mistakes
- Set inert on the app root that contains the portal → the dialog becomes inert too → mount the dialog outside the inert subtree.
- Use inert as a focus-management system → focus can still land in the wrong place on open or close → define a complete focus lifecycle.
- Hide background with aria-hidden while it contains focus → assistive technology sees inconsistent state → move focus first and use inert on the background.
- Forget interrupted transitions → the page remains locked → clear inert state in every close and unmount path.
Follow-up questions and responses
Does inert replace a focus trap?
It prevents the background from being focusable, so a modal can often avoid a hand-written trap. You still need to place initial focus, restore it, name the dialog, and handle browser or component fallbacks.
Can a non-modal drawer use inert?
Only when the product intentionally makes the background unavailable. For a non-modal drawer that permits background interaction, do not mark the page inert; use appropriate disclosure semantics instead.
What if the opener disappears?
Restore focus to the nearest logical control, such as the updated row or page heading, and announce the result when needed. Never attempt to focus a detached or disabled element.