optgroup 必须作为 select 的直属子元素,仅包裹 option,label 不可为空且需为纯文本;disabled 属性对 optgroup 无效,须单独设置每个 option;css 支持极弱,仅限 font-weight、color 等基础样式。

optgroup 标签本身不“标注”选项,它只是把 option 按逻辑归类——分类是否有效,取决于你是否严格遵守它的结构规则和语义约束。
必须嵌在 select 里,且只能直接包裹 option
浏览器只在 select 上下文中识别 optgroup。把它写在 div 里、放在 select 外、或中间插个空格文本节点,都可能导致整个分组被忽略。
-
optgroup必须是select的**直属子元素**,不能嵌套在另一个optgroup或option里 - 内部只允许出现
option元素,不能有div、span、注释甚至多余换行(旧版 Safari 对空白敏感) - 错误示例:
<select><div><optgroup label="A"><option>x</option></optgroup></div></select>→ 分组失效
label 属性不可省,且不能为空字符串
没有 label,optgroup 就等于不存在——浏览器不会渲染标题,也不会向屏幕阅读器播报分组信息。
- 写成
<optgroup><option>苹果</option></optgroup>或<optgroup label=""></optgroup>,结果都是“看不见的分组” - label 值需为纯文本,不支持 HTML 实体、换行符或内联样式;中文建议控制在 2–4 字,如
label="华东"而非label="地理位置-第一大区" - 动态生成时记得
.trim(),避免label="前端 "这类带尾随空格的写法
禁用整组不是靠 disabled 属性
optgroup 上加 disabled 是无效的:标题仍显示,内部 option 依然可选。真要禁用一组,得单独给每个 option 加 disabled。
-
<optgroup disabled label="已下线"><option value="v1">1.0</option></optgroup>→ 标题可见,选项仍能点中 - 正确做法:
<optgroup label="已下线"><option value="v1" disabled>1.0</option></optgroup> - 如果分组内容动态变化,JS 中需遍历其
children并逐个设disabled = true,不能只操作optgroup自身
样式微调只做三件事,别碰伪元素和背景色
浏览器对 optgroup 的 CSS 支持极弱:color 和 font-weight 基本可用,但 background、padding、border 在多数环境(尤其是 iOS Safari 原生选择器)中完全无效。
- 安全写法仅限:
optgroup { font-weight: bold; color: #666; margin-top: 0.5em; } - 不要用
optgroup::before或display: none隐藏分组——前者不生效,后者破坏可访问性 - 超过 50 个选项时,
optgroup已经撑不住了;该切搜索型组件(如 Choices.js)就切,别硬加十组optgroup堆砌
真正容易被忽略的点是:分组逻辑必须贴合用户认知,而不是数据库字段或字母顺序。比如国家列表按大洲分,比按首字母 A–Z 平均切 10 组,更能减少滚动和误点——这和标签怎么写无关,但决定了 optgroup 到底有没有用。











