基于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键支持:提供键盘快捷操作,符合无障碍设计规范。
模态框方案补充(若仍想使用)
若坚持用模态框作为菜单,需修正以下问题:
- 修复PHP语法错误:
echo '<dialog id="true-menu">'; echo '<button id="close-true-menu">Close</button>'; echo '<!-- 菜单内容 -->'; echo '</dialog>';
- 添加无障碍属性:
<dialog id="true-menu" role="dialog" aria-modal="true" aria-labelledby="menuTitle"> <h2 id="menuTitle">菜单</h2> <button id="close-true-menu">关闭</button> <!-- 菜单选项 --> </dialog>
- 完善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
相关产品推荐
相关产品推荐

