Segmented ControlForm-associated
2.89 KB gzip2.49 KB brotli2.98 KB zstdEvery feature it needs is Baseline widely available.
Works in Chrome 112+, Edge 112+, Firefox 119+, Safari 16.5+.
Why these versions:
- ARIA attribute reflection needs
Firefox 119+. - Nesting needs
Chrome 112+,Edge 112+andSafari 16.5+.
Partially supported:
- Nesting (nesting) — Chrome, Chrome Android and Edge ship it partially before 120 and Safari and Safari on iOS ship it partially before 17.2.
sv-segmented-control is a single-selection control, comparable to a radio button group, that submits its selected value with forms.
Usage
<label for="plan">Choose a plan</label>
<sv-segmented-control id="plan" value="1"> <button value="1">Personal</button> <button value="2">Business</button> <button value="3">Enterprise</button> <button value="4" disabled>Custom</button></sv-segmented-control>Only direct child <button> elements become options, and each one needs its own value.
Selection states
The selected background is painted by two things: a pill that slides between buttons during the animation, and the button itself once it settles. Give both the same fill, or the color jumps at the end:
/* Moving pill */sv-segmented-control::part(indicator) { background-color: hotpink;}
/* Resting background */sv-segmented-control button[data-sv-active]::before { background-color: hotpink;}data-sv-active only lands once the animation finishes. Style anything that has to change at once, like text color, on aria-checked="true" instead.
Orientation
--sv-segmented-control-flex-dir beats the vertical attribute wherever it is set. Setting flex-direction on the element does nothing, since the flex container lives in the shadow root.
Arrow keys and aria-orientation follow the rendered axis, whichever one set it.
Keyboard
| Key | Behavior |
|---|---|
ArrowRight, ArrowDown | Selects the next enabled option, wrapping round |
ArrowLeft, ArrowUp | Selects the previous enabled option, wrapping |
Arrow keys walk the buttons in visual order, accounting for dir and --sv-segmented-control-flex-dir.
Accessibility
The control is a radio group with a different look. Name it with <label for>, aria-label, or aria-labelledby.
Structure
divcontainer
API References
Methods
setValue()
Selects a value and slides the indicator to the matching button, optionally overriding the animation.
type IndicatorAnimationOptions = { duration?: number; easing?: string;};Properties
value
The current selected value. Setting it slides the indicator, the same as calling setValue().
defaultValue
The original (or default) value of the segmented control. It reflects the element's value attribute.
required
If true, the user must select a value before submitting a form.
disabled
Disable the whole group preventing to select any option.
name
The name of the control, submitted with the form data.
vertical
Whether the buttons are laid out vertically, which also decides aria-orientation. Reflects to the vertical attribute.
This is only the default axis. The --sv-segmented-control-flex-dir custom property takes any flex-direction value and overrides it wherever it is set, so the axis can follow a media query.
@media (max-width: 600px) { sv-segmented-control { --sv-segmented-control-flex-dir: column; }}Attributes
"disabled"
Prevents user interaction.
"value"
The current selected value. Setting it slides the indicator, the same as calling setValue().
"required"
If true, the user must select a value before submitting a form.
"vertical"
Whether the buttons are laid out vertically, which also decides aria-orientation. Reflects to the vertical attribute.
This is only the default axis. The --sv-segmented-control-flex-dir custom property takes any flex-direction value and overrides it wherever it is set, so the axis can follow a media query.
@media (max-width: 600px) { sv-segmented-control { --sv-segmented-control-flex-dir: column; }}Events
valuechange
Fired after value changes, whether by the user or from code.
optionclicked
Fired when the user clicks an option, or moves to it with an arrow key, before the value changes. Cancel it to keep the current value.
Slots
| Name | Description |
|---|---|
Default | The buttons which represent the segmented control options. |
CSS Properties
| Name | Description | Default |
|---|---|---|
--sv-segmented-control-bg | Background color for the container and all inactive buttons. | --sv-gray-6 |
--sv-segmented-control-active-bg | Background color applied to the selected (active) button. | --sv-accent |
--sv-segmented-control-active-clr | Text color for the selected (active) button. | --sv-accent-content |
--sv-segmented-control-hover-bg | Background color shown when a button is hovered. | --sv-gray-5 |
--sv-segmented-control-bdr-clr | Border color applied to the container. | --sv-gray-5 |
--sv-segmented-control-bdr-sz | Thickness of the container’s border. | --sv-bdr-sz-sm |
--sv-segmented-control-bdr-rad | Border radius for both the container and its buttons. Button radius is derived from this value and the surrounding spacing. | --sv-bdr-rad-lg |
--sv-segmented-control-pad | Spacing between the buttons and the container edge. | 0.5em |
--sv-segmented-control-flex-dir | A flex-direction value that lays the buttons out. Set from outside to override the vertical attribute. | row |
--sv-segmented-control-dur | Duration of the toggle animation. | 350ms |
--sv-segmented-control-ease | Easing curve used for toggle animations. | cubic-bezier(0.16, 1, 0.3, 1) |
CSS Parts
| Name | Description |
|---|---|
::part(container) | Segmented control container element. |
::part(indicator) | Segmented control indicator element. |