Skip to content

Segmented ControlForm-associated

2.89 KB gzip2.49 KB brotli2.98 KB zstd Baseline 2023 Widely available

Every feature it needs is Baseline widely available.

Works in Chrome 112+, Edge 112+, Firefox 119+, Safari 16.5+.

Why these versions:

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
divindicator - Slides behind the checked option
slotdefault - Your option buttons

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.

Tip

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.

Tip

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.