不能直接替代,因其无change事件、不支持value绑定和键盘导航,仅能通过++js手动实现伪下拉逻辑,并需补全无障碍与兼容性支持。

details 标签不能直接替代 <select></select>,但能模拟展开式交互菜单
很多人想用 <details></details> 做下拉选择器,结果发现它不触发 change 事件、无法绑定 value、也不支持键盘导航(如方向键切换选项)。它本质是「可折叠内容容器」,不是表单控件。真要替代 <select></select>,得靠组合:用 <details></details> + <summary></summary> + 点击后手动设置隐藏字段或更新状态。
基础结构必须包含 <summary></summary>,且只能有一个
<details></details> 内部第一个子元素必须是 <summary></summary>(否则浏览器会自动生成一个默认摘要),后续才是可展开内容。常见错误是把多个 <summary></summary> 塞进去,或漏写它导致样式/行为异常。
正确写法示例:
<details><summary>请选择城市</summary><ul>
<li><a href="#" data-value="beijing">北京</a></li>
<li><a href="#" data-value="shanghai">上海</a></li>
</ul></details>
注意:<summary></summary> 本身不可被 JavaScript 的 click 事件捕获(部分浏览器会冒泡,但不可靠),应监听 <details></details> 的 toggle 事件判断展开/收起,选项点击则单独绑定。
用 toggle 事件 + data-value 实现伪选中逻辑
要让这个结构“像”选择器,关键在两点:一是记录当前选中项,二是同步显示到 summary 文本。不能依赖 <details></details> 自身状态,得靠 JS 维护。
-
<details></details>的toggle事件只在用户点击 summary 时触发,不包括内部链接点击 —— 所以选项点击后需手动调用detailsElement.removeAttribute('open')收起 - 每个选项用
data-value存值,点击时更新一个隐藏的<input type="hidden">或组件 state - summary 文本需 JS 动态改写,例如:
summary.textContent = '已选:' + value;别用 innerHTML,避免 XSS - 若需初始值,得提前设置
<details open></details>并初始化 summary 文本和 hidden input
无障碍与兼容性短板必须手动补足
<details></details> 在 Safari 和旧版 Edge 中有渲染差异,且原生不支持键盘操作(空格/回车展开、方向键移动焦点等)。如果项目需要 WCAG 合规,至少补三件事:
- 给
<summary></summary>加role="button"和tabindex="0",确保可聚焦 - 监听
keydown,对空格/回车响应detailsElement.open = !detailsElement.open - 选项列表用
role="listbox",每个<a></a>改为<div role="option"> 并加 <code>tabindex="-1",再用 JS 管理焦点流 - Chrome 122+ 开始支持
<details></details>的focusable属性,但别依赖 —— 大部分生产环境还得手写
真正复杂的表单场景,<details></details> 只适合作为轻量级筛选面板;要完整替代 <select></select>,还是用基于 <div> 的自定义下拉库更可控。</div>











