Skip to main content

Theme config

Theme mode

Color palette

Grays

Border radii/radiuses/radiopedes/you know
Border radius
Field border radius
Button border radius
All
Components
Guides
API
Recent

    Components

    Radio

    See also: Form documentation.

    Full supportSupported since v105.Full supportSupported since v121.Full supportSupported since v15.4.

    Anatomy

    • label.ui-radio

      Container element.

    • <input>

      The radio input.

    • .ui-label

      The label.

    • .ui-end-text

      Supporting text displayed below the label.

    Give every <input type="radio"> in the group the samename attribute. Browsers use that shared name to enforce mutual exclusivity within the group.

    Legend
    <form class="ui-form">
    <fieldset class="ui-fieldset">
    <legend>Legend</legend>
    <div class="ui-field-group" role="group">
    <label class="ui-radio">
    <input name="radio-group" type="radio" value="1" checked />
    <span class="ui-label">Radio 1</span>
    </label>
    <label class="ui-radio">
    <input name="radio-group" type="radio" value="2" />
    <span class="ui-label">Radio 2</span>
    </label>
    <label class="ui-radio">
    <input name="radio-group" type="radio" value="3" />
    <span class="ui-label">Radio 3</span>
    </label>
    </div>
    </fieldset>
    </form>

    Direction

    Legend
    <form class="ui-form">
    <fieldset class="ui-fieldset">
    <legend>Legend</legend>
    <div class="ui-field-group ui-row" role="group">
    <label class="ui-radio">
    <input name="radio-group-direction" type="radio" value="1" checked />
    <span class="ui-label">Radio 1</span>
    </label>
    <label class="ui-radio">
    <input name="radio-group-direction" type="radio" value="2" />
    <span class="ui-label">Radio 2</span>
    </label>
    <label class="ui-radio">
    <input name="radio-group-direction" type="radio" value="3" />
    <span class="ui-label">Radio 3</span>
    </label>
    </div>
    </fieldset>
    </form>

    Field description

    Can be placed above and below the fields.

    Legend

    Field description above fields

    Legend

    Field description below fields

    <form class="ui-form">
    <fieldset class="ui-fieldset">
    <legend>Legend</legend>
    <p class="ui-field-description">Field description above fields</p>
    <div class="ui-field-group ui-row" role="group">
    <label class="ui-radio">
    <input
    name="radio-group-field-description-1"
    type="radio"
    value="1"
    checked
    />
    <span class="ui-label">Radio 1</span>
    </label>
    <label class="ui-radio">
    <input name="radio-group-field-description-1" type="radio" value="2" />
    <span class="ui-label">Radio 2</span>
    </label>
    <label class="ui-radio">
    <input name="radio-group-field-description-1" type="radio" value="3" />
    <span class="ui-label">Radio 3</span>
    </label>
    </div>
    </fieldset>
    <fieldset class="ui-fieldset">
    <legend>Legend</legend>
    <div class="ui-field-group ui-row" role="group">
    <label class="ui-radio">
    <input
    name="radio-group-field-description-2"
    type="radio"
    value="1"
    checked
    />
    <span class="ui-label">Radio 1</span>
    </label>
    <label class="ui-radio">
    <input name="radio-group-field-description-2" type="radio" value="2" />
    <span class="ui-label">Radio 2</span>
    </label>
    <label class="ui-radio">
    <input name="radio-group-field-description-2" type="radio" value="3" />
    <span class="ui-label">Radio 3</span>
    </label>
    </div>
    <p class="ui-field-description">Field description below fields</p>
    </fieldset>
    </form>

    Disabled

    Attach the disabled attribute to the <fieldset> element.

    Legend
    <form class="ui-form">
    <fieldset class="ui-fieldset" disabled>
    <legend>Legend</legend>
    <div class="ui-field-group ui-row" role="group">
    <label class="ui-radio">
    <input name="radio-group-disabled" type="radio" value="1" checked />
    <span class="ui-label">Radio 1</span>
    </label>
    <label class="ui-radio">
    <input name="radio-group-disabled" type="radio" value="2" />
    <span class="ui-label">Radio 2</span>
    </label>
    <label class="ui-radio">
    <input name="radio-group-disabled" type="radio" value="3" />
    <span class="ui-label">Radio 3</span>
    </label>
    </div>
    </fieldset>
    </form>

    Required

    Attach the required attribute to at least one of your <input> elements.

    These are required!
    <form class="ui-form">
    <fieldset class="ui-fieldset">
    <legend>These are required!</legend>
    <div class="ui-field-group ui-row" role="group">
    <label class="ui-radio">
    <input name="radio-group-required" type="radio" value="1" required />
    <span class="ui-label">Radio 1</span>
    </label>
    <label class="ui-radio">
    <input name="radio-group-required" type="radio" value="2" required />
    <span class="ui-label">Radio 2</span>
    </label>
    <label class="ui-radio">
    <input name="radio-group-required" type="radio" value="3" required />
    <span class="ui-label">Radio 3</span>
    </label>
    </div>
    </fieldset>
    </form>

    Validation

    Attach the data-invalid attribute to your <fieldset class="ui-fieldset"> element

    Legend
    Something went wrong!
    <form class="ui-form">
    <fieldset class="ui-fieldset" data-invalid>
    <legend>Legend</legend>
    <div class="ui-field-group ui-row" role="group">
    <label class="ui-radio">
    <input name="radio-group-validation" type="radio" value="1" checked />
    <span class="ui-label">Radio 1</span>
    </label>
    <label class="ui-radio">
    <input name="radio-group-validation" type="radio" value="2" />
    <span class="ui-label">Radio 2</span>
    </label>
    <label class="ui-radio">
    <input name="radio-group-validation" type="radio" value="3" />
    <span class="ui-label">Radio 3</span>
    </label>
    </div>
    <span class="ui-end-text">Something went wrong!</span>
    </fieldset>
    </form>

    API

    Radio API

    TypeModifiersDefaultDescription
    Layout.ui-stack-Stacks the label under the input.
    Sizes.ui-large, .ui-small-The size of the element.
    Validation[data-invalid]-Shows error styles.

    Parts

    PartDescription
    label.ui-radioContainer element.
    <input>The radio input.
    .ui-labelThe label.
    .ui-end-textSupporting text displayed below the label.

    Use .ui-sr-only instead of .ui-label to hide the label visually.

    Field group API

    TypeModifiersDefaultDescription
    Orientationdefault, .ui-row-The orientation of the element.

    Parts

    PartDescription
    .ui-field-groupContainer element.

    The root needs role="group". Wrap it in a .ui-fieldset with a <legend> to label it.

    Browser support

    Full supportSupported since v105.Full supportSupported since v121.Full supportSupported since v15.4.

    See also the full browser support guide.

    Installation

    See also

    @layer components.root {
    label.ui-radio {
    --_input-size: 1.125rem;
    --_indicator-size: 50%;
    align-items: center;
    color: var(--text-primary);
    cursor: pointer;
    display: inline-grid;
    gap: 0 var(--size-2);
    grid-auto-columns: auto;
    grid-auto-flow: column;
    inline-size: fit-content;
    line-height: 1.5;
    transform: translateZ(0);
    user-select: none;
    /* Disabled */
    &:has([disabled]) {
    cursor: not-allowed;
    opacity: 0.64;
    user-select: none;
    input {
    cursor: not-allowed;
    }
    }
    /* Required dot */
    &:has(:invalid) {
    .ui-label:after {
    color: var(--red);
    content: "*";
    inset: 0 -0.25ex auto auto;
    position: absolute;
    }
    }
    /* Label */
    .ui-label {
    color: var(--text-primary);
    font-size: var(--font-size-05);
    grid-column: 2;
    grid-row: 1;
    padding-inline: 0 1ex;
    position: relative;
    }
    /* End text */
    :where(.ui-end-text) {
    color: var(--text-muted);
    font-size: var(--font-size-0);
    grid-column: 2;
    grid-row: 2;
    line-height: 1.5;
    z-index: 1;
    }
    /* Stacked layout */
    &.ui-stack {
    grid-auto-columns: unset;
    justify-items: center;
    .ui-label {
    grid-column: 1/-1;
    grid-row: 2;
    margin-block-start: var(--size-1);
    padding-inline: 1ex;
    /* Required dot */
    &::after {
    inset: 0 -0.25ex auto auto;
    }
    }
    .ui-end-text {
    grid-column: 1/-1;
    grid-row: 3;
    }
    }
    /* Input */
    input[type="radio"] {
    appearance: none;
    aspect-ratio: 1;
    background-color: var(--surface-default);
    block-size: var(--_input-size);
    border: 1px solid var(--field-border-color);
    border-radius: var(--radius-round);
    box-sizing: border-box;
    cursor: pointer;
    display: grid;
    inline-size: var(--_input-size);
    margin: 0;
    padding: 0;
    place-items: center;
    position: relative;
    &:checked {
    background-color: var(--primary);
    border-color: var(--primary);
    }
    /* Dot */
    &::after {
    background-color: var(--primary-contrast);
    block-size: var(--_indicator-size);
    border-radius: var(--radius-round);
    content: "";
    inline-size: var(--_indicator-size);
    margin: auto;
    opacity: 0;
    }
    &:checked::after {
    opacity: 1;
    }
    &::before {
    --highlight-size: 175%;
    }
    }
    /* Sizes */
    &.ui-small {
    input[type="radio"] {
    --_input-size: var(--size-3);
    }
    }
    &.ui-large {
    input[type="radio"] {
    --_input-size: var(--size-4);
    }
    }
    /* Validation */
    &[data-invalid],
    &:has(:user-invalid) {
    --primary: var(--critical);
    :where(.ui-end-text) {
    color: var(--critical);
    }
    }
    /* Touch devices */
    @media (pointer: coarse) {
    input[type="radio"] {
    block-size: var(--size-4);
    inline-size: var(--size-4);
    }
    }
    @media (forced-colors: active) {
    input[type="radio"] {
    border: 1px solid CanvasText;
    &:checked {
    background-color: SelectedItem;
    border-color: SelectedItem;
    &::after {
    background-color: SelectedItemText;
    }
    }
    }
    }
    }
    }
    @layer components.extended {
    /* Form */
    :where(.ui-form) {
    display: grid;
    gap: var(--size-8);
    hr {
    margin-block: 0;
    }
    }
    /* Fieldset */
    :where(.ui-fieldset) {
    all: unset;
    border: 0;
    border-radius: 0;
    display: grid;
    gap: var(--size-1);
    margin: 0;
    min-inline-size: 0;
    padding: 0;
    /* Legend */
    :where(legend, .ui-legend) {
    all: unset;
    color: var(--text-primary);
    font-weight: 600;
    margin-block-end: var(--size-3);
    padding: 0;
    &:has(+ :where(.ui-field-description)) {
    margin-block-end: 0;
    }
    }
    /* Field description / supporting text */
    :where(.ui-field-description) {
    color: var(--text-muted);
    font-size: var(--font-size-05);
    line-height: var(--font-lineheight-3);
    &:has(+ *) {
    margin-block-end: var(--size-3);
    }
    }
    /* End text */
    :where(.ui-end-text) {
    color: var(--text-muted);
    font-size: var(--font-size-0);
    line-height: var(--font-lineheight-3);
    }
    &:has(.ui-text-field.ui-row) {
    row-gap: var(--size-7);
    }
    /* Disabled */
    &[disabled] {
    opacity: 0.64;
    user-select: none;
    input,
    label,
    .ui-label {
    cursor: not-allowed;
    }
    }
    /* Error / validation */
    &[data-invalid] {
    :where(.ui-end-text) {
    color: var(--critical);
    }
    :where(.ui-checkbox, .ui-radio, .ui-switch) {
    --primary: var(--critical);
    :where(.ui-end-text) {
    color: var(--critical);
    }
    }
    :where(.ui-switch) {
    input {
    border-radius: var(--radius-round);
    outline: 2px solid var(--critical);
    }
    }
    }
    /* Required */
    &:has(:invalid) {
    :where(legend, .ui-legend) {
    padding-inline-end: 1ex;
    position: relative;
    &::after {
    color: var(--red);
    content: "*";
    inset: 0 -0.25ex auto auto;
    position: absolute;
    }
    }
    }
    }
    /* Field group */
    :where(.ui-field-group) {
    display: flex;
    flex-direction: column;
    gap: var(--size-4);
    /* If it only has checkboxes, radios, or switches */
    &:has(> :where(.ui-checkbox, .ui-radio, .ui-switch)):not(
    :has(> :not(.ui-checkbox, .ui-radio, .ui-switch))
    ) {
    gap: var(--size-2);
    }
    /* If it only has buttons */
    &:has(.ui-button):not(:has(*:not(.ui-button))) {
    align-items: center;
    flex-direction: row;
    gap: var(--size-2);
    /* If it's not preceded by an hr */
    &:not(hr + &) {
    margin-block-start: var(--size-4);
    }
    }
    & + & {
    margin-block-start: var(--size-5);
    }
    /* Directions */
    &.ui-row {
    flex-direction: row;
    flex-wrap: wrap;
    &:has(> :where(.ui-checkbox, .ui-radio, .ui-switch)) {
    gap: var(--size-4);
    }
    }
    }
    }