应根据用途选择:表单级联用配合js,导航折叠用。仅支持单层,多级需动态更新并处理事件绑定;语义准确、无需js即可展开,但非表单控件,不支持required且需css修正多级展开。

HTML 下拉菜单用 <select></select> 还是 <details></details>?
纯 HTML 原生下拉菜单,只靠 <select></select> 无法实现二级、三级联动(比如“省份→城市→区县”)。它天生只支持单层选项,<optgroup></optgroup> 仅能分组显示,不能嵌套或动态展开。想做多级联动,必须配合 JavaScript;若只是静态展示+点击展开(如导航菜单),<details></details> + <summary></summary> 更轻量、语义更准,且无需 JS 就能折叠/展开。
用 <select></select> 做二级联动,关键在监听 change 事件
用户选中一级选项后,要动态替换二级 <select></select> 的 <option></option>。不能直接 innerHTML 替换整个 <select></select>,否则会丢失已绑定的事件监听器。
- 先清空二级
<select></select>:用while (select2.firstChild) select2.removeChild(select2.firstChild) - 再逐个 append 新
<option></option>元素(不用字符串拼接),避免 XSS 风险 - 注意保留默认提示项(如
<option value="">请选择城市</option>),否则用户可能误提交空值 - 如果数据来自接口,记得加 loading 状态(比如禁用二级下拉 + 显示 “加载中…”)
用 <details></details> 实现可折叠多级菜单,兼容性要注意
<details></details> 支持原生折叠,但不支持“多级同时展开”(子 <details></details> 默认随父级关闭),需加 CSS 修正:
details[open] details { display: block; }
details[open] details[open] { display: block; }
常见坑:
立即学习“前端免费学习笔记(深入)”;
- Safari 15.4 之前不支持
<details></details>的toggle事件,要用addEventListener('toggle', ...)且检查event.target.open - 无法用
required或form关联提交,它不是表单控件,只适合导航类菜单 - 屏幕阅读器支持良好,但需确保
<summary></summary>文本明确(如“华北地区 ▼”),别只用图标
为什么不要用 <select></select> 做导航式下拉菜单?
很多初学者把顶部导航栏的“产品→企业版→私有部署”强行塞进 <select></select>,这违反语义且体验差:
-
<select></select>是为表单输入设计的,键盘操作逻辑(方向键切换、回车确认)和导航需求冲突 - 移动端点开后遮挡页面,无法 hover 展开,也没办法做动画过渡
- 无障碍属性(
aria-haspopup,aria-expanded)得手动补全,而<details></details>原生支持 - 真正需要的其实是带键盘导航(Tab/Arrow/Enter)、焦点管理、Aria 标注的自定义下拉组件——这时候该上
role="menu"+ JS 控制,而不是硬套<select></select>
多级菜单的复杂点不在结构嵌套,而在焦点流控制和状态同步。哪怕只加两级,漏掉一次 focus() 或没处理 Escape 键,用户就会卡住。别省这一步。










