模态框内聚焦陷阱实现问题 - 无障碍访问
解决模态框焦点陷阱问题
你的核心问题是原方法通过修改所有外部元素tabindex的方式,没法阻止焦点跳到浏览器地址栏(地址栏属于浏览器UI,不在页面DOM范围内)。正确的做法是监听Tab键事件,在模态框内实现焦点循环,同时打开时自动聚焦第一个可聚焦元素。
以下是修复后的完整代码:
<!DOCTYPE html> <html lang="zh-CN"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <style> .modal { display: none; position: fixed; left: 50%; top: 50%; transform: translate(-50%, -50%); width: 250px; padding: 20px; z-index: 999; background-color: aliceblue; } </style> <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script> </head> <body> <button class="openModal">打开模态框</button> <div class="modal"> <button class="closeModal">关闭模态框</button> <h4>这里是文本</h4> <a href="/main-page">跳转到主页</a> </div> <a href="/home">首页</a> <a href="/about">关于我们</a> <script> // 缓存常用元素 const $openBtn = $('.openModal'); const $modal = $('.modal'); const $closeBtn = $('.closeModal'); // 获取模态框内所有可聚焦元素 function getFocusableElements() { return $modal.find('button, [href], input, select, textarea, [tabindex]:not([tabindex="-1"])'); } $openBtn.on('click', function() { $modal.fadeIn(); // 聚焦模态框内第一个可聚焦元素 const focusableEls = getFocusableElements(); if (focusableEls.length > 0) { focusableEls.first().focus(); } }); $closeBtn.on('click', function() { $modal.fadeOut(); // 关闭后恢复焦点到打开按钮,提升可用性 $openBtn.focus(); }); // 监听Tab键事件,实现焦点循环 $modal.on('keydown', function(e) { const focusableEls = getFocusableElements(); const firstEl = focusableEls.first()[0]; const lastEl = focusableEls.last()[0]; const isTabPressed = e.key === 'Tab'; if (!isTabPressed) return; // Shift+Tab 从第一个元素往前跳时,聚焦最后一个元素 if (e.shiftKey && document.activeElement === firstEl) { lastEl.focus(); e.preventDefault(); } // Tab 从最后一个元素往后跳时,聚焦第一个元素 else if (!e.shiftKey && document.activeElement === lastEl) { firstEl.focus(); e.preventDefault(); } }); </script> </body> </html>
关键改进点:
- 自动聚焦:模态框打开后,直接获取内部所有可聚焦元素并聚焦第一个,无需修改外部元素的
tabindex - 焦点循环:监听模态框内的Tab/Shift+Tab事件,当焦点到达边界时循环到另一端,同时调用
e.preventDefault()阻止浏览器默认的焦点跳转行为,彻底避免焦点跳出到地址栏 - 可用性优化:关闭模态框后将焦点恢复到打开按钮,符合无障碍设计规范
- 性能优化:缓存常用元素,避免重复DOM查询
内容的提问来源于stack exchange,提问作者user27057925
相关产品推荐
相关产品推荐

