iOS Safari 的 <select> 高度完全不可控,因其点击后调用脱离 DOM 的全屏系统选择器,CSS 样式仅影响 44×44px 触控热区;可行方案是放弃原生下拉样式,采用 appearance: none 轻量适配或自定义组件,并确保 touchstart preventDefault、44px 最小热区、-webkit-overflow-scrolling: touch。

原生 <select> 在移动端(尤其是 iOS Safari)根本无法可靠控制下拉菜单高度——它会直接调用全屏或半屏系统选择器,CSS 完全失效。想“适配”,就得接受一个前提:放弃对原生弹出层的任何高度幻想。
为什么 iOS Safari 的 <select> 高度完全不可控
iOS Safari 对 <select> 的处理是硬编码级的:点击后触发 全屏系统选择器(UIDatePicker 或 UIPickerView),这个界面不在 DOM 中、不受 CSS 影响、不响应 max-height、size、甚至 transform。你写的样式只作用于顶部那个 44×44px 的触控热区,而热区本身还有最小尺寸强制要求。
- 设
height: 32px?热区被压扁 → 点不中 → 用户以为按钮坏了 - 加
size="5"?iOS 忽略该属性,仍走全屏选择器 - 用
transform: scale()缩放?热区物理尺寸变小 → 触摸命中率暴跌 - 试图用
overflow-y: auto包裹?对脱离文档流的系统弹窗毫无意义
移动端真正可行的两种路径
不是“怎么调高度”,而是“怎么绕过高度问题”:
-
轻量方案(仅限简单场景):保留原生
<select>,但用appearance: none+ 自定义箭头 + 显式设置min-height: 44px+padding保证触控热区达标;放弃对下拉菜单样式的任何期待,接受它全屏展开 -
自定义方案(推荐):用
<div class="custom-select"><button aria-expanded="false"></button><ul role="listbox" aria-hidden="true"></ul></div>替代;<ul>设max-height: 200px+overflow-y: auto,高度完全可控;必须监听touchstart并preventDefault()防止 300ms 延迟
自定义下拉在移动端必须处理的三个细节
否则哪怕写对了 max-height,也会在真机上崩:
立即学习“前端免费学习笔记(深入)”;
-
touchstart事件必须绑定到<button>和<ul>上,并立即preventDefault()—— 否则 iOS Safari 会拦截并唤起原生选择器 -
<button>的min-height和padding加起来不能低于44px,否则不符合 WCAG 触摸热区标准,Lighthouse 直接报错 - 滚动容器(
<ul>)需加-webkit-overflow-scrolling: touch,否则 iOS 滚动卡顿、回弹异常;同时避免在父级加overflow: hidden,会截断滚动条
最常被忽略的一点:所谓“适配移动端”,本质不是让下拉菜单变矮或变高,而是让**用户能点中、能滚动、能看清、能键盘导航**。原生 <select> 在这些环节里有太多隐性约束,硬改高度只会暴露更多兼容性裂缝。



















