You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

屏幕阅读器无法读取弹窗条款内容的无障碍技术求助

解决模态条款弹窗的VoiceOver无障碍问题

你的问题核心是仅用off-screen定位隐藏弹窗,但缺少无障碍属性关联和模态弹窗的焦点管理逻辑,导致屏幕阅读器识别不到弹窗状态,焦点也无法正常进入弹窗区域。以下是具体修复方案:

1. 完善隐藏类的无障碍处理

给.no-vis类补充无障碍属性,同时定义弹窗显示时的基础样式:

.no-vis {
  position: absolute;
  left: -10000px;
  top: auto;
  width: 1px;
  height: 1px;
  overflow: hidden;
}
/* 弹窗显示时的样式示例 */
.caption-content.active {
  position: fixed;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  width: 80%;
  max-width: 600px;
  height: 70vh;
  overflow-y: auto;
  padding: 20px;
  background: #fff;
  z-index: 1000;
}
/* 屏幕阅读器专用辅助类 */
.sr-only {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border-width: 0;
}

2. 给触发按钮添加无障碍关联属性

让屏幕阅读器明确按钮的功能和控制对象:

<button class="caption-link" id="caption-link-1" aria-expanded="false" aria-controls="caption-1">
  <span>Terms and Conditions</span>
</button>

3. 弹窗的语义化与无障碍配置

给弹窗添加模态标识和语义角色,补充屏幕阅读器可识别的标题:

<div class="caption-content no-vis" id="caption-1" role="dialog" aria-modal="false" aria-hidden="true" aria-labelledby="caption-title-1">
  <h2 id="caption-title-1" class="sr-only">条款与条件</h2>
  <button class="caption-content-close" id="content-close-1" aria-label="关闭条款弹窗"></button>
  <div class="scroll-content">
    Aliquam sit amet venenatis dui. Ut facilisis at dui vitae gravida. Lorem ipsum dolor sit amet, consectetur adipiscing elit.
  </div>
</div>

4. 实现焦点管理与状态同步逻辑

通过JS处理弹窗的显示/隐藏,同步无障碍属性,确保焦点在弹窗内循环:

const triggerBtn = document.getElementById('caption-link-1');
const modal = document.getElementById('caption-1');
const closeBtn = document.getElementById('content-close-1');
// 获取弹窗内所有可聚焦元素
const modalFocusables = modal.querySelectorAll('button, [href], input, select, textarea, [tabindex]:not([tabindex="-1"])');
const firstFocusable = modalFocusables[0];
const lastFocusable = modalFocusables[modalFocusables.length - 1];

// 打开弹窗
triggerBtn.addEventListener('click', () => {
  modal.classList.remove('no-vis');
  modal.classList.add('active');
  modal.setAttribute('aria-modal', 'true');
  modal.setAttribute('aria-hidden', 'false');
  triggerBtn.setAttribute('aria-expanded', 'true');
  // 焦点移到弹窗内的关闭按钮
  closeBtn.focus();
});

// 关闭弹窗函数
function closeModal() {
  modal.classList.add('no-vis');
  modal.classList.remove('active');
  modal.setAttribute('aria-modal', 'false');
  modal.setAttribute('aria-hidden', 'true');
  triggerBtn.setAttribute('aria-expanded', 'false');
  // 焦点回归触发按钮
  triggerBtn.focus();
}

closeBtn.addEventListener('click', closeModal);
// ESC键关闭弹窗
document.addEventListener('keydown', (e) => {
  if (e.key === 'Escape' && !modal.classList.contains('no-vis')) {
    closeModal();
  }
});

// 焦点陷阱:Tab键在弹窗内循环
modal.addEventListener('keydown', (e) => {
  if (e.key === 'Tab') {
    if (e.shiftKey) {
      if (document.activeElement === firstFocusable) {
        e.preventDefault();
        lastFocusable.focus();
      }
    } else {
      if (document.activeElement === lastFocusable) {
        e.preventDefault();
        firstFocusable.focus();
      }
    }
  }
});

关键修复点说明

  • aria-hidden:控制屏幕阅读器是否读取弹窗内容,隐藏时设为true,显示时设为false
  • aria-modal="true":标记弹窗为模态,让屏幕阅读器仅读取弹窗内内容
  • aria-expanded:实时反馈按钮的展开/收起状态
  • 焦点陷阱:确保Tab键在弹窗内循环,ESC键可关闭弹窗,符合无障碍交互规范
  • 屏幕阅读器专用标题:让VoiceOver能识别弹窗主题,提升内容可读性

内容的提问来源于stack exchange,提问作者Jonathan

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.17 09:02:54