Skip to main content

Looking for the web component? See Radio button (web component)

Variations

A radio control provides the minimum functional markup necessary to display a Bolt-styled radio.

Refer to the radio control code reference docs for more information.

<bolt-radio-control>
  <input
    id="INPUT_ID"
    type="radio"
  />
  <label for="INPUT_ID">
    <bolt-radio-facade></bolt-radio-facade>
  </label>
</bolt-radio-control>
<bolt-radio-control>
  <input
    disabled
    id="INPUT_ID"
    type="radio"
  />
  <label for="INPUT_ID">
    <bolt-radio-facade></bolt-radio-facade>
  </label>
</bolt-radio-control>
<bolt-radio-control class="bolt-invalid">
  <input
    id="INPUT_ID"
    type="radio"
  />
  <label for="INPUT_ID">
    <bolt-radio-facade></bolt-radio-facade>
  </label>
</bolt-radio-control>

A radio field provides the minimum markup required to display a single radio, label, and optional description.

Refer to the radio field code reference docs for more information.

<bolt-radio-control>
  <input
    id="INPUT_ID"
    type="radio"
  />
  <label for="INPUT_ID">
    <bolt-radio-facade></bolt-radio-facade>
    <div class="bolt-field__label">
      Field label
    </div>
  </label>
</bolt-radio-control>
<bolt-radio-control>
  <input
    id="INPUT_ID"
    type="radio"
  />
  <label for="INPUT_ID">
    <bolt-radio-facade></bolt-radio-facade>
    <div class="bolt-field__label">
      Field label
    </div>
    <div class="bolt-field__description">
      This is a field description. It may include <strong>bold</strong>, <em>italic</em>, and other basic formatting, but avoid interactive elements like links and buttons.
    </div>
  </label>
</bolt-radio-control>
<bolt-radio-control>
  <input
    disabled
    id="INPUT_ID"
    type="radio"
  />
  <label for="INPUT_ID">
    <bolt-radio-facade></bolt-radio-facade>
    <div class="bolt-field__label">
      Field label
    </div>
  </label>
</bolt-radio-control>
<bolt-radio-control class="bolt-invalid">
  <input
    id="INPUT_ID"
    type="radio"
  />
  <label for="INPUT_ID">
    <bolt-radio-facade></bolt-radio-facade>
    <div class="bolt-field__label">
      Field label
    </div>
  </label>
</bolt-radio-control>

A radio group provides the markup necessary to display a set of related radio fields as a cohesive unit.

Refer to the checkbox group code reference docs for more information.

<fieldset class="bolt-fieldset bolt--radios">
  <legend>
    <span class="bolt-fieldset__name">
      Group name
    </span>
    <span class="bolt-annotation bolt-optional">
      (optional)
    </span>
  </legend>
  <div class="bolt-fieldset__body">
    <bolt-radio-control>
      <input
        id="INPUT_ID_1"
        name="INPUT_GROUP"
        type="radio"
      />
      <label for="INPUT_ID_1">
        <bolt-radio-facade></bolt-radio-facade>
        <div class="bolt-field__label">
          Option 1
        </div>
      </label>
    </bolt-radio-control>
    <bolt-radio-control>
      <input
        id="INPUT_ID_2"
        name="INPUT_GROUP"
        type="radio"
      />
      <label for="INPUT_ID_2">
        <bolt-radio-facade></bolt-radio-facade>
        <div class="bolt-field__label">
          Option 2
        </div>
      </label>
    </bolt-radio-control>
    <bolt-radio-control>
      <input
        id="INPUT_ID_3"
        name="INPUT_GROUP"
        type="radio"
      />
      <label for="INPUT_ID_3">
        <bolt-radio-facade></bolt-radio-facade>
        <div class="bolt-field__label">
          Option 3
        </div>
      </label>
    </bolt-radio-control>
  </div>
