max-height 对原生 select 下拉菜单完全无效,因其弹出层由系统底层绘制、脱离 DOM 和文档流,CSS 无法控制;唯一跨浏览器有效的限高方式是使用 size 属性,而真正可控的限高需通过 div+ul 自定义实现。

max-height 对原生 select 下拉菜单完全无效,你设了也不会限制弹出层高度——它压根不在 DOM 里,浏览器根本不让你用 CSS 控制。
为什么 max-height 在 select 上没用
原生下拉菜单是操作系统或浏览器底层绘制的独立 UI 组件,脱离文档流,CSS 无法穿透。你在 select 上写 max-height: 200px,只会影响顶部可点击区域的视觉高度;弹出来的列表该显示 10 行还是 12 行,由系统策略决定(Windows 通常最多 10–12 行,macOS 更不可控),和你的样式无关。
- Chrome / Edge / Safari 均无视
max-height、overflow-y、line-height对option的设置 - Firefox 虽有少量 UA 样式可干预,但行为不一致,且新版已进一步收紧
- Lighthouse 会直接标记“
max-height未生效”,因为浏览器渲染时根本没读这条规则
size 属性是唯一跨浏览器有效的原生限高方式
size 是 HTML 原生属性,它告诉浏览器“展开时默认显示几行选项”,浏览器据此计算弹出菜单的初始高度,并在超出时自动加滚动条——这是目前唯一无需 JS、全平台兼容的方案。
-
size="5":展开后最多显示 5 行,多余项需滚动查看 -
size="1"等效于默认下拉(即隐藏列表),适合保持点击展开交互 - 注意:
size会让select渲染成多行控件(类似textarea),失去“仅点击才展开”的语义,移动端(尤其 iOS Safari)可能直接忽略size,强制走全屏选择器
要保留点击展开 + 限高?必须用 div+ul 自定义
这是唯一能真正控制弹出层高度、滚动、键盘导航和可访问性的路径。关键不是“怎么写”,而是绕开几个硬坑:
立即学习“前端免费学习笔记(深入)”;
- 父容器必须设
position: relative,否则ul用position: absolute会定位错乱 - 下拉层(
ul)设max-height: 200px+overflow-y: auto,这才是真正生效的限高 - 必须监听外部点击、
Escape键、ArrowDown/Up导航,否则焦点和可访问性全崩 - 别漏掉
aria-expanded和aria-controls,否则屏幕阅读器不知道菜单开没开 - iOS Safari 对
focus极不敏感,得额外处理touchstart和blur同步
最常被忽略的一点:自定义下拉不是“换个结构就行”,而是要把原生 select 隐藏(opacity: 0 + position: absolute),再用 ul 模拟选项,最后把选中值同步回原生 select 的 value——否则表单提交时根本拿不到数据。



















