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

基于HTML、PHP、JavaScript实现菜单折叠展开的问题求助

适配视障用户的Grid布局侧边栏折叠方案

问题分析

你之前的两种方案存在以下核心问题:

  • 第一种方案:JS操作的元素ID(mySidebar/main)与Grid布局里的sidebar/content不匹配,且直接修改元素宽度和边距会破坏Grid的原生布局逻辑,应该调整Grid的列定义而非元素样式。
  • 模态框方案:PHP代码存在语法错误(<dialog>标签多了多余引号),且缺少必要的ARIA无障碍属性,导致屏幕阅读器无法正确识别模态框的角色和状态。

可行解决方案

基于你的Grid布局,我们通过调整Grid列宽实现侧边栏折叠/展开,同时保证完全适配屏幕阅读器:

1. 修正后的HTML结构(可直接转成PHP echo输出)

<!-- 菜单按钮:用button确保键盘可访问 -->
<button id="menuToggle" aria-expanded="false" aria-controls="sidebar">
  菜单
</button>

<!-- Grid布局容器 -->
<body>
  <header id="header">页眉</header>
  <aside id="sidebar">侧边栏菜单</aside>
  <main id="content" tabindex="-1">主内容区</main>
  <footer id="footer">页脚</footer>
</body>

2. 调整后的CSS代码

保留你的Grid布局基础,新增折叠状态的样式:

body {
  min-height: 100vh;
  display: grid;
  /* 默认展开状态:侧边栏300px,内容区自适应 */
  grid-template-columns: 300px 1fr;
  grid-template-rows: 60px 1fr auto;
  grid-template-areas:
    "menubtn header"
    "sidebar content"
    "footer footer";
}

/* 折叠状态:侧边栏宽度为0,内容区占满 */
body.sidebar-collapsed {
  grid-template-columns: 0 1fr;
}

/* 隐藏折叠后的侧边栏内容,避免屏幕阅读器读取 */
body.sidebar-collapsed #sidebar {
  overflow: hidden;
  visibility: hidden;
}

#menuToggle {
  grid-area: menubtn;
}
#header {
  grid-area: header;
  background-color: white;
}
#sidebar {
  grid-area: sidebar;
  background-color: white;
  transition: visibility 0.2s;
}
#content {
  grid-area: content;
}
#footer {
  grid-area: footer;
  background-color: white;
}

3. 无障碍友好的JavaScript代码

const menuToggle = document.getElementById('menuToggle');
const body = document.body;
const sidebar = document.getElementById('sidebar');
const content = document.getElementById('content');

menuToggle.addEventListener('click', () => {
  // 切换折叠状态
  const isCollapsed = body.classList.toggle('sidebar-collapsed');
  
  // 更新ARIA属性,告知屏幕阅读器状态变化
  menuToggle.setAttribute('aria-expanded', !isCollapsed);
  
  // 折叠时将焦点移到主内容区,展开时移回侧边栏
  if (isCollapsed) {
    content.focus();
  } else {
    sidebar.focus();
  }
});

// 支持键盘操作:ESC键折叠侧边栏
document.addEventListener('keydown', (e) => {
  if (e.key === 'Escape' && !body.classList.contains('sidebar-collapsed')) {
    body.classList.add('sidebar-collapsed');
    menuToggle.setAttribute('aria-expanded', 'false');
    menuToggle.focus();
  }
});

4. 无障碍优化核心要点

  • 使用<button>元素:默认支持键盘聚焦(Tab键)和回车/空格触发,无需额外处理。
  • aria-expanded属性:实时告知屏幕阅读器菜单的展开/折叠状态。
  • aria-controls属性:关联按钮与控制的侧边栏元素,让屏幕阅读器用户明确按钮作用。
  • 焦点管理:折叠/展开时主动转移焦点,符合视障用户的导航逻辑。
  • ESC键支持:提供键盘快捷操作,符合无障碍设计规范。

模态框方案补充(若仍想使用)

若坚持用模态框作为菜单,需修正以下问题:

  1. 修复PHP语法错误:
echo '<dialog id="true-menu">';
echo '<button id="close-true-menu">Close</button>';
echo '<!-- 菜单内容 -->';
echo '</dialog>';
  1. 添加无障碍属性:
<dialog id="true-menu" role="dialog" aria-modal="true" aria-labelledby="menuTitle">
  <h2 id="menuTitle">菜单</h2>
  <button id="close-true-menu">关闭</button>
  <!-- 菜单选项 -->
</dialog>
  1. 完善JS焦点管理:
const trueMenu = document.getElementById('true-menu');
const closeButton = document.getElementById('close-true-menu');
const menuButton = document.getElementById('menubtn').querySelector('button');

menuButton.addEventListener('click', () => {
  trueMenu.showModal();
  closeButton.focus();
});

closeButton.addEventListener('click', () => {
  trueMenu.close();
  menuButton.focus();
});

// ESC键关闭模态框
trueMenu.addEventListener('close', () => {
  menuButton.focus();
});

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.17 22:34:52