</fieldset>
<fieldset class="bolt-fieldset bolt--radios">
  <legend>
    <span class="bolt-fieldset__name">
      Group name
    </span>
    <span class="bolt-annotation bolt-optional">
      (optional)
    </span>
    <div class="bolt-help">
      This is some instructional text.
    </div>
  </legend>
  <div class="bolt-fieldset__body">
    <bolt-radio-control>
      <input
        id="demo-instructional-text-1"
        name="demo-basic-group-rads"
        type="radio"
      />
      <label for="demo-instructional-text-1">
        <bolt-radio-facade></bolt-radio-facade>
        <div class="bolt-field__label">
          Option 1
        </div>
      </label>
    </bolt-radio-control>
    <bolt-radio-control>
      <input
        id="demo-instructional-text-2"
        name="demo-basic-group-rads"
        type="radio"
      />
      <label for="demo-instructional-text-2">
        <bolt-radio-facade></bolt-radio-facade>
        <div class="bolt-field__label">
          Option 2
        </div>
      </label>
    </bolt-radio-control>
    <bolt-radio-control>
      <input
        id="demo-instructional-text-3"
        name="demo-basic-group-rads"
        type="radio"
      />
      <label for="demo-instructional-text-3">
        <bolt-radio-facade></bolt-radio-facade>
        <div class="bolt-field__label">
          Option 3
        </div>
      </label>
    </bolt-radio-control>
  </div>
</fieldset>
<fieldset class="bolt-fieldset bolt--radios">
  <legend>
    <span class="bolt-fieldset__name">
      Group name
    </span>
    <span class="bolt-annotation bolt-optional">
      (optional)
    </span>
  </legend>
  <div class="bolt-fieldset__body">
    <bolt-radio-control>
      <input
        disabled
        id="INPUT_ID_1"
        name="INPUT_GROUP"
        type="radio"
      />
      <label for="INPUT_ID_1">
        <bolt-radio-facade></bolt-radio-facade>
        <div class="bolt-field__label">
          Option 1 (disabled)
        </div>
      </label>
    </bolt-radio-control>
    <bolt-radio-control>
      <input
        id="INPUT_ID_2"
        name="INPUT_GROUP"
        type="radio"
      />
      <label for="INPUT_ID_2">
        <bolt-radio-facade></bolt-radio-facade>
        <div class="bolt-field__label">
          Option 2
        </div>
      </label>
    </bolt-radio-control>
    <bolt-radio-control>
      <input
        id="INPUT_ID_3"
        name="INPUT_GROUP"
        type="radio"
      />
      <label for="INPUT_ID_3">
        <bolt-radio-facade></bolt-radio-facade>
        <div class="bolt-field__label">
          Option 3
        </div>
      </label>
    </bolt-radio-control>
  </div>
</fieldset>
<fieldset
  class="bolt-fieldset bolt--radios"
  disabled
>
  <legend>
    <span class="bolt-fieldset__name">
      Group name
    </span>
    <span class="bolt-annotation bolt-optional">
      (optional)
    </span>
  </legend>
  <div class="bolt-fieldset__body">
    <bolt-radio-control>
      <input
        id="INPUT_ID_1"
        name="INPUT_GROUP"
        type="radio"
      />
      <label for="INPUT_ID_1">
        <bolt-radio-facade></bolt-radio-facade>
        <div class="bolt-field__label">
          Option 1
        </div>
      </label>
    </bolt-radio-control>
    <bolt-radio-control>
      <input
        id="INPUT_ID_2"
        name="INPUT_GROUP"
        type="radio"
      />
      <label for="INPUT_ID_2">
        <bolt-radio-facade></bolt-radio-facade>
        <div class="bolt-field__label">
          Option 2
        </div>
      </label>
    </bolt-radio-control>
    <bolt-radio-control>
      <input
        id="INPUT_ID_3"
        name="INPUT_GROUP"
        type="radio"
      />
      <label for="INPUT_ID_3">
        <bolt-radio-facade></bolt-radio-facade>
        <div class="bolt-field__label">
          Option 3
        </div>
      </label>
    </bolt-radio-control>
  </div>
