您现在的位置是:网站首页 > <optgroup>-选项分组文章详情

<optgroup>-选项分组

<optgroup> 是 HTML 中用于在 <select> 元素内对 <option> 进行分组的标签。它通过视觉或逻辑上的分隔提升用户体验,尤其适合选项数量较多或需要分类的场景。

<optgroup> 的基本语法

<optgroup> 必须嵌套在 <select> 内,且至少包含一个 <option>。其核心属性是 label,用于定义分组的名称(不可省略)。例如:

<select>
  <optgroup label="水果">
    <option value="apple">苹果</option>
    <option value="banana">香蕉</option>
  </optgroup>
  <optgroup label="蔬菜">
    <option value="carrot">胡萝卜</option>
    <option value="tomato">番茄</option>
  </optgroup>
</select>

渲染效果为下拉菜单中显示分组标题“水果”和“蔬菜”,选项分别缩进显示。

分组嵌套与禁用分组

虽然 HTML 标准不允许 <optgroup> 嵌套,但可以通过 disabled 属性禁用整个分组:

<select>
  <optgroup label="可用选项">
    <option value="1">选项1</option>
    <option value="2">选项2</option>
  </optgroup>
  <optgroup label="暂不可用" disabled>
    <option value="3">选项3</option>
    <option value="4">选项4</option>
  </optgroup>
</select>

禁用分组会灰色显示且无法选择其中选项。

动态生成分组选项

通过 JavaScript 可以动态创建分组。以下示例从数据对象生成分组:

const foods = {
  fruits: ["苹果", "香蕉"],
  vegetables: ["胡萝卜", "番茄"]
};

const select = document.createElement('select');
for (const [group, items] of Object.entries(foods)) {
  const optgroup = document.createElement('optgroup');
  optgroup.label = group;
  items.forEach(item => {
    const option = new Option(item, item.toLowerCase());
    optgroup.appendChild(option);
  });
  select.appendChild(optgroup);
}
document.body.appendChild(select);

样式定制技巧

默认分组标题不可选中且样式固定,但可通过 CSS 调整分组和选项样式:

optgroup {
  font-style: normal; /* 取消斜体 */
  background-color: #f0f0f0;
}
optgroup option {
  padding-left: 20px; /* 缩进选项 */
}

实际应用场景

  1. 地区选择器:按大洲分组国家

    <select>
      <optgroup label="亚洲">
        <option value="cn">中国</option>
        <option value="jp">日本</option>
      </optgroup>
      <optgroup label="欧洲">
        <option value="fr">法国</option>
        <option value="de">德国</option>
      </optgroup>
    </select>
    
  2. 商品分类:电子产品按类型分组

    <select>
      <optgroup label="手机">
        <option value="iphone">iPhone</option>
        <option value="samsung">三星</option>
      </optgroup>
      <optgroup label="笔记本">
        <option value="macbook">MacBook</option>
        <option value="surface">Surface</option>
      </optgroup>
    </select>
    

与其他表单元素的联动

结合 <datalist> 实现分组自动补全(注意:部分浏览器可能不支持):

<input list="food-list" placeholder="输入食物名称">
<datalist id="food-list">
  <optgroup label="水果">
    <option value="苹果">
    <option value="香蕉">
  </optgroup>
  <optgroup label="蔬菜">
    <option value="胡萝卜">
    <option value="番茄">
  </optgroup>
</datalist>

无障碍访问建议

为提升可访问性:

  • 确保 label 属性简洁明确
  • 避免过度嵌套导致屏幕阅读器混淆
  • 对禁用分组提供额外说明
<select aria-describedby="help-text">
  <optgroup label="基础套餐">
    <option value="basic1">基础版</option>
  </optgroup>
  <optgroup label="高级套餐" disabled>
    <option value="pro1">专业版</option>
  </optgroup>
</select>
<p id="help-text">高级套餐需升级后可用</p>

浏览器兼容性注意事项

所有现代浏览器均支持 <optgroup>,但需注意:

  • 移动端设备可能以不同方式展示分组
  • 某些旧版本 IE 对动态生成的 <optgroup> 支持有限
  • 打印时分组样式可能丢失

分组数据的表单提交

表单提交时仅包含选中 optionvalue,分组信息不会提交。如需传递分组信息,可通过以下方式:

<select name="food">
  <optgroup label="fruit">
    <option value="fruit_apple">苹果</option>
  </optgroup>
</select>

或使用 JavaScript 在提交时附加数据:

document.querySelector('form').addEventListener('submit', (e) => {
  const select = document.querySelector('select');
  const selectedOption = select.options[select.selectedIndex];
  const group = selectedOption.parentElement.label;
  // 添加隐藏字段
  const input = document.createElement('input');
  input.type = 'hidden';
  input.name = 'food_group';
  input.value = group;
  e.target.appendChild(input);
});

与其他前端框架的整合

在 Vue/React 中动态渲染分组:

// React 示例
function FoodSelect({ groups }) {
  return (
    <select>
      {Object.entries(groups).map(([label, options]) => (
        <optgroup label={label} key={label}>
          {options.map(opt => (
            <option value={opt.value} key={opt.value}>
              {opt.label}
            </option>
          ))}
        </optgroup>
      ))}
    </select>
  );
}
<!-- Vue 示例 -->
<select>
  <optgroup v-for="(options, label) in groups" :label="label">
    <option v-for="opt in options" :value="opt.value">
      {{ opt.label }}
    </option>
  </optgroup>
</select>

分组的多选支持

<optgroup> 同样适用于多选列表框:

<select multiple size="6">
  <optgroup label="前端技术">
    <option>HTML</option>
    <option>CSS</option>
  </optgroup>
  <optgroup label="后端技术">
    <option>Node.js</option>
    <option>Java</option>
  </optgroup>
</select>

性能优化建议

当选项超过 1000 项时:

  • 避免深层嵌套分组
  • 考虑虚拟滚动技术
  • 分组标题尽量简短
// 虚拟滚动优化示例
const virtualSelect = new VirtualScrollSelect({
  options: largeData,
  groupBy: 'category',
  renderGroup: (group) => `<optgroup label="${group}"></optgroup>`
});

我的名片

网名:~川~

岗位:console.log 调试员

坐标:重庆市-九龙坡区

邮箱:cc@qdcc.cn

沙漏人生

站点信息

  • 建站时间:2013/03/16
  • 本站运行
  • 文章数量
  • 总访问量
微信公众号
每次关注
都是向财富自由迈进的一步