The <optgroup> Element
A comprehensive beginner-to-guru lesson on the HTML <optgroup> element, semantic option grouping, labels, disabled groups, customizable selects, accessibility, DOM APIs, form boundaries, security, testing, and resilient component architecture.
Basic
What problem does <optgroup> solve?
<optgroup> gives a <select> a semantic group for related <option> elements. The group is not itself selectable: it organizes choices so users can understand the structure of a long option list.
The beginner mental model
Think of a select as a set of choices and an optgroup as a labeled shelf inside that set. The shelf organizes options; the user still selects an option, never the shelf itself.
The smallest useful example
A conventional select can group options with a label. The label is part of the control UI, while each option remains an individual selectable value.
<select name="language">
<optgroup label="European languages">
<option value="en">English</option>
<option value="fr">French</option>
</optgroup>
<optgroup label="Asian languages">
<option value="ja">Japanese</option>
<option value="ko">Korean</option>
</optgroup>
</select>Output
Ready to run.
Quick check
Complete the HTML with the element that creates the labeled group of options.
<>
<option>English</option>
</optgroup>
Why grouping matters
Grouping is useful when the relationship between choices is meaningful to the user. It should reduce search effort and clarify categories, not merely create visual decoration.
Optgroup is not a generic container
Do not treat optgroup as a generic div-like wrapper. Its meaning is specific to select controls and is interpreted by the browser as an option group.
Optgroup is not selectable
Only option elements represent selectable choices. An optgroup contributes organization and labeling, but it never becomes the selected value.
Where <optgroup> is allowed
The current HTML Standard permits optgroup as a descendant of select. Its content model is deliberately constrained so the browser can maintain the select option model.
The content model at a glance
In the current model, an optgroup may contain an optional legend followed by option elements and the script-supporting or wrapper content permitted by the customizable-select model. This differs from the older mental model of “only options.”
Traditional selects and customizable selects
Traditional selects use the label attribute for the group name. Customizable selects can use a first-child legend, which creates a richer styling and labeling surface while preserving the group semantics.
The label attribute
The label attribute supplies the group name used by the select UI. It is required when a group has no child legend, so an unlabeled optgroup is not a complete authoring pattern.
Writing a useful group label
A group label should identify the common category shared by its options. It should not repeat every option name or become a marketing sentence.
Label versus option text
The optgroup label names the category; each option names one choice. Keeping those responsibilities separate makes both the visual hierarchy and accessible interpretation clearer.
The first-child legend
In a customizable select, a legend may be the first element child of optgroup. The standard uses that legend as the group label and gives authors a targetable element for richer presentation.
Legend replaces the label for the group name
When an optgroup has a first-child legend, the current standard derives the group label from that legend rather than the label attribute. This creates a deliberate semantic bridge between the older and customizable-select models.
Intermediate
Why the legend must be first
The first-child position is part of the algorithm. Putting a legend later in the group does not turn it into the group caption.
What belongs inside the group
An option belongs to the optgroup when it is a descendant of that optgroup under the select option model. Wrapper elements used by customizable selects do not create a new semantic group.
Optgroups cannot be nested
Optgroups are not recursive categories. The standard does not permit one optgroup to contain another, so deeper taxonomy should be represented by a different control design rather than fake nested groups.
When one level is not enough
If users genuinely need multiple levels of classification, forcing a hierarchy into one select often creates a poor interaction model. Consider separate controls or a different information architecture instead.
The disabled attribute
The disabled attribute disables the option group as a unit. Its options become unavailable for selection through the native select interaction.
Disabled group versus disabled option
A disabled optgroup communicates that the category itself is currently unavailable; a disabled option communicates that one particular choice is unavailable. Use the smallest accurate scope.
<optgroup label="Unavailable category" disabled>
<option value="a">Choice A</option>
<option value="b">Choice B</option>
</optgroup>
<optgroup label="Available category">
<option value="c" disabled>Choice C</option>
<option value="d">Choice D</option>
</optgroup>Quick check
Which change disables every option in the "Unavailable" group without disabling the other group?
<optgroup label="Unavailable">
<option value="a">Choice A</option>
</optgroup>
Disabled does not mean hidden
Disabled options remain part of the control structure. Do not assume that disabled means absent, removed, or inaccessible to every form of programmatic inspection.
Dynamic disabledness
Changing optgroup.disabled through JavaScript changes the group state. Components should treat this as state mutation, not as a substitute for authorization or server-side validation.
The form boundary
Optgroup participates in the select structure, not as an independent form control. Form submission is owned by the select and its selected options.
<form>
<label for="pet">Pet</label>
<select id="pet" name="pet">
<optgroup label="Domestic">
<option value="cat">Cat</option>
<option value="dog">Dog</option>
</optgroup>
</select>
</form>Advanced
The name attribute is not an optgroup attribute
Optgroup does not have a name attribute that contributes a submitted field. The select owns the form-data name; the group supplies organization.
The value boundary
An optgroup has no value of its own. If a user selects an option inside it, the selected option supplies the value that the select contributes to form data.
Selection state belongs to option
Do not build application state around a selected optgroup because there is no such state. Read selection from the select and its options.
The HTMLOptGroupElement interface
The DOM interface is HTMLOptGroupElement. Its core reflected properties are disabled and label, matching the element-specific content attributes.
Reading and writing disabled
The disabled IDL property reflects the boolean disabled attribute. Setting it through JavaScript is equivalent to changing that element state in the DOM.
Reading and writing label
The label IDL property reflects the label attribute. It represents the authored group label; in a customizable select, the effective displayed group label can instead come from the first legend.
The label algorithm
The current standard defines an effective optgroup label algorithm: use the first legend when present, otherwise use the label attribute, otherwise the result is the empty string. This is a useful model for debugging unexpected group names.
<select>
<optgroup label="Fallback label">
<legend>Customizable label</legend>
<option>One</option>
</optgroup>
</select>Customizable select structure
Customizable selects introduce wrapper and button structure around the select’s option model. Optgroup remains the semantic grouping mechanism while the internal presentation can become richer.
<select>
<button>
<selectedcontent></selectedcontent>
</button>
<optgroup>
<legend>Animals</legend>
<option value="cat"><span>Cat</span></option>
<option value="dog"><span>Dog</span></option>
</optgroup>
</select>Rich option content changes the possibilities
Customizable selects can give options richer content than traditional text-only options. This makes optgroup useful for organizing richer choices without turning it into a generic layout container.
Optgroup legend versus select button
The optgroup legend labels a group inside the popup/list of choices. The select button represents the currently selected choice. They solve different problems and should not be conflated.
Accessibility starts with grouping
A group label gives users of assistive technology and other nonvisual representations the category relationship that sighted users may perceive from indentation or typography.
Do not replace native semantics casually
If a native select and optgroup already express the interaction you need, replacing them with generic divs and ARIA recreates a large amount of browser behavior. Native semantics should be the default starting point.
ARIA role boundaries
The current technical summary gives optgroup an implicit group role and does not permit an arbitrary role override. Authors should therefore use the element for its native semantics rather than trying to turn it into another widget.
Keyboard interaction belongs to select
Keyboard navigation and selection behavior belong to the select control and browser UI. Optgroup supplies grouping information; it should not become a keyboard widget of its own.
Screen-reader expectations
Exact announcements vary by browser and assistive technology, but a meaningful group label gives the accessibility tree useful category information. Test the actual control rather than relying on a visual simulation.
Localization of group labels
Group labels are user-facing text and must be localized like option labels. Avoid concatenating language-specific prefixes or assuming that a category has the same grammatical form in every locale.
RTL and bidirectional text
Right-to-left presentation does not change the semantic role of optgroup. Keep category and option strings properly localized and let document direction and bidirectional isolation handle text presentation where needed.
Long groups and information architecture
If a group contains dozens of options, adding more groups is not automatically the solution. Review the number of choices, grouping quality, search needs, and whether another control would reduce cognitive load.
Empty groups
An optgroup without useful options provides no meaningful choice grouping. Empty groups should normally be removed from the rendered control or populated only when application state genuinely requires them.
Generated groups
Server-rendered and client-generated optgroups should follow the same semantic contract: stable group labels, stable option values, and no accidental duplicate or empty categories.
Filtering options
If JavaScript filters options, preserve group semantics. Hiding every option in a group can leave an empty heading, so the UI may need to remove or suppress that group while filtering.
Remote data and groups
When groups come from an API, treat group labels as untrusted data and validate the data shape before rendering. The server remains authoritative for permissions and allowed values.
Security is not disabledness
A disabled optgroup is a user-interface state, not an authorization mechanism. A server must still validate the submitted select value against the user’s permissions.
// UI state is not authorization.
const allowed = new Set(["cat", "dog"]);
// Validate the submitted select value on the server as well.Injection boundaries
Group labels and option content are data. When rendering them dynamically, use DOM text/content APIs or properly escaped templating rather than inserting untrusted strings as executable HTML.
Form reset behavior
Resetting the form restores the select’s relevant option selection state according to the form-control model. Optgroup does not own a separate selected value to restore.
Constraint validation
Optgroup is not the constraint-validation owner. Requiredness and validity rules belong to the select and its selected options according to the form-control model.
Submission debugging
When a grouped select submits the wrong value, inspect the select name and selected option value first. Changing the optgroup label cannot change the submitted field name or option value.
DOM mutation and live collections
Adding, removing, or moving options and groups changes the live DOM structure the select uses to construct its option list. Test mutations with the browser’s actual select behavior rather than assuming a static-tree algorithm.
const group = document.querySelector("optgroup");
group.disabled = true;
group.label = "Temporarily unavailable";Framework rendering hazards
Component frameworks can accidentally recreate option and optgroup nodes during updates. Stable keys and predictable ownership help preserve user state and avoid unnecessary DOM churn.
Web Components boundary
A custom component may render optgroups internally, but it should expose a clear data contract for group labels, option values, disabled state, and selection. Do not leak implementation-specific DOM assumptions into application state.
CSS is presentation, not grouping
CSS can style group labels and spacing, but it does not create the semantic grouping relationship. If the DOM lacks optgroup, visual indentation alone is not an equivalent semantic implementation.
Native rendering variability
The browser and operating system control much of a traditional select’s popup rendering. Authors should not depend on a particular font, indentation, separator, or exact group appearance unless the chosen customizable-select model explicitly provides that control.
Testing the semantics
A strong test suite verifies that groups exist where expected, labels are correct, options belong to the intended group, and disabled state is applied at the correct scope.
Testing the form behavior
Behavioral tests should verify selected values and submitted form data, not just screenshots. A visually correct group can still submit an incorrect value if the select or option contract is wrong.
Testing accessibility
Accessibility tests should check the accessible naming and grouping behavior with automated checks plus representative browser and assistive-technology testing. DOM structure alone cannot prove the complete user experience.
Progressive enhancement
A native select with optgroup already has a strong baseline. Enhance its presentation only when the enhancement preserves the underlying control semantics and remains usable when the enhancement fails.
Common mistake: using div for categories
A div can visually separate options in a custom UI, but inside a native select it is not a substitute for optgroup’s grouping semantics. Use the semantic element when the interaction is actually a select.
Common mistake: nesting optgroups
Do not create category > subcategory by nesting optgroup. The element is intentionally one level deep. If the information architecture requires deeper hierarchy, reconsider the control.
Common mistake: putting selection state on the group
Never model an optgroup as the selected entity. Selection belongs to options; the group is context.
Common mistake: trusting disabled for authorization
A disabled group is helpful UI feedback but cannot protect data. Treat every submitted value as untrusted input on the server.
Common mistake: overusing groups
Grouping every few options can make a select harder to scan. A group earns its place when the category helps the user predict and choose among its options.
A practical authoring checklist
Before shipping a grouped select, verify semantic grouping, meaningful labels, valid placement, correct disabled scope, correct option values, accessible labeling, localization, and server-side validation.
Every optgroup has a meaningful group label.
Only options are treated as selectable choices.
No optgroups are nested.
Disabled state is applied at the narrowest correct scope.
The select owns the submitted name and selected value.
Labels and options are localized and accessible.
Server-side validation does not trust disabled UI state.
A practical debugging checklist
When a group looks or behaves incorrectly, inspect the DOM hierarchy, effective group label, disabled state, selected option, select name, option value, and browser support for any customizable-select features in use.
Inspect the DOM hierarchy.
Determine the effective group label.
Check optgroup.disabled and individual option.disabled.
Inspect the select value and selected option.
Check the select name and submitted form data.
Verify browser support for customizable-select features.
Beginner exercise
Build a language select with two meaningful optgroups. Give each group a concise label and verify that selecting an option submits the option value rather than the group label.
Intermediate exercise
Add a temporarily unavailable group and a disabled individual option in another group. Explain why each disabled state belongs at its particular scope and test the keyboard and pointer behavior.
Advanced exercise
Convert a traditional grouped select to a customizable select using first-child legends and rich option content. Preserve the select’s value and accessibility contract while changing only the presentation layer.
Guru exercise
Design a reusable grouped-select component fed by remote data. Define its semantic data contract, stable keys, localization strategy, security validation, progressive fallback, accessibility test plan, and mutation behavior before writing the renderer.
The expert mental model
At expert level, think of optgroup as a semantic node in the select’s option model: it contributes grouping, labeling, and disabledness, while selection, value, validation, and submission remain owned by the select/option system.
Where this lesson stops
This lesson owns optgroup-specific semantics, grouping, labeling, disabledness, DOM API, accessibility, and architecture. The dedicated option, select, legend, and selectedcontent lessons own their respective element-specific behavior; cross-element form validation and submission belong to broader form-control lessons.
Thanks for your feedback.
Mark this learning resource complete to track your learning progress.