Radio group <fieldset>
A set of native radios, shown as the classic dot or as joined buttons — the form counterpart of a segmented control.
<fieldset><fieldset class="l-radio-group">
<legend>View</legend>
<label>
<input
type="radio"
class="l-radio"
name="view"
value="list"
checked
/>
List
</label>
<label>
<input
type="radio"
class="l-radio"
name="view"
value="board"
/>
Board
</label>
</fieldset>The group is a <fieldset> captioned by its <legend>, and each item is a <label> wrapping one <input type="radio">. That is the platform's own way to group and name a set of radios, so there is no ARIA to add and no for/id pair to keep in sync. There is no JavaScript either: radios sharing a name already give single selection, arrow-key navigation, form submission, reset and validation — this is a stylesheet, not a component.
That is the difference with segmented control: use this when the value is submitted with a form, and the segmented control when the choice takes effect immediately.
Options
Appearance
Default
The radio primitive: put .l-radio on each input.
Code
<fieldset
class="l-radio-group"
data-orientation="vertical"
>
<legend>Notifications</legend>
<label>
<input
type="radio"
class="l-radio"
name="notifications"
value="all"
checked
/>
All new messages
</label>
<label>
<input
type="radio"
class="l-radio"
name="notifications"
value="mentions"
/>
Direct messages and mentions
</label>
<label>
<input
type="radio"
class="l-radio"
name="notifications"
value="none"
/>
Nothing
</label>
</fieldset>Button
Add data-appearance="button" on the group and .l-button on each label. The items are joined into a single unit and the selected one keeps the button's active fill.
Code
<fieldset
class="l-radio-group"
data-appearance="button"
>
<legend>View</legend>
<label class="l-button">
<input
type="radio"
name="view"
value="list"
checked
/>
List
</label>
<label class="l-button">
<input
type="radio"
name="view"
value="board"
/>
Board
</label>
<label class="l-button">
<input
type="radio"
name="view"
value="calendar"
/>
Calendar
</label>
</fieldset>Naming the group
The <legend> names the group — the technique WCAG H71 and RGAA 11.6 ask for. When no visible caption fits, a view switcher in a toolbar for instance, drop the <legend> and name the <fieldset> with aria-label instead.
<fieldset
class="l-radio-group"
data-appearance="button"
aria-label="View"
>
<label class="l-button">…</label>
</fieldset>Orientation
Add data-orientation="vertical" to stack the items. Works in both appearances.
Code
<fieldset
class="l-radio-group"
data-appearance="button"
data-orientation="vertical"
>
<legend>Delivery</legend>
<label class="l-button">
<input
type="radio"
name="delivery"
value="standard"
checked
/>
Standard
</label>
<label class="l-button">
<input
type="radio"
name="delivery"
value="express"
/>
Express
</label>
<label class="l-button">
<input
type="radio"
name="delivery"
value="pickup"
/>
Pickup
</label>
</fieldset>Sizes
In the button appearance, set data-size on every label so the group stays even. Any .l-button size works.
Code
<fieldset
class="l-radio-group"
data-appearance="button"
>
<legend>Small</legend>
<label
class="l-button"
data-size="sm"
>
<input
type="radio"
name="density-sm"
value="compact"
checked
/>
Compact
</label>
<label
class="l-button"
data-size="sm"
>
<input
type="radio"
name="density-sm"
value="cosy"
/>
Cosy
</label>
</fieldset>
<fieldset
class="l-radio-group"
data-appearance="button"
>
<legend>Medium</legend>
<label class="l-button">
<input
type="radio"
name="density-md"
value="compact"
checked
/>
Compact
</label>
<label class="l-button">
<input
type="radio"
name="density-md"
value="cosy"
/>
Cosy
</label>
</fieldset>
<fieldset
class="l-radio-group"
data-appearance="button"
>
<legend>Large</legend>
<label
class="l-button"
data-size="lg"
>
<input
type="radio"
name="density-lg"
value="compact"
checked
/>
Compact
</label>
<label
class="l-button"
data-size="lg"
>
<input
type="radio"
name="density-lg"
value="cosy"
/>
Cosy
</label>
</fieldset>Disabled segment
Add disabled to a segment's input. Arrow keys skip it, and it drops out of the tab order — both from the browser, not from us.
Code
<fieldset
class="l-radio-group"
data-appearance="button"
>
<legend>Plan</legend>
<label class="l-button">
<input
type="radio"
name="plan"
value="free"
checked
/>
Free
</label>
<label class="l-button">
<input
type="radio"
name="plan"
value="pro"
/>
Pro
</label>
<label class="l-button">
<input
type="radio"
name="plan"
value="enterprise"
disabled
/>
Enterprise
</label>
</fieldset>Accessibility
Criteria
- Role
Native
<input type="radio">controls exposeradioand their checked state without any ARIAWCAG4.1.2RGAA11.1- Group name
The
<fieldset>groups the radios and its<legend>names them, natively. Without a visible caption,aria-labelon the fieldsetWCAG1.3.1RGAA11.5- Segment name
The
<label>wraps its input, so its text is the accessible name — nofor/idpair neededWCAG4.1.2RGAA11.1- Keyboard
Arrow keys move and select through the group; the group is a single
Tabstop. Browser behaviour, not scriptedWCAG2.1.1RGAA7.3- Focus ring
In the button appearance the input is transparent but focusable, so the ring is mirrored onto its label and raised above the joined borders
- Target size
In the button appearance a segment is a full
.l-button, so it clears the 24px minimum at every sizeWCAG2.5.8
Rules
- The group is a
<fieldset>, named by a<legend>first child — or byaria-labelwhen no visible caption fits - Every input in the group shares one
name - Wrap each input in a
<label>— that names it and makes it the click target, with nofor/idpair - For the button appearance, set
data-appearance="button"on the group and.l-buttonon every label; otherwise put.l-radioon every input - Never hide the input with
display: noneorvisibility: hidden: it would leave the accessibility tree and the tab order
Keyboard interactions
API reference
Importing
@import 'luxen-ui/css/radio-group';The segments are .l-button elements, so luxen-ui/css/button is required too.
Attributes & Properties
aria-labelAttribute- Names the group when no visible
<legend>fits — a view switcher in a toolbar, say. Prefer a<legend>: it is the technique WCAG H71 and RGAA 11.6 ask for. data-appearanceAttribute- button — Renders the items as joined buttons: put
.l-buttonon each label. Omit it for the radio primitive: put.l-radioon each input. data-orientationhorizontal | verticalAttribute- Stacks the items. Defaults to horizontal.
CSS classes
.l-radio-groupClass- Applied to the
<fieldset>grouping the radios. Its first child is the<legend>naming them; each item is a<label>wrapping one<input type="radio">.