# Button groups

> Related buttons that bump and reshape against each other, in two variants and five sizes.

## Anatomy

A button group places related buttons in one visual cluster. Use it for commands such as playback controls or for toggle buttons such as text formatting. Each item remains a native button and a Tab stop.

The root is a `<div class="button-group">`. Common [buttons](/buttons.html.md) and [icon buttons](/icon-buttons.html.md) can be direct children. `Expressive.AutoInit()` keeps standard-group width stable while the pressed item grows; `data-selection` additionally enables managed toggle state.

Bold Italic Underline

```
<div class="button-group" data-selection="multiple"
     role="group" aria-label="Text formatting">
  <button type="button" class="button tonal" aria-pressed="false">
    <span class="material-symbols" aria-hidden="true">format_bold</span>
    Bold
  </button>
  <button type="button" class="button tonal" aria-pressed="false">
    <span class="material-symbols" aria-hidden="true">format_italic</span>
    Italic
  </button>
  <button type="button" class="button tonal" aria-pressed="false">
    <span class="material-symbols" aria-hidden="true">format_underlined</span>
    Underline
  </button>
</div>
```

Use a plain group for commands. Add selection behavior only when pressing a button toggles an on/off state. Use a [segmented button](/segmented-buttons.html.md) when two to five choices form a compact form field whose value belongs in radios or checkboxes.

## Standard

Standard is the default. Items keep separate shapes, and the gap closes as the size grows: 18dp at `xsmall`, 12dp at `small`, and 8dp from `medium` through `xlarge`. Pressing an item widens it by 15% of its measured width and morphs its corners toward the square shape for that size. The immediate neighbors provide the width, so the group's outer width stays fixed.

```
<div class="button-group" role="group" aria-label="Playback">
  <button type="button" class="icon-button filled" aria-label="Previous track">
    <span class="material-symbols" aria-hidden="true">skip_previous</span>
  </button>
  <button type="button" class="icon-button filled" aria-label="Play">
    <span class="material-symbols" aria-hidden="true">play_arrow</span>
  </button>
  <button type="button" class="icon-button filled" aria-label="Next track">
    <span class="material-symbols" aria-hidden="true">skip_next</span>
  </button>
</div>
```

## Connected

Add `connected` to a selection group; do not use the connected treatment for one-shot actions. The group fills its container with equal items separated by 2dp. The outer ends remain round while the joins are squared off. The live M3 measurement keeps the `xsmall` join at 4dp; pressing `small` and `medium` changes their inner corners from 8dp to 4dp. The larger pairs are 16dp to 12dp at `large` and 20dp to 16dp at `xlarge`.

```
<div class="button-group connected"
     data-selection="single"
     data-selection-required
     role="group"
     aria-label="Text alignment">
  <button type="button" class="icon-button tonal"
          aria-label="Align left" aria-pressed="true">
    <span class="material-symbols" aria-hidden="true">format_align_left</span>
  </button>
  <button type="button" class="icon-button tonal"
          aria-label="Align center" aria-pressed="false">
    <span class="material-symbols" aria-hidden="true">format_align_center</span>
  </button>
  <button type="button" class="icon-button tonal"
          aria-label="Align right" aria-pressed="false">
    <span class="material-symbols" aria-hidden="true">format_align_right</span>
  </button>
</div>
```

## Selection

A selection group contains toggle buttons. Add `data-selection="single"` when at most one item may be on, or `data-selection="multiple"` for independent toggles. Add `data-selection-required` when at least one must remain on. Give every item its initial `aria-pressed` value; `ButtonGroup` maintains it after `AutoInit()`.

Bold Italic Underline

```
<div class="button-group connected"
     data-selection="multiple"
     role="group"
     aria-label="Text formatting">
  <button type="button" class="button filled" aria-pressed="true">Bold</button>
  <button type="button" class="button filled" aria-pressed="false">Italic</button>
  <button type="button" class="button filled" aria-pressed="false">Underline</button>
</div>

<script>
  Expressive.AutoInit();
</script>
```

Selection changes color, shape, and icon fill, so color is not the only cue. Native buttons provide Enter and Space activation; all items remain in the Tab order. Keep visible labels when space allows. Give an unfamiliar icon-only item a tooltip as well as an `aria-label`.

## Sizes

Put `xsmall`, `small` (the default), `medium`, `large`, or `xlarge` on the group. Common and icon buttons inherit the matching 32dp, 40dp, 56dp, 96dp, or 136dp geometry. An explicit size on a child still wins. The 32dp and 40dp visual sizes keep a minimum 48dp interaction target.

One Two Three

One Two Three

One Two

```
<div class="button-group medium">
  <button type="button" class="button tonal">One</button>
  <button type="button" class="button tonal">Two</button>
  <button type="button" class="button tonal">Three</button>
</div>
```

## Semantics

A button group is not a composite widget. Do not use `role="toolbar"`, `radiogroup`, or a roving `tabindex`: items are reached with Tab. When the cluster needs a name, use `role="group"` with `aria-label` or `aria-labelledby`. This role adds no arrow-key contract.

Action groups accept a direct `<button>` or `<a class="button" href>`. Selection groups accept only direct `<button type="button">` items, each with an initial `aria-pressed`. Links cannot expose toggle state. The native button supplies keyboard activation, and `ButtonGroup` changes the state on the resulting click.

Give every icon-only item an accessible name because its decorative icon is `aria-hidden`. Avoid a standard icon button when its meaning is not familiar; use a filled, tonal, or outlined container and a tooltip. Reduced-motion preferences remove the width and shape transitions.

## Tokens

Set these properties on the group. The defaults describe a small standard group; size and variant classes replace the values that differ.

| Token | Default |
| --- | --- |
| `--md-comp-button-group-between-space` | `12px` |
| `--md-comp-button-group-pressed-item-width-multiplier` | `.15` |
| `--md-comp-button-group-item-shape-round` | `9999px` |
| `--md-comp-button-group-item-shape-square` | `12px` |
| `--md-comp-button-group-pressed-item-shape` | `8px` |
| `--md-comp-button-group-container-shape` | `9999px` (connected) |
| `--md-comp-button-group-inner-corner-corner-size` | `8px` (connected) |
| `--md-comp-button-group-pressed-inner-corner-corner-size` | `4px` (connected) |
| `--md-comp-button-group-selected-inner-corner-corner-size` | `50%` (connected) |

Child geometry and colors still come from the button or icon-button token family. Toggle groups map the selected and unselected Material button colors onto `aria-pressed` and retain hover, focus, pressed, disabled, and focus-ring feedback.