</fieldset>
<fieldset class="bolt-fieldset bolt--radios">
  <legend>
    <span class="bolt-fieldset__name">
      Group name
    </span>
    <span class="bolt-annotation bolt-optional">
      (optional)
    </span>
    <bolt-contextual-help
      heading="Heading text"
      type="push"
    >
      <p>Contextual help body content.</p>
    </bolt-contextual-help>
  </legend>
  <div class="bolt-fieldset__body">
    <bolt-radio-control>
      <input
        id="INPUT_ID_1"
        name="INPUT_GROUP"
        type="radio"
      />
      <label for="INPUT_ID_1">
        <bolt-radio-facade></bolt-radio-facade>
        <div class="bolt-field__label">
          Option 1
        </div>
      </label>
    </bolt-radio-control>
    <bolt-radio-control>
      <input
        id="INPUT_ID_2"
        name="INPUT_GROUP"
        type="radio"
      />
      <label for="INPUT_ID_2">
        <bolt-radio-facade></bolt-radio-facade>
        <div class="bolt-field__label">
          Option 2
        </div>
      </label>
    </bolt-radio-control>
    <bolt-radio-control>
      <input
        id="INPUT_ID_3"
        name="INPUT_GROUP"
        type="radio"
      />
      <label for="INPUT_ID_3">
        <bolt-radio-facade></bolt-radio-facade>
        <div class="bolt-field__label">
          Option 3
        </div>
      </label>
    </bolt-radio-control>
  </div>
</fieldset>
<fieldset
  class="
    bolt-fieldset bolt--radios
    bolt-invalid
  "
>
  <legend>
    <span class="bolt-fieldset__name">
      Group name
    </span>
    <div class="bolt-fieldset__errors">
      <bolt-field-error>
        This group has invalid data.
      </bolt-field-error>
    </div>
  </legend>
  <div class="bolt-fieldset__body">
    <bolt-radio-control>
      <input
        id="INPUT_ID_1"
        name="INPUT_GROUP"
        type="radio"
      />
      <label for="INPUT_ID_1">
        <bolt-radio-facade></bolt-radio-facade>
        <div class="bolt-field__label">
          Option 1
        </div>
      </label>
    </bolt-radio-control>
    <bolt-radio-control>
      <input
        id="INPUT_ID_2"
        name="INPUT_GROUP"
        type="radio"
      />
      <label for="INPUT_ID_2">
        <bolt-radio-facade></bolt-radio-facade>
        <div class="bolt-field__label">
          Option 2
        </div>
      </label>
    </bolt-radio-control>
    <bolt-radio-control>
      <input
        id="INPUT_ID_3"
        name="INPUT_GROUP"
        type="radio"
      />
      <label for="INPUT_ID_3">
        <bolt-radio-facade></bolt-radio-facade>
        <div class="bolt-field__label">
          Option 3
        </div>
      </label>
    </bolt-radio-control>
  </div>
</fieldset>
Code reference

The HTML implementation provides maximum control over the markup. However, it is up to the consumer to implement all advanced interaction logic.

If you want Bolt to handle the interaction logic, check out the web component implementation.

This implementation should be compatible with @angular/forms without the need for additional dependencies.

The <bolt-radio-facade> custom element is designed exclusively for use within the radio control pattern in order to encapsulate the complex SVG markup and CSS required to present a styled radio button control.

All APIs built for <bolt-radio-facade> should be considered "private" and are subject to change at any time, without warning. Any use of the custom element outside of documented patterns shall be done so at consumer's own risk.

As documented below, the radio control pattern is not fully accessible without additional configuration.

  • Please refer to the radio control accessibility docs for more information about accessibility concerns.
<!-- Root (REQUIRED) -->
<bolt-radio-control
  class="
    [bolt-invalid]
  "
>
  <!-- Input (REQUIRED) -->
  <input
    [checked]
    [disabled]
    id="INPUT_ID""
    type="radio"
    ...
  />

  <!-- Label (REQUIRED) -->
  <label for="INPUT_ID">
    <!-- Facade (REQUIRED) -->
    <bolt-radio-facade></bolt-radio-facade>
  </label>
</bolt-radio-control>

Unless specified, elements should be defined in the order presented above.

A radio control is comprised of the following items:

  • Root (REQUIRED)
    • MAY apply .bolt-invalid class to apply "invalid" appearance to a single control.
  • Input (REQUIRED)
    • MUST have [type="radio"] attribute configuration.
    • MUST have an [id] attribute.
    • Refer to MDN for best practices on using the HTML <input type="radio"> element.
  • Label (REQUIRED)
    • MUST have a [for] attribute with value matching the [id] of the Input.
  • Facade (REQUIRED)
    • MUST be present to display a radio button on screen.

