I want to hide an optgroup element when it doesn’t have any option element which cannot be selected. In the example below the first optgroup element shall be shown and the second should be hidden.
optgroup {
display: none;
}
optgroup:has(option:not(:disabled)) {
display: unset;
}
<select id="location" name="location">
<option value="" selected="">Standort wählen</option>
<optgroup label="Kanton Luzern">
<option value="buttisholz">Buttisholz</option>
<option value="littau" disabled="">Littau</option>
<option value="luzern">Luzern</option>
<option value="malters" disabled="">Malters</option>
<option value="schuepfheim">Schüpfheim</option>
</optgroup>
<optgroup label="Kanton Schaffhausen">
<option value="schaffhausen" disabled="">Schaffhausen</option>
</optgroup>
</select>
I have come up with this solution which seems to work (only tested in Chrome) but I am looking for a solution with just one statement instead of 2 if that is possible:
optgroup {
display: none;
}
optgroup:has(option:not(:disabled)) {
display: unset;
}
I tried this version which doesn’t work because it seems that the :enabled pseudo selector can only be used for input, select and textarea fields:
optgroup:not(option:enabled) {
display: none;
}
2
Answers
Here’s a single-statement solution that should work across modern browsers and provide the desired behavior of hiding optgroup elements that do not have any non-disabled option elements.
Here’s how it works:
The optgroup:not(:has(option:not(:disabled))) selector selects all
optgroup elements that do not have a child option element that is not
disabled.
The :has() pseudo-class is used to check if the optgroup element has
a child option element that is not disabled.
The :not() pseudo-class is then used to negate this condition,
effectively targeting the optgroup elements that do not have any
non-disabled option elements as children.
The display: none; rule is then applied to the targeted optgroup
elements, hiding them.
Keep it simple and readable!
use css
:enabled