原生 和 可实现语义化、无障碍折叠菜单,但 必须是 的首个直接子元素;添加 open 属性可默认展开;样式定制应清除原生箭头并用伪元素控制图标;手风琴效果需 js 监听 toggle 事件实现单开。

直接用 <details></details> 和 <summary></summary> 就能实现原生折叠菜单,不用写 JavaScript,语义清晰、键盘可用、屏幕阅读器友好。
基础结构必须严格
<summary></summary> 必须是 <details></details> 的第一个**直接子元素**,中间不能有空格、换行、注释或包裹容器。否则 Safari 可能完全不响应点击,其他浏览器也可能行为异常。
- ✅ 正确:
<details><summary>菜单项</summary><nav>链接1</nav></details> - ❌ 错误:
<details><div><summary>菜单项</summary></div> <nav>...</nav></details>(summary 不是直接子元素) - ❌ 错误:
<details><p>说明</p><div class="aritcle_card flexRow artxards"> <div class="artcardd flexRow"> <a class="aritcle_card_img" rel="nofollow" href="/xiazai/skill8272" title="anything-to-html"><img src="https://img.php.cn/upload/skill/000/000/081/179195588450431.jpg" alt="anything-to-html" onerror="this.onerror='';this.src='/static/lhimages/moren/morentu.png'" ></a> <div class="aritcle_card_info flexColumn"> <a rel="nofollow" href="/xiazai/skill8272" title="anything-to-html" class="overflowclass">anything-to-html</a> <p class="overflowclass">将调研报告、方案对比、数据分析、需求梳理、会议纪要、设计说明、代码评审、学习笔记等任务产物输出为可在浏览器直接打开的单文件 HTML,替代 Markdown 作为最终交付物。Markdown 在信息密度、视觉清晰度和可分享性上已跟不上 AI 产物的丰富度,HTML 能同时承载排版、表格、SVG 等。</p> </div> <a rel="nofollow" href="/xiazai/skill8272" title="anything-to-html" class="aritcle_card_btn flexRow flexcenter"><b></b><span>下载</span> </a> </div> </div> <summary>菜单项</summary></details>(summary 不是首个子元素)
默认展开与初始状态控制
加 open 属性让菜单一打开页面就展开:
<details open><summary>主菜单</summary><nav>…</nav></details>- 注意:
open是布尔属性,只写open即可,不要写open="true"或open="false" - JS 中切换状态要用
element.toggleAttribute('open'),而不是赋值element.open = false(后者只影响初始渲染)
样式定制:替换箭头+保持可访问性
浏览器默认箭头在 Safari 中难以控制,推荐用伪元素统一处理:
- 先清除原生标记:
summary { list-style: none; } - 加自定义图标:
summary::before { content: "▶"; margin-right: 6px; transition: transform 0.2s; } - 展开时旋转:
details[open] > summary::before { content: "▼"; transform: rotate(0deg); } - 别给
summary设display: block或flex,避免热区错位或图标偏移
手风琴效果(单开一栏)需 JS 配合
原生不支持自动收起其他项,但只需监听 toggle 事件即可:
- 用
toggle事件(不是click),它在状态真正变更后触发,兼容键盘和脚本操作 - 示例逻辑:当前展开时,遍历所有兄弟
<details></details>,移除它们的open属性 - 注意:
toggle不冒泡,需对每个元素单独绑定,或用事件委托配合closest()
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!