A radio field is an extension of the radio control pattern, above.

  • Please refer to the radio field accessibility docs for information about accessibility concerns.
<!-- Root (REQUIRED) -->
<bolt-radio-control
  class="
    [bolt-invalid]
  "
>
  <!-- Input (REQUIRED) -->
  <input
    id="INPUT_ID""
    type="radio"
    ...
  />

  <!-- Label (REQUIRED) -->
  <label for="INPUT_ID">
    <!-- Facade (REQUIRED) -->
    <bolt-radio-facade></bolt-radio-facade>

    <!-- Field label (REQUIRED) -->
    <div class="bolt-field__label">...</div>

    <!-- Field description (optional) -->
    <div class="bolt-field__description">...</div>
  </label>
</bolt-radio-control>

Unless specified, elements should be defined in the order presented above.

A radio field is comprised of the following items:

  • All radio control items.
  • Field label (REQUIRED)
    • MUST be present to provide an accessible label.
    • MUST have .bolt-field__label class.
  • Field description (optional)
    • MUST have .bolt-field__description class.
    • Supports formatted text, but avoid including interactive elements.
  • Please refer to the radio group accessibility docs for information about accessibility concerns.
<!-- Root (REQUIRED) -->
<fieldset
  class="
    bolt-fieldset bolt--radios
    [bolt-invalid]
  "
  [disabled]
>
  <!-- Legend (REQUIRED) -->
  <legend>
    <!-- Fieldset name (REQUIRED) -->
    <span class="bolt-fieldset__name">
      ...
    </span>

    <!-- Annotation (optional) -->
    <span class="bolt-annotation bolt-optional">
      (optional)
    </span>

    <!-- Contextual help (optional) -->
    <bolt-contextual-help
      type="push"
      [disabled]
      ...
    >
      ...
    </bolt-contextual-help>

    <!-- Instructional text (optional) -->
    <div class="bolt-help">
      This is some instructional text.
    </div>

    <!-- Fieldset errors (optional) -->
    <div
      [aria-live="..."]
      class="bolt-fieldset__errors"
    >
      <!-- Error (optional) -->
      <bolt-field-error>...</bolt-field-error>
    </div>
  </legend>

  <!-- Fieldset body (REQUIRED) -->
  <div class="bolt-fieldset__body">
    <!-- Field 1 -->
    <bolt-radio-control>...</bolt-radio-control>
    ...
    <!-- Field N -->
    <bolt-radio-control>...</bolt-radio-control>
  </div>
</fieldset>

Unless specified, elements should be defined in the order presented above.

A radio group is comprised of the following items:

  • Root (REQUIRED)
    • MUST be a <fieldset> element to apply correct semantic markup.
    • MUST match .bolt-fieldset.bolt--radios CSS selector.
    • MAY apply .bolt-invalid class to apply "invalid" appearance to the entire group.
    • MAY add [disabled] attribute to semantically disable all fields within the group.
    • Refer to MDN for best practices on using the HTML <fieldset> element.
  • Legend (REQUIRED)
    • MUST be present for semantic configuration.
  • Fieldset name (REQUIRED)
    • MUST have .bolt-fieldset__name class.
    • MUST be an inline element.
  • Annotation (optional)
    • When present, communicates that selecting options within the group is not critical for workflow progression.
    • MUST match .bolt-annotation.bolt-optional CSS selector.
    • MUST be an inline element.
    • Should have "(optional)" as inner text.
  • Contextual help (optional)
    • MUST have [type="push"]
    • See contextual help component for more information.
  • Fieldset errors (optional)
    • Supports wrapping one or more error messages to be associated with the group.
    • MUST have .bolt-fieldset__errors class.
    • MAY define [aria-live] attribute, depending on validation strategy.
  • Error (optional)
    • Defines a single error message.
    • A <bolt-field-error> element is recommended.
    • Error and disabled state should not be used at the same time.
  • Fieldset body (REQUIRED)
    • Base container element used to apply various layouts.
      • The grid component might be handy here.
    • MUST have .bolt-fieldset__body class
    • MUST have at least two radio field children.
Design guidelines
  • Radio buttons should be placed in a logical order (e.g., alphabetical, most likely to least likely, simplest to most complex, least to most risk).
  • Include an "Other," "Does not apply," or similar option for users who may not want to answer or if not all possible options are listed. Consider alternatives if a selection is not required, like using a Radio group with an option equating to "none of these options."
  • Text labels should wrap, keeping the Radio selector glyph itself aligned with the first line of a label.
  • Except for decisions that require a boolean choice (e.g., Yes/No, True/False, etc.), do not use side-by-side horizontal positioning of radio buttons to prevent an unintended visual grouping of unrelated options.
  • Lay out lists of Radio buttons vertically, with one option per line for ease of comprehension.
  • A Radio button should not be used on its own; it should be rendered in a group of at least two or more options.
  • Combine Radio buttons with a fieldset and legend for the best context and accessibility.
  • Both the Radio button AND its label should be able to be used to make a selection.
  • To verify a deliberate selection, no Radio button should be selected by default unless a selection must be made by default for a page to render (example, a defaulted selection in a filter).
  • Once a Radio button is selected, it cannot be deselected. Choosing another related Radio button should change the state back to unselected.
  • Avoid individual Radio button validation messages or styles; validation should be displayed at the group level.
  • Input validation and error messaging for Radio buttons should only occur after form submission.
  • Radio buttons may be used in a list, form, or table for single selections.
  • When a user must make a single, mutually exclusive selection from 2-8 options.
  • When a selection doesn't have an immediate effect and/or requires form submission.
  • When viewing all available options is critical.
  • Don't use Radio buttons as an alternative to a Button or Link for actions or navigation.
  • Avoid using Radio buttons when multiple choices are allowed; use Checkboxes instead.
  • Avoid Radio buttons for situations where users can deselect items; use Checkboxes instead.
  • Avoid Radio buttons when a selection results in immediate changes, especially on mobile; use Switch instead.
  • Avoid Radio buttons when it's visually difficult to observe the state change; use Switch instead.
  • If there are more than 8 options presented, use Select in order to avoid clutter.

Do

  • Present Radio button options in a logical order.
  • Allow text wrapping beneath Radio buttons. Keep the Radio selector glyph aligned with the first line of a wrapping label.
  • Include a label for each Radio button.
  • Combine Radio buttons with a fieldset and legend for the best context and accessibility.
  • Keep legends and labels concise and descriptive.
  • Use Radio buttons for single selections from 2 to 8 options.

Don't

  • Don't default a selection in a Radio group.
  • Don't use Radio buttons when multiple items can be selected.
  • Don't vertically center label text inside Radio buttons.
  • Don't nest Radio buttons.
  • Don't use Radio groups for selecting multiple items.
  • Don't use side-by-side horizontal positioning in order to prevent unintended visual grouping.
  • Radio button labels use sentence case.
  • Error messages use sentence case and include a period.
  • Keep labels and legends concise and simple.
Accessibility

In addition to code requirements, the following guidelines should be taken into account to ensure maximum accessibility.

  • A lone radio control MUST define an accessible label via one of the following strategies:
    • input[aria-label]
    • input[aria-labelledby] + external element
    • visually-hidden text within the associated <label>
  • See also: radio control API
  • AVOID including interactive elements within the field description.
    • These types of elements will conflict with expected field interactions.
  • See also: radio field API
  • By default, screen readers will NOT automatically announce error messages that are dynamically added to the group <legend>.
    • Configuring the errors wrapper as a live region via the [aria-live] attribute is a potential strategy for communicating mid-form validation errors with AT users (before form submission).
      • WARNING: If you implement this strategy in your project, make sure to perform proper accessibility testing to ensure that screen readers announce errors at relevant times during user interaction.
  • See also: radio group API

Display settings

Note: not all settings persist across pages

Default Compact (-1) Sparse (+1) XL (default) 2XL 3XL Default Min Max Light (default) System Dark Branded (default) Unbranded