原生<select>的height和max-height对下拉菜单无效,因浏览器将其分为顶部可样式化区域和系统级不可样式化弹出层;唯一跨浏览器控制可见选项数的方案是size属性;精确限高需自定义<div><ul>组件。

原生 <select> 的 height 属性只影响顶部按钮区,对下拉弹出菜单完全无效;真正能控制“可见选项数量”的唯一跨浏览器方案是 size 属性;若需点击展开 + 精确限高,则必须用 <div> + <ul> 自定义实现。
为什么直接设 height 或 max-height 失效
浏览器把 <select> 拆成两个独立渲染层:顶部“选中区”(CSS 可部分干预)和系统级“弹出菜单”(由操作系统或 UA 绘制,CSS 完全穿透不了)。你写 height: 36px,可能只压扁了按钮,点开后菜单还是默认显示 8–12 行、每行约 24px 高。更关键的是:line-height、padding、max-height 加在 <select> 或 <option> 上,Chrome/Edge/Safari/iOS 全部忽略。
-
max-height在<select>上会被 Lighthouse 直接标记为“未生效” - 给
<option>设height或line-height—— 所有主流浏览器均不解析 - iOS Safari 强制最小触摸热区为 44×44px,硬缩到 32px 就点不中
用 size 属性控制可见行数(最稳原生方案)
size 是 HTML 原生属性,不是 CSS,它让 <select> 以常驻列表模式展开,并固定显示指定行数。此时高度由行数 × 浏览器默认行高决定,滚动稳定、聚焦正常,且无需 JS。
- 写法:
<select size="4"><option>A</option></select>→ 展开时显示 4 行,超出自动滚动 -
size和multiple可共存,但加了multiple后视觉变成多选列表,不再是传统下拉箭头样式 - 慎用
size="1":等效于默认单选,但某些旧版 Safari 下可能丢失箭头 - 移动端注意:iOS Safari 可能无视
size,强制走全屏选择器
transform: scale() 微调视觉高度(轻量折中)
如果你必须保留单选下拉样式,又想让整体看起来更紧凑,transform: scale(1, 0.75) 是比硬改 height 更可控的方式——它缩放整个元素(含文字和边框),不会干扰弹出菜单的渲染逻辑。
立即学习“前端免费学习笔记(深入)”;
- 必须补
transform-origin: top center和margin-top,否则缩放后元素上移错位 - 同步调大
font-size(如原14px缩放 0.75 倍后建议设为16px),避免文字过小 - 风险:Chrome 120+ 会报 “form elements not scalable” 可访问性警告
- 别在 flex 容器里用,除非额外加
align-items: center,否则垂直对齐会偏
自定义下拉组件(唯一 100% 可控路径)
当设计要求包含「固定最大高度 + 自定义滚动条 + 行高/内边距自由设置」时,绕过原生 <select> 是唯一可靠选择。核心是隐藏原生元素,用语义化结构模拟交互,并用 JS 同步值。
-
<ul>上设max-height: 200px+overflow-y: auto,这才是真生效的限高 - 每个
<li>可自由设padding、line-height、min-height - 必须监听
click(外部关闭)、Escape(收起)、ArrowDown/Up(键盘导航)、Enter(确认) - 无障碍关键:保留原生
<select>在 DOM 中(position: absolute; opacity: 0; pointer-events: none;),同步更新其value
真正需要统一单项高度、hover 高亮、搜索过滤或虚拟滚动的场景,自定义不是过度设计,而是浏览器能力边界决定的必然选择——原生 <select> 的弹出层,本质就是一个不可样式化的黑盒。



















