Тег optgroup (от английского option group, «группа вариантов») собирает варианты option внутри select в группу с общим заголовком. Заголовок задаёт атрибут label, а сама группа в данные формы не отправляется: на сервер уходит только value выбранного варианта. Закрывающий </optgroup> можно опустить, если сразу за группой идёт другой optgroup или конец select.
Группы собирает тег select, а сами варианты описаны на странице про тег option. Основы выбора из списка разобраны в уроке «Выпадающий список в HTML: select и option».
<select name="food">
<optgroup label="Фрукты">
<option value="a">Яблоко</option>
<option value="p">Груша</option>
</optgroup>
<optgroup label="Овощи">
<option value="c">Морковь</option>
</optgroup>
</select>
В этой статье
- Тег optgroup в HTML: что это и где его записывают
- Атрибут label: заголовок группы
- Что записывают внутри optgroup: option, hr и вложенные группы
- Отключённая группа: атрибут disabled
- Что уходит на сервер и как узнать группу выбранного варианта
- Группы в списке с size и multiple
- Тег optgroup и JavaScript: createElement, label и parentElement
- CSS для optgroup: что стилизуется и customizable select
- Доступность optgroup: роль group и название группы
- Атрибуты тега optgroup
- Вопросы про тег optgroup: заголовок без группы и выбор всей группы
- Частые ошибки с тегом optgroup
Тег optgroup в HTML: что это и где его записывают
Группа нужна, когда вариантов много и их удобно разделить по смыслу: фрукты и овощи, страны по частям света. Заголовок показывается над вариантами группы жирным шрифтом, а сами варианты сдвигаются вправо. Выбрать заголовок нельзя: он не является вариантом. В одном списке допустимы и группы, и одиночные option. Родителем optgroup может быть только select: запись в div, form или datalist недопустима.
<select name="c">
<option value="0">Не выбрано</option>
<optgroup label="Фрукты">
<option value="a">Яблоко</option>
</optgroup>
</select>
Пример: список без групп и с группами
Выберите запись: под результатом число групп, вариантов и прямых потомков select.
Атрибут label: заголовок группы
Атрибут label задаёт заголовок группы, и по описанию стандарта он обязателен, если внутри нет legend. Без него проверка HTML сообщает об ошибке, а заголовок пустой. Пустой label="" ошибки не вызывает, но заголовок получается пустым, и группа ничем не отличается от обычного списка. В скрипте заголовок читается и меняется свойством label.
<optgroup label="Фрукты">
<option>Яблоко</option>
</optgroup>
Пример: группа с label, без него и с пустым
Выберите запись: под результатом свойство label и наличие атрибута.
Что записывают внутри optgroup: option, hr и вложенные группы
Внутри optgroup записывают только option. Группы идут одна за другой, между ними допустим разделитель hr. Вложенных групп не бывает: браузер закрывает первую группу пустой, а вторая становится её соседкой. Разделитель hr внутри группы тоже закрывает её, и следующие варианты оказываются вне группы. Текст прямо в optgroup недопустим. Закрывающие теги можно опустить: браузер сам разделит группы.
<optgroup label="A">
<option>1</option>
</optgroup>
<hr>
<optgroup label="B">
<option>2</option>
</optgroup>
Пример: как браузер разбирает группы
Выберите запись: под результатом потомки select, число групп и вариантов.
Отключённая группа: атрибут disabled
Атрибут disabled отключает группу целиком. Список показывает её серой, варианты внутри выбрать мышью нельзя, а стрелки клавиатуры их пропускают. У самих вариантов свойство disabled остаётся false, но псевдокласс :disabled на них совпадает. Скрипт может выбрать вариант отключённой группы, но в данные формы он не попадёт. Свойство disabled группы можно переключать, и варианты станут доступны снова.
<optgroup label="Овощи" disabled>
<option value="3">Морковь</option>
</optgroup>
Пример: отключённая группа
Выберите запись: под результатом состояние группы, варианта и данные формы.
Что уходит на сервер и как узнать группу выбранного варианта
В данные формы попадает пара из name списка и value выбранного варианта. Группа в них не входит. Если серверу нужно знать группу, её определяют по value (например, коды вариантов группы начинаются с одной цифры) или добавляют второе поле. В скрипте группу выбранного варианта получают через option.parentElement.label или option.closest("optgroup"), а для варианта вне группы результат пустой. Атрибут name у optgroup не работает: браузер его игнорирует, а проверка HTML сообщает об ошибке.
const option = select.selectedOptions[0];
const group = option.closest("optgroup");
console.log(group ? group.label : "нет группы");
Пример: что уходит на сервер и какая группа у выбранного
Выберите вариант в списке: под результатом данные формы и группа выбранного.
Группы в списке с size и multiple
В выпадающем списке группы видны при раскрытии. В списке с size или multiple заголовки всегда на виду: они выделены жирным, а варианты сдвинуты вправо. Клик по заголовку ничего не выбирает, события change не будет. При multiple можно выбрать несколько вариантов из разных групп, а заголовки остаются невыбираемыми.
<select name="c" size="6" multiple>
<optgroup label="Фрукты">
<option value="1">Яблоко</option>
</optgroup>
</select>
Пример: группы в списке с size и multiple
Выберите запись и кликайте по заголовкам и вариантам: под результатом выбор и данные формы.
Тег optgroup и JavaScript: createElement, label и parentElement
Группу создают через document.createElement("optgroup"), задают label, добавляют в неё варианты через appendChild(new Option(...)) и подключают группу к списку через select.add(group). Группы не входят в select.options: там только варианты, зато select.children содержит группы, одиночные option и hr. Группа варианта хранится в option.parentElement. Свойства label и disabled читаются и меняются.
const group = document.createElement("optgroup");
group.label = "Овощи";
group.appendChild(new Option("Морковь", "3"));
select.add(group);
Пример: создание группы и чтение её свойств
Выберите запись и нажмите «Выполнить»: под результатом ответ скрипта.
CSS для optgroup: что стилизуется и customizable select
Особых CSS-свойств у optgroup нет. Браузер рисует заголовок жирным и без отступа, а варианты сдвигает вправо. В списке с size стили группы (color, font-style, font-size, background) действуют и наследуются вариантами. В раскрывающемся списке оформление зависит от браузера. В customizable select заголовок можно записать тегом legend внутри optgroup и оформить как обычный элемент. Такой режим включает appearance: base-select, его записывают внутри @supports.
optgroup {
color: #7a1f1f;
font-style: italic;
}
Пример: стили групп и base-select
Выберите вариант оформления: под результатом вычисленные стили группы и варианта.
Доступность optgroup: роль group и название группы
У optgroup неявная роль group, и менять её через role не следует: проверка HTML считает это ошибкой. Название группы берётся из label, поэтому у группы с пустым заголовком названия нет. Название самого списка задают через label или aria-label у select. Как задать название списку, показано в уроке «Элементы форм в HTML: select, textarea, checkbox и radio».
<select aria-label="Продукт">
<optgroup label="Фрукты">
<option value="1">Яблоко</option>
</optgroup>
</select>
Пример: название группы и состояние вариантов
Выберите запись: под результатом группы, их названия и состояние вариантов.
Атрибуты тега optgroup
Группа принимает глобальные атрибуты и те, что собраны в таблице. Атрибуты списка (name, multiple, size) записывают у select. Несуществующие атрибуты отмечены отдельно: браузер их игнорирует, а проверка HTML сообщает об ошибке.
| Атрибут | Статус | Что делает | Пример записи |
|---|---|---|---|
label | актуален | Заголовок группы. Обязателен, если нет legend. Пустой даёт группу без названия | <optgroup label="Фрукты"> |
disabled | актуален | Отключает группу: варианты внутри нельзя выбрать, в данные они не попадут | <optgroup disabled> |
hidden | глобальный | Скрывает группу в списке | <optgroup hidden> |
value | не существует | Значение задают у option, группа его не имеет | <optgroup value="1"> |
selected | не существует | Выбирают вариант, а не группу | <optgroup selected> |
name | не существует | Атрибут name записывают у select | <optgroup name="g"> |
multiple | не существует | Режим множественного выбора записывают у select | <optgroup multiple> |
placeholder | не существует | Подсказку делают первым пустым вариантом, а не атрибутом | <optgroup placeholder="x"> |
role | не менять | Роль group задана тегом, переопределять её не следует: проверка HTML сообщает об ошибке | <optgroup role="menu"> |
Вопросы про тег optgroup: заголовок без группы и выбор всей группы
Заголовок в списке можно сделать и без optgroup, а выбрать сразу всю группу хотят многие: как сделать заголовок без optgroup и как выбрать сразу все варианты группы.
Как сделать заголовок без optgroup?
Подойдёт отключённый option перед вариантами: выбрать его нельзя, и в данные формы он не уйдёт. Но у такого заголовка есть минусы: он попадает в select.options и считается вариантом, варианты под ним не сдвигаются, а скрипт не найдёт группу через parentElement. Если нужен только визуальный разделитель, достаточно hr.
<select name="c">
<option disabled>Фрукты</option>
<option value="1">Яблоко</option>
</select>
Пример: заголовок через optgroup и через disabled option
Выберите способ: под результатом число вариантов и данные формы.
Как выбрать все варианты группы скриптом?
У группы нет собственного состояния выбора, поэтому выбирают её варианты по одному. Это работает в списке с multiple. В обычном списке выбран один вариант, и каждое новое присваивание selected = true снимает выбор с предыдущего, так что останется последний.
const group = select.querySelector("optgroup");
group.querySelectorAll("option").forEach((o) => {
o.selected = true;
});
Пример: выбор всех вариантов группы
Нажмите кнопку над результатом: под результатом выбранные варианты и данные формы.
Частые ошибки с тегом optgroup
Ошибки с группой в основном про вложенность, атрибуты и ожидания от отправки формы.
| Ошибка | Что происходит | Как исправить |
|---|---|---|
Группа без label | Заголовка нет, проверка HTML сообщает об ошибке | Записать label с названием группы |
optgroup внутри optgroup | Вложенных групп нет: вторая становится соседней, а варианты после неё остаются вне групп | Записать группы одна за другой |
Текст прямо в optgroup | Запись недопустима, проверка HTML сообщает об ошибке | Записывать только option |
hr внутри группы | Группа закрывается, следующие варианты оказываются вне неё | Записывать hr между группами |
optgroup вне select | Запись в div, form или datalist недопустима | Записать группу внутри select |
value или selected у optgroup | Атрибуты не работают, проверка HTML сообщает об ошибке | Записать их у option |
| Ждут, что группа уйдёт на сервер | Уходит только value выбранного варианта | Закодировать группу в value или читать её скриптом |
| Попытка выбрать заголовок группы | Заголовок не является вариантом, клик по нему ничего не выбирает | Для выбираемого пункта записать option |
Подсчёт вариантов через select.children | В результат попадают группы, hr и одиночные option | Использовать select.options |