HTML下拉菜单必须用<select>标签配合<option>实现,支持原生交互、无障碍访问和表单提交;禁用提示项需设value="" disabled selected,样式定制受限,深度需求应改用专业库。

HTML 下拉菜单用 <select> 最简单,别手写 <div> 模拟
原生 <select> 是唯一被所有浏览器一致支持、带键盘导航、屏幕阅读器兼容、无需 JS 就能提交表单的方案。手写 <div> + <ul> 模拟下拉,90% 的场景纯属给自己加 bug。
常见错误现象:click 事件不触发、Enter 键无法选中、移动端点开后闪退、表单提交时值为空。
-
<select>必须配<option>,不能用<li> - 默认选中用
selected属性,不是value="xxx" - 禁用某选项用
disabled,不是style="display:none"(后者仍会被提交)
怎么让下拉菜单有「请选择」提示项又不提交它
关键在第一个 <option> 的 value 设为空字符串,并加 disabled 和 selected —— 这样它显示但不可选,且表单提交时不会带上这个空值。
示例:
立即学习“前端免费学习笔记(深入)”;
<select name="category"> <option value="" disabled selected>请选择分类</option> <option value="news">新闻</option> <option value="blog">博客</option> </select>
注意:disabled 项在 Chrome/Firefox 中默认灰显,但 Safari 有时不渲染为禁用态,建议补一句 opacity: 0.6;另外,如果后端要求必填,得靠 JS 或服务端校验,required 属性对 disabled 项无效。
下拉选项太多时,<select> 性能会卡吗
不会。原生 <select> 渲染由浏览器底层控制,几千个 <option> 也不卡——但用户体验会崩:滚动慢、搜索难、移动端弹出框巨大。
真实瓶颈不在渲染,而在交互效率:
- 用户无法输入搜索,只能滚动/滑动查找
- 移动端
<select>弹出的是系统原生选择器,样式完全不可控 - 没有分组折叠、异步加载、远程搜索等能力
这时该换方案:用 <input> + <datalist>(轻量级搜索补全),或引入 select2 / Choices.js 等库——但前提是确认团队真需要这些功能,而不是“看着高级就上”。
为什么 onchange 不触发,或者触发两次
因为监听错了事件类型,或绑在了错误节点上。原生 <select> 应该用 change,不是 click 或 input;而且必须绑定在 <select> 元素本身,不是它的父容器。
典型错误:
- 写成
<select onclick="handle()>→ 点击空白处不触发 - 用
addEventListener('input', ...)→<select>不发input事件 - JS 动态设置
select.value = 'xxx'后没手动触发change→ 用户没操作,事件不冒泡
正确做法:
document.querySelector('select').addEventListener('change', function(e) {
console.log(e.target.value); // 拿到当前选中值
});
原生下拉最麻烦的其实是样式定制——appearance: none 在 Safari 上行为不稳定,箭头图标对齐跨浏览器差异大,而一旦开始 hack 这些,就离自己实现一个可访问的下拉不远了。











