参考资料
没找到解决方法,随便看看
- 解决elementui中el-radio报错:Blocked aria-hidden on an element because its descendant retained focus.-CSDN博客
- Modal组件渲染后控制台报错“aria-hidden“_locked aria-hidden on a <input> element because th-CSDN博客
- “aria-hidden 元素不包含可聚焦元素”显示模态时的问题_前端开发问题-跟版网
- aria-hidden的报错_aria-hidden报错-CSDN博客
- aria-hidden属性引发的思考 - 知乎
异常
之前在实现 Hexo 前面的搜索功能,有使用到 Bootstrap 的模态框
<!-- 模态窗口 -->
<div class="modal" id="searchModal" tabindex="-1" aria-modal="true" role="dialog">
<div class="modal-dialog modal-lg" role="document">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title">搜索</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
</div>
<div class="modal-body">
<input type="text" class="form-control" id="searchInput" placeholder="Keyword">
<div class="search-content" id="searchResult"></div>
</div>
</div>
</div>
</div>
可能是之前没注意,后续在控制台发现一个报错,虽然不影响使用,但显示台看着有点碍眼,解决记录下
触发这个异常的原因是我在模态窗显示的时候,点击关闭按钮隐藏模态窗
而问题产生来自于 aria-hidden
属性
aria-hidden 属性
aria-hidden
属性不熟悉,查了下资料,具体可参考 MDN
aria-hidden
属性用于指示辅助技术(如屏幕阅读器、读屏软件),主要是给残障人士使用的,当你给一个元素添加 aria-hidden
属性的时候,该元素会对「读屏软件」隐藏
对于正常人而言,元素的隐藏状态基于其是否被渲染。
通常是通过 CSS 的 display
属性设置为 none
来决定是否可见
对于残障人士,使用辅助技术「读屏软件」来阅读内容,设置了 aria-hidden
属性的元素,虽然肉眼可见(对于正常人来讲),但「读屏软件」会忽略该元素。
aria-hidden
属性因为对于「读屏软件」是隐藏的,所以有这个属性的元素及其子元素都不允许获取焦点。
问题
Bootstrap
模态窗问题的警告就是来自于焦点管理Bootstrap
的 js 默认会给模态窗容器添加上 aria-hidden=true
由于我代码更新了,所以这里拿 Fluid
主题举例,因为 Fluid
主题也是使用的 bootstrap
的模态窗,HTML 结构有些许不同,但原理一样
可以看到模态窗下面的元素(关闭按钮)包含有 aria-hidden=true
当点击关闭按钮的时候,焦点在按钮上,而按钮在包含有 aria-hidden=true
属性的元素内,上面说到拥有 aria-hidden=true
属性的元素对于屏幕阅读器而言是隐藏的,所以这对屏幕阅读器而言,就是焦点消失了(隐藏了),从而引发了错误,也就是控制台所报告的:
有一个元素拥有焦点,而它的一个祖先元素设置了
aria-hidden
。这意味着焦点被隐藏了,这违反了 WAI-ARIA 规范。
解决方法
有几种解决方法
- 移除
aria-hidden="true"
属性。 - 确保焦点元素不在
aria-hidden="true"
元素的后代中。 - 使用
inert
属性替代aria-hidden
,inert
属性可以防止元素获得焦点。
我这里采用方案 1
bootstrap
的模态窗口本身不写这个属性是也没用的
<!-- 模态窗口 -->
<div class="modal" id="searchModal" tabindex="-1" aria-modal="true" role="dialog">
<div class="modal-dialog modal-lg" role="document">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title">搜索</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
</div>
<div class="modal-body">
<input type="text" class="form-control" id="searchInput" placeholder="Keyword">
<div class="search-content" id="searchResult"></div>
</div>
</div>
</div>
</div>
因为 bootstrap.min.js
还是会给自动加上的,显示模态窗和隐藏模态窗的事件处理中会动态添加
所以要么只能改动 bootstrap.min.js
代码,要么自己重写模态窗的事件处理,全看个人
改动代码
在 bootstrap
的 js
中设置该属性的行注释掉,不设置这个属性即可
重写事件处理
仅供参考使用,可能要因地制宜
function serachEvent() {
/* 搜索相关事件 */
var modal = document.getElementById("searchModal"); // 模态窗
var searchBtn = document.querySelector(
'.links-item[data-bs-toggle="modal"][data-bs-target="#searchModal"]'
); // 触发按钮
var closeButton = modal.querySelector(".btn-close"); // 模态窗关闭按钮
// 点击触发按钮时显示模态框
searchBtn.addEventListener("click", () => {
showModal();
});
// 点击关闭按钮时隐藏模态框
closeButton.addEventListener("click", hideModal);
// 点击模态窗外部时隐藏模态框
modal.addEventListener("click", function (event) {
if (event.target.classList.contains("is-visible")) {
hideModal();
}
});
// 按下 ESC 键关闭模态窗口
document.addEventListener("keydown", function (event) {
if (event.key === "Escape" && modal.classList.contains("is-visible")) {
hideModal();
}
});
}
// 显示模态框
function showModal() {
var searchInput = document.getElementById("searchInput");
body.classList.add('no-scroll')
modal.classList.add("is-visible");
searchInput.focus();
}
// 隐藏模态框
function hideModal() {
body.classList.remove("no-scroll");
modal.classList.remove("is-visible");
}