您现在的位置是:网站首页 > <optgroup>-选项分组文章详情
<optgroup>-选项分组
陈川
【
HTML
】
20144人已围观
4822字
<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; /* 缩进选项 */
}
实际应用场景
-
地区选择器:按大洲分组国家
<select> <optgroup label="亚洲"> <option value="cn">中国</option> <option value="jp">日本</option> </optgroup> <optgroup label="欧洲"> <option value="fr">法国</option> <option value="de">德国</option> </optgroup> </select>
-
商品分类:电子产品按类型分组
<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>
支持有限 - 打印时分组样式可能丢失
分组数据的表单提交
表单提交时仅包含选中 option
的 value
,分组信息不会提交。如需传递分组信息,可通过以下方式:
<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>`
});
上一篇: <select>-下拉选择框
下一篇: <option>-下拉选项