必须直接嵌套在内且label非空,否则被浏览器忽略;disabled仅禁用选项不隐藏标题;ios/safari中视觉分组基本无效,仅保留语义与可访问性。

直接用 <optgroup></optgroup>,别想用 <div> 包裹或 JS 模拟——浏览器只认这一种原生分组方式,其他全是障眼法,还破坏可访问性。
<h3>为什么 <code><optgroup></optgroup> 必须直接写在 <select></select> 里
浏览器解析器硬性规定:<optgroup></optgroup> 只能是 <select></select> 的**直接子元素**。任何中间层(<div>、注释、文本节点、甚至换行缩进)都会导致整段被静默忽略。
<ul>
<li>
<code><select><div><optgroup label="水果"></optgroup></div></select> → 分组标题不显示,DOM 里根本找不到 <optgroup></optgroup>
{% if group %}<optgroup label="{{ group.name }}">...</optgroup>{% endif %},但 group.name 为空 → 整个 <optgroup></optgroup> 被跳过,只剩孤零零的 <option></option>
select.appendChild(optgroup) → Chrome 报 DOMException,Firefox 静默丢弃正确做法只有一种:<select><optgroup label="水果"><option>苹果</option></optgroup></select>;JS 中必须用 select.add(optgroup),且先赋值 optgroup.label = "xxx"。
label 属性不能为空、不能含 HTML、中文建议 2–4 字
label 不是装饰,是 <optgroup></optgroup> 唯一必需属性。它决定分组标题是否渲染、屏幕阅读器能否识别归属关系。
-
<optgroup><option>苹果</option></optgroup>(漏写label)→ 标题消失,语义丢失 -
<optgroup label=""></optgroup>或<optgroup label=" "></optgroup>→ 浏览器当作无效标签跳过 -
<optgroup label="<strong>水果</strong>"></optgroup>→ HTML 标签被当作文本渲染,显示为字面量 "水果" - 中文 label 过长(如
label="其他分类(请谨慎选择)")→ 在移动端或小屏下截断、可读性差
实操建议:服务端输出前加校验 if (!group.label?.trim()) 就跳过该组;JS 创建时统一做 .trim() 并 fallback 到 "未命名"。
disabled 加在 <optgroup></optgroup> 上,只禁选项、不隐藏标题
这是最常被误解的行为:<optgroup label="实验功能" disabled></optgroup> 会让内部所有 <option></option> 置灰不可选,但 label 文字依然清晰可见——这不是 bug,是规范要求。
- 看到某组全灰却还有标题,第一反应不是“没生效”,而是确认是否所有
<option></option>都被写了disabled,还是真用了<optgroup disabled></optgroup> -
<optgroup disabled></optgroup>在 Safari 16 及更早版本中完全无效,组内选项仍可点击;iOS 原生<select></select>中,label通常根本不显示 - 想让某组“彻底消失”,不能靠
disabled,得用 JS 移除整个<optgroup></optgroup>节点,或服务端压根不输出该标签
真正需要禁用整组时,就老老实实写 <optgroup label="实验功能" disabled><option value="a">A</option></optgroup>,别绕弯。
iOS 和 Safari 对 <optgroup></optgroup> 的支持极弱
别在移动端指望 <optgroup></optgroup> 的视觉分组效果。iOS 原生下拉菜单中,label 几乎从不渲染,用户只看到平铺的 <option></option>;Safari 对 background-color、padding 等样式基本无视,color 是少数还能调的属性。
- 如果你的用户大量使用 iPhone,
<optgroup></optgroup>的主要价值只剩语义和可访问性(屏幕阅读器能读出“前端技术,组合”),视觉分组意义不大 - 不要为了“看起来整齐”强行加 CSS 试图修复 iOS 表现——多数无效,还可能触发渲染异常
- 若业务强依赖分组可见性(如后台管理系统),考虑降级方案:用两个独立
<select></select>,或改用自定义下拉组件(但需手动实现键盘导航与无障碍支持)
最麻烦的点往往藏在细节里:label 看似写了,但前后有空格;DOM 插入顺序错了;以为 disabled 能隐藏标题;或者忘了 iOS 根本不画那个灰字——这些地方一错,分组就形同虚设。











