Bug report
Current behavior
When a modal Dialog (or AlertDialog) opens, FloatingFocusManager applies aria-hidden="true" to all background elements to hide them from assistive technology. However, it does not remove those elements from sequential focus navigation. This means focusable elements (links, buttons, inputs) remain tabbable while sitting inside an aria-hidden="true" subtree which violates WCAG 2.1 SC 4.1.2.
Flagged by IBM Equal Access Checker and axe-core as:
Rule: aria_hidden_nontabbable / Reason: Fail_1
"Element should not be focusable within the subtree of an element with an aria-hidden attribute with value 'true'"
Expected behavior
Background elements should be removed from both the accessibility tree and sequential focus navigation when a modal opens. This is best achieved using the inert HTML attribute rather than relying solely on aria-hidden="true".
Reproducible example
Open any Dialog in docs and run IBM Equal Access Checker or similar tool
Base UI version
v1.4.1
Which browser are you using?
Firefox
Which OS are you using?
Windows
Which assistive tech are you using (if applicable)?
Tested with IBM Equal Access Checker and axe-core.
Additional context
Affects: Dialog, AlertDialog, and any component using modal FloatingFocusManager.
Root cause
FloatingFocusManager calls markOthers with ariaHidden: true when a modal opens, but never passes inert: true:
// FloatingFocusManager.tsx
const ariaHiddenCleanup = markOthers(insideElements, {
ariaHidden: modal || isUntrappedTypeableCombobox,
mark: false,
})
aria-hidden only removes elements from the accessibility tree. The inert HTML attribute (supported in all modern browsers) removes elements from both the accessibility tree and sequential focus navigation which is exactly what a modal background needs.
supportsInert() is already supported and full inert plumbing... it's just never used in this call path.
Suggested fix
Update the call to use markerInsideElements (for consistency with the marker call) and pass the inert flag conditionally based on browser support (supportsInert()).
Workaround
Observe data-base-ui-inert (the marker attribute already set by the second markOthers call) via MutationObserver and mirror inert onto the same elements.
Note: data-base-ui-inert is also applied to base-ui's focus guard sentinel elements. Those must be excluded, making them inert removes them from the tab order and breaks focus trapping, allowing Tab to escape to the browser chrome.
function useInertBackground() {
useEffect(() => {
const observer = new MutationObserver((mutations) => {
for (const mutation of mutations) {
if (mutation.type !== 'attributes') continue
const el = mutation.target as HTMLElement
// Skip focus guard sentinels — base-ui uses these to bounce Tab back
// into the dialog. Making them inert breaks focus trapping entirely.
if (el.hasAttribute('data-base-ui-focus-guard')) continue
if (el.hasAttribute('data-base-ui-inert')) {
el.setAttribute('inert', '')
} else {
el.removeAttribute('inert')
}
}
})
observer.observe(document.body, {
subtree: true,
attributes: true,
attributeFilter: ['data-base-ui-inert'],
})
return () => observer.disconnect()
}, [])
}
Bug report
Current behavior
When a modal
Dialog(orAlertDialog) opens,FloatingFocusManagerappliesaria-hidden="true"to all background elements to hide them from assistive technology. However, it does not remove those elements from sequential focus navigation. This means focusable elements (links, buttons, inputs) remain tabbable while sitting inside anaria-hidden="true"subtree which violates WCAG 2.1 SC 4.1.2.Flagged by IBM Equal Access Checker and axe-core as:
Expected behavior
Background elements should be removed from both the accessibility tree and sequential focus navigation when a modal opens. This is best achieved using the
inertHTML attribute rather than relying solely onaria-hidden="true".Reproducible example
Open any Dialog in docs and run IBM Equal Access Checker or similar tool
Base UI version
v1.4.1
Which browser are you using?
Firefox
Which OS are you using?
Windows
Which assistive tech are you using (if applicable)?
Tested with IBM Equal Access Checker and axe-core.
Additional context
Affects:
Dialog,AlertDialog, and any component using modalFloatingFocusManager.Root cause
FloatingFocusManagercallsmarkOtherswithariaHidden: truewhen a modal opens, but never passesinert: true:aria-hiddenonly removes elements from the accessibility tree. TheinertHTML attribute (supported in all modern browsers) removes elements from both the accessibility tree and sequential focus navigation which is exactly what a modal background needs.supportsInert()is already supported and fullinertplumbing... it's just never used in this call path.Suggested fix
Update the call to use
markerInsideElements(for consistency with the marker call) and pass theinertflag conditionally based on browser support (supportsInert()).Workaround
Observe
data-base-ui-inert(the marker attribute already set by the secondmarkOtherscall) viaMutationObserverand mirrorinertonto the same elements.