select
Dropdown menu for choosing from a list of predefined options. Vanilla Breeze resets the native appearance and adds a custom SVG chevron, consistent sizing, and focus styling via design tokens.
When to Use
- Choosing from a predefined list (countries, categories, sizes)
- When the list has more than 5 options (otherwise consider radio buttons)
- When screen space is limited
- When the user cannot enter custom values
Consider alternatives:
Examples
Basic select, optgroup categorization, multiple selection, and disabled states.
Basic Select
<label for="country">Country</label><select id="country" name="country"> <option value="">Select a country...</option> <option value="us">United States</option> <option value="ca">Canada</option> <option value="uk">United Kingdom</option></select>
With Option Groups
Organize options into categories using optgroup.
<select id="product"> <option value="">Select a product...</option> <optgroup label="Electronics"> <option value="laptop">Laptop</option> <option value="phone">Smartphone</option> </optgroup> <optgroup label="Accessories"> <option value="case">Phone Case</option> <option value="charger">Charger</option> </optgroup></select>
Multiple Selection
Allow selecting multiple options with the multiple attribute. Use size to control how many options are visible.
<select multiple size="5"> <option value="html">HTML</option> <option value="css">CSS</option> <option value="js">JavaScript</option> <option value="python">Python</option> <option value="rust">Rust</option></select>
Disabled States
Disable the entire select or individual options within it.
<!-- Entire select disabled --><select disabled> <option>Cannot change</option></select> <!-- Individual option disabled --><select> <option value="free">Free</option> <option value="pro">Pro - $29/mo</option> <option value="enterprise" disabled>Enterprise (Contact us)</option></select>
Attributes
| Attribute | Purpose | Example |
|---|---|---|
name |
Form field name for submission | name="country" |
required |
Field must have a non-empty value | required |
disabled |
Prevents selection | disabled |
multiple |
Allow selecting multiple options | multiple |
size |
Number of visible options (useful with multiple) |
size="5" |
autocomplete |
Autofill hint | autocomplete="country" |
With form-field
Wrap a select in the form-field custom element for enhanced validation, required indicators, and helper text.
<form-field> <label for="department">Department</label> <select id="department" name="department" required> <option value="" disabled selected>Select department...</option> <option value="sales">Sales</option> <option value="engineering">Engineering</option> </select></form-field>
Accessibility
- Always use a label: Every select needs an associated label, either wrapping or via
for/id - Use autocomplete: Add appropriate
autocompletevalues for autofill (e.g.,country) - Keyboard navigation: Arrow keys navigate options; typing jumps to matching text
- Option groups: Help screen readers understand option categories
- Avoid onChange submission: Do not submit forms automatically on select change without warning
- Multiple select guidance: Provide visible instructions for Ctrl/Cmd-click
CSS Reference
VB sets appearance: none to remove the native dropdown arrow and replaces it with a custom SVG chevron positioned via background-image. The select inherits shared input styles (border, radius, focus ring) from the form layer.
/* Select inherits shared input styles, then overrides: */ select { appearance: none; padding-inline-end: var(--size-xl); background-image: url("data:image/svg+xml,...chevron-svg..."); background-repeat: no-repeat; background-position: right var(--size-xs) center; background-size: 1.25rem; cursor: pointer;} select:disabled { cursor: not-allowed;} /* Multiple select removes the custom chevron */select[multiple] { padding: var(--size-xs);} optgroup { font-weight: 600;}
Customizable Select
Chrome 135+ ships appearance: base-select, which unlocks full CSS control over the dropdown picker, options, checkmark icon, and open/close animations — while retaining native semantics, keyboard navigation, form participation, and accessibility.
VB wraps all customizable-select styles in @supports (appearance: base-select), making this a zero-risk progressive enhancement. Non-supporting browsers keep the existing appearance: none + SVG chevron.
What Changes Automatically
- Dropdown picker gets surface background, border, radius, shadow, and max-height scroll
- Options gain hover highlight, checked color, and rounded corners
- Checkmark icon uses
--color-interactive - Chevron rotates 180° on open
- Picker animates in with opacity + translateY (respects
prefers-reduced-motion) <optgroup>headers render as uppercase muted section labels with dividers
No markup changes are required — every existing <select> upgrades automatically.
Rich Content
For selects with images, icons, or descriptions inside options, add a <button> trigger with <selectedcontent> to mirror the selected option in the closed state.
<select name="language"> <button> <selectedcontent></selectedcontent> </button> <option value="en"> <span aria-hidden="true">🇺🇸</span> English <span class="detail"> — American English</span> </option> <option value="es"> <span aria-hidden="true">🇪🇸</span> Español <span class="detail"> — Spanish</span> </option> <option value="fr"> <span aria-hidden="true">🇫🇷</span> Français <span class="detail"> — French</span> </option></select>
<button>becomes the trigger — VB styles it as a flex container<selectedcontent>automatically clones the selected option's content- Elements with
class="detail"are hidden in the closed trigger to keep it compact - Images inside options are sized to
1.5emwithborder-radiusandobject-fit: cover
Styling Reference
The base-select value exposes these pseudo-elements and states:
| Selector | What It Targets |
|---|---|
::picker(select) |
The dropdown popup container |
::picker-icon |
The built-in chevron arrow |
::checkmark |
The selected-option indicator |
:open |
Select while picker is visible |
selectedcontent |
Cloned content of selected option in trigger |
Select vs Combo Box
Use this table to decide between the native customizable select and VB's combo-box web component.
| Capability | Customizable Select | combo-box |
|---|---|---|
| JavaScript required | No | Yes |
| Filterable / searchable | No (type-ahead only) | Yes |
| Rich content in options | Yes (images, icons, text) | Yes |
| Form participation | Native | Manual (hidden input) |
| Browser support | Chrome 135+ | All modern browsers |
| Styled dropdown | Yes (with @supports gate) | Yes |
Browser Support
appearance: base-select ships in Chrome 135 (April 2025). Other browsers are implementing it — check caniuse for current status.
VB's implementation is fully gated behind @supports:
@supports (appearance: base-select) { select:not([multiple]) { appearance: base-select; /* ... all customizations ... */ }} /* Non-supporting browsers keep: */select { appearance: none; background-image: var(--select-chevron);}
Detect in JavaScript:
if (CSS.supports('appearance', 'base-select')) { // Customizable select is active}
Related
- option - Individual options within a select
- optgroup - Group related options with a label
- selectedcontent - Clone selected option content in the trigger button
- datalist - Autocomplete with custom values
- combo-box - Fully custom filterable dropdown
- form-field - Enhanced select with validation
- label - Required for accessibility