Excel下拉菜单最常用方法是通过“数据验证”设置序列,选中单元格→数据→数据验证→允许选“序列”→来源输入逗号分隔选项或引用区域,操作简单且能规范输入、减少错误。

用 <select> 实现基础下拉菜单,但别指望它能自定义样式
原生 <select> 是最轻量、无障碍支持最好的下拉方案,适合表单提交场景。但它在 Chrome/Firefox/Safari 中渲染逻辑不同,appearance 无法彻底统一外观,伪元素(如 ::after)对箭头图标支持极差,iOS 上甚至不触发 :hover。
实操建议:
立即学习“前端免费学习笔记(深入)”;
- 仅用于纯功能型选择(如“省份→城市”级联筛选),不加动画、不换字体、不改背景渐变
- 必须配
<label for="xxx">提升可访问性,否则屏幕阅读器可能跳过 - 若需禁用某选项,用
<option disabled value="">请选择</option>,别只靠 CSS 灰掉 - 不要给
<select>设height或line-height——这会导致 Safari 下拉箭头错位
用 <details><summary> 做语义化下拉,兼容性已够用
<details> 是 HTML5 原生展开组件,无需 JS 就能切换显隐,且天然支持键盘(Space/Enter 展开,Tab 导航),比手写 aria-expanded 省心得多。Edge 79+、Chrome 12+、Firefox 49+、Safari 6.2+ 都支持,连 iOS 15.4 也稳。
实操建议:
立即学习“前端免费学习笔记(深入)”;
- 把导航菜单项包进
<details>,<summary>里放主菜单文字,内部用<nav>或无序列表组织子项 - 用
summary::marker { content: "▼"; }替换默认三角,避免 Safari 不支持list-style - 若需点击区域更大,给
<summary>加padding,但别设display: block——会破坏默认焦点行为 - 注意:不支持多级嵌套(
<details>内再套<details>在部分 Android WebView 中会失效)
手写 dropdown 组件时,focusout 和 blur 的触发时机必须分清
自定义下拉菜单最常卡在“点空白处收起菜单”这个需求上。很多人直接监听 document.addEventListener('click', ...),结果导致点击下拉按钮本身也触发关闭——因为事件冒泡了。更糟的是,在 Firefox 中 focusout 不冒泡,而 blur 根本不触发,光靠一个事件监听器必翻车。
实操建议:
立即学习“前端免费学习笔记(深入)”;
- 用
mousedown+focusout组合:在<body>监听mousedown,检查event.target是否在下拉容器外;同时监听下拉触发元素的focusout,延迟 100ms 关闭(防 Chrome 中快速切换输入框失焦误关) - 禁止在
<summary>或下拉按钮上用preventDefault()——这会让键盘用户无法用Enter激活 - 移动端要额外处理
touchstart,iOS Safari 的click有 300ms 延迟,直接响应touchstart更跟手 - 别忘了
tabindex="-1"给下拉面板,否则键盘用户 Tab 过去会跳进不可见区域
复杂导航交互中,aria-haspopup 和 aria-expanded 不是摆设
当导航含多层弹出(比如“产品→云服务→API 文档”三级菜单),光靠视觉动效不够。NVDA、VoiceOver 等读屏软件依赖 ARIA 属性判断是否可展开、当前状态。漏写或写错值(如把 aria-expanded="false" 写成 "0")会导致读屏直接跳过整个菜单。
实操建议:
立即学习“前端免费学习笔记(深入)”;
-
aria-haspopup="menu"必须加在触发按钮上(不是<div>容器),且值只能是"menu"、"listbox"等标准字符串,不能是true -
aria-expanded要和真实状态严格同步:JS 切换类名的同时,必须同步设置该属性为"true"或"false" - 子菜单容器加
role="menu",每个菜单项用role="menuitem",禁用项补aria-disabled="true" - 别用
aria-hidden="true"隐藏下拉面板——这会让读屏完全忽略内容,应该用hidden属性或display: none
Tab 进入菜单后,方向键是否能上下切换?Esc 是否回退到上一级而非直接退出?这些细节没对齐 WCAG 2.1,再炫的动效也等于没做。


















