Fylgja Button Group

A button group is a segmented control: a row of joined buttons where exactly one is selected. It is built from radio inputs styled as buttons inside an input group, so it keeps real single-select semantics and needs no JavaScript.

Preview

<div role="group" aria-label="Text alignment" class="input-group --merge" style="--rounded: var(--radius-4); --btn-stroke: color-mix(in oklab, var(--root-bg) 70%, var(--root-fg))">
	<label class="btn"><input type="radio" name="align" checked>Left</label>
	<label class="btn"><input type="radio" name="align">Center</label>
	<label class="btn"><input type="radio" name="align">Right</label>
</div>

Usage

  • Wrap the options in a <div class="input-group --merge"> with role="group" and an aria-label. The --merge modifier collapses the doubled borders between the buttons so they read as one unit, and rounds the outer ends.
  • Each option is a <label class="btn"> containing an <input type="radio"> that shares one name. The input group hides the radios automatically, so no sr-only is needed.
  • Mark the default option’s radio checked. Fylgja’s button active style targets the label that :has(input:checked), so the selection highlights itself.
  • Set --rounded on the group for the pill shape and --btn-stroke for the border color.

Accessibility

  • Radios give arrow-key navigation and single-select for free; the input group hides them from view but keeps them operable via their labels.
  • The aria-label on the group names the set of choices.

FAQ

Why radios instead of buttons?

Radios give real single-select semantics for free, arrow-key navigation between options, only one chosen, and it submits with a form. The visible buttons are labels wrapping a visually hidden radio.

How does the selected option get highlighted?

Fylgja's button active style applies to a label that :has(input:checked), so the checked radio's label shows the active background with no JavaScript.