bootstrap
bootstrap copied to clipboard
Modals aria-hidden attribute
Prerequisites
- [X] I have searched for duplicate or closed issues
- [X] I have validated any HTML to avoid common problems
- [X] I have read the contributing guidelines
Describe the issue
I'm actually using Brave Beta - Chrome 131.0.6778.14 Beta, checking around this issue seems to be in Beta and Nightly builds; but not the current release
I tested on Chrome beta - same version as my Brave and it exists there
I'm concluding it is an imminent issue
I can see this got mentioned a while back in #29769
The Issue: I've started seeing aria-hidden issues when I close my modals, and have been able to see it on the demo modals at https://getbootstrap.com/docs/5.3/components/modal/
So to replicate the issue I open the modal, then close it using the cross (top right in the modal header) a second or so after the click this appears in the console, I hadn't noticed before today
I've gone back over my code and am consistent with the documentation
Reduced test cases
The issue exists in my code and can be demonstrated on the getbootstrap.com site
What operating system(s) are you seeing the problem on?
Windows
What browser(s) are you seeing the problem on?
Chrome
What version of Bootstrap are you using?
v5.3.3
A bit more on this - I'm thinking it is a rising issue
This only occurs when the fade class is set, so it is to do with elements having focus and visible when the aria attribute is set
Is it sensible to move the setting of the aria hidden attribute down to after the css transition has taken place ? I'm thinking the attribute is set too early
This file is js/dist/modal.js
It is a rising issue; the same thing happens in Google Chrome (Canary Version 133.0.6840.0). The issue occurs when the fade class is present.
It is a rising issue; the same thing happens in Google Chrome (Canary Version 133.0.6840.0). The issue occurs when the
fadeclass is present.
In my previous comment, I mentioned that the issue occurs when the fade class is present. Even though the issue disappears (most of the times), there are (random?) times when the issue occurs even when the fade class is not used. So, I am not sure if the fade class is a factor in this case.
I don't know enough to definitively associate it with fade - but am associating it with something retaining focus until after the transition between the events hide.bs.modal and hidden.bs.modal - so have blamed fade I guess
but it is random - it exists in bootstrap 4 too
In a modified bootstrap.js it disappears for me when the aria-hidden line is moved down
This is an actual issue. I can reproduce this in our standard frontend (Shopware) with all modals. We recently added focus handling for better accessibility to our modals, to return the focus state to the button that opened the modal after it is closed. But the error message still occurs, because we use the hidden.bs.modal event to do so, but it is too late. When using the hide.bs.modal event it won't work because the browser seems to prevent you from focusing elements outside a dialog, which is basically correct from an accessibility standpoint.
I fixed it like this for now:
modal.addEventListener('hide.bs.modal', () => {
if (document.activeElement instanceof HTMLElement) {
document.activeElement.blur();
}
});
If the bootstrap modal keeps using the aria-hidden attribute, it should implement a similar solution or even a better focus handling in general. Some other solution would be to move modal content to a <template> tag to not make it part of the actual accessibility tree while not in use.
This is an actual issue. I can reproduce this in our standard frontend (Shopware) with all modals. We recently added focus handling for better accessibility to our modals, to return the focus state to the button that opened the modal after it is closed. But the error message still occurs, because we use the
hidden.bs.modalevent to do so, but it is too late. When using thehide.bs.modalevent it won't work because the browser seems to prevent you from focusing elements outside a dialog, which is basically correct from an accessibility standpoint.I fixed it like this for now:
modal.addEventListener('hide.bs.modal', () => { if (document.activeElement instanceof HTMLElement) { document.activeElement.blur(); } });If the bootstrap modal keeps using the
aria-hiddenattribute, it should implement a similar solution or even a better focus handling in general. Some other solution would be to move modal content to a<template>tag to not make it part of the actual accessibility tree while not in use.
Thank you, @Phil23, for sharing your solution! It works perfectly and helped me better understand the issue.
To make this functionality more global and consistent across our application, I adapted your approach slightly:
window.addEventListener('hide.bs.modal', () => {
if (document.activeElement instanceof HTMLElement) {
document.activeElement.blur();
}
});
This ensures that the focus is managed correctly on all modals without needing to attach the listener to each modal individually
I see this without fade class set, I don't think that's necessary for a repro.
This is an actual issue. I can reproduce this in our standard frontend (Shopware) with all modals. We recently added focus handling for better accessibility to our modals, to return the focus state to the button that opened the modal after it is closed. But the error message still occurs, because we use the
hidden.bs.modalevent to do so, but it is too late. When using thehide.bs.modalevent it won't work because the browser seems to prevent you from focusing elements outside a dialog, which is basically correct from an accessibility standpoint. I fixed it like this for now: modal.addEventListener('hide.bs.modal', () => { if (document.activeElement instanceof HTMLElement) { document.activeElement.blur(); } });If the bootstrap modal keeps using the
aria-hiddenattribute, it should implement a similar solution or even a better focus handling in general. Some other solution would be to move modal content to a<template>tag to not make it part of the actual accessibility tree while not in use.Thank you, @Phil23, for sharing your solution! It works perfectly and helped me better understand the issue.
To make this functionality more global and consistent across our application, I adapted your approach slightly:
window.addEventListener('hide.bs.modal', () => { if (document.activeElement instanceof HTMLElement) { document.activeElement.blur(); } }); This ensures that the focus is managed correctly on all modals without needing to attach the listener to each modal individually
It works successfully, thank you
I suddenly started getting this issue on my modals. Any plans to fix it?
Solution we are currently using with 5.3 modals.
window.addEventListener('hide.bs.modal', event => {
event.target.inert = true
})
window.addEventListener('show.bs.modal', event => {
event.target.inert = false
})
We chose toggling inert over invoking blur() since the latter (shortened example below) might cause unexpected issues for assistive technology users.
window.addEventListener('hide.bs.modal', () => {
document.activeElement?.blur()
})
I've noticed this as well. I don't entirely understand why aria-hidden is necessary in the first place. The modal class will add display: none when it's not being shown:
https://github.com/twbs/bootstrap/blob/6d3345b24c7e58ccb3f228d9395996b3c3f5a216/scss/_modal.scss#L39
Isn't that sufficient to hide the modal from screen readers and other accessibility technology?
I have also encountered the same problem, which I only encountered recently with the update of Chrome. It seems that the old version from a long time ago would not pop up this issue
Received this same error in our Chrome extension. Also solved my manually triggering the blur.
Solution we are currently using with 5.3 modals.
window.addEventListener('hide.bs.modal', event => { event.target.inert = true })
window.addEventListener('show.bs.modal', event => { event.target.inert = false })
I incorporated this neat and idiomatic workaround (thanks for the hint!) as a fix in PR #41867, setting the inert attribute directly in the functions for showing and hiding the modal. My OCD kicked in today and I wanted to get rid of the warnings in the console. After some unsatisfying experiments with .blur(), I settled on the inert attribute approach, as it was also suggested in the warning itself. The PR should address this issue at the source, and hopefully it gets merged :shipit:. Until then the workaround from @mavelo-llc works just fine 👍.