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

Button group

Groups related buttons by wrapping them with class="button-group" and role="group".

Full support Supported since v111. Full support Supported since v113. Full support Supported since v16.2.
  • Button groups should consist of 2-5 buttons.
  • Don't allow them to wrap onto a new line.
  • If an icon is used without label text make sure the button communicates clearly what it does.
Button group or Toggle group?

If your buttons depend on state (controlled) - use Toggle group.

If you just need to group a bunch of "dumb" (uncontrolled) buttons - use Button group.

Variants

Change the appearance of the entire group with the .outlined, .tonal, and .filled classes.

<div role="group" class="button-group">
<button class="button">Text</button>
<button class="button">Text</button>
<button class="button">Text</button>
</div>
<div role="group" class="button-group">
<button class="button outlined">Outlined</button>
<button class="button outlined">Outlined</button>
<button class="button outlined">Outlined</button>
</div>
<div role="group" class="button-group">
<button class="button tonal">Tonal</button>
<button class="button tonal">Tonal</button>
<button class="button tonal">Tonal</button>
</div>
<div role="group" class="button-group">
<button class="button filled">Filled</button>
<button class="button filled">Filled</button>
<button class="button filled">Filled</button>
</div>

Colors

Add a .primary or .critical class to recolor the entire group. The default is a neutral gray.

<div class="button-group primary filled" role="group">
<button class="button">Primary</button>
<button class="button">Primary</button>
<button class="button">Primary</button>
</div>
<div class="button-group critical filled" role="group">
<button class="button">Critical</button>
<button class="button">Critical</button>
<button class="button">Critical</button>
</div>

Icons

Yes of course, they're just buttons.

<div role="group" class="button-group outlined">
<button class="button" aria-label="Label">
<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 32 32">
<path fill="currentColor"
d="M29.907 5.14a1.25 1.25 0 0 1-.047 1.767l-19 18a1.25 1.25 0 0 1-1.775-.055l-6.75-7.25a1.25 1.25 0 0 1 1.83-1.704l5.89 6.327L28.14 5.093a1.25 1.25 0 0 1 1.767.047">
</path>
</svg>
</button>
<button class="button" aria-label="Label">
Maybe
</button>
<button class="button" aria-label="Label">
<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 32 32">
<path fill="currentColor"
d="M26.29 4.293a1 1 0 1 1 1.414 1.414L17.413 16l10.291 10.29a1 1 0 1 1-1.414 1.414L16 17.413L5.707 27.704a1 1 0 0 1-1.414-1.414L14.585 16L4.293 5.707a1 1 0 0 1 1.414-1.414L16 14.584z">
</path>
</svg>
</button>
</div>
<div role="group" class="button-group outlined">
<button class="button">
<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 32 32">
<path fill="currentColor"
d="M29.907 5.14a1.25 1.25 0 0 1-.047 1.767l-19 18a1.25 1.25 0 0 1-1.775-.055l-6.75-7.25a1.25 1.25 0 0 1 1.83-1.704l5.89 6.327L28.14 5.093a1.25 1.25 0 0 1 1.767.047">
</path>
</svg> OK
</button>
<button class="button">
<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 32 32">
<path fill="currentColor"
d="M11.499 10.803A4.505 4.505 0 0 1 16 6.5a4.5 4.5 0 0 1 4.5 4.5c0 1.276-.298 2.02-.676 2.565c-.368.53-.836.925-1.471 1.459l-.286.241c-.745.632-1.614 1.42-2.268 2.628c-.659 1.217-1.049 2.76-1.049 4.857a1.25 1.25 0 0 0 2.5 0c0-1.778.328-2.892.748-3.667c.424-.783.993-1.324 1.685-1.91l.259-.217c.616-.515 1.363-1.139 1.937-1.966C22.579 13.98 23 12.724 23 11a7 7 0 0 0-7-7a7.005 7.005 0 0 0-6.999 6.695a1.25 1.25 0 1 0 2.498.108M16 29a1.5 1.5 0 1 0 0-3a1.5 1.5 0 0 0 0 3">
</path>
</svg> Maybe
</button>
<button class="button">
<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 32 32">
<path fill="currentColor"
d="M26.29 4.293a1 1 0 1 1 1.414 1.414L17.413 16l10.291 10.29a1 1 0 1 1-1.414 1.414L16 17.413L5.707 27.704a1 1 0 0 1-1.414-1.414L14.585 16L4.293 5.707a1 1 0 0 1 1.414-1.414L16 14.584z">
</path>
</svg> No
</button>
</div>

Sizes

Adjust the size of all buttons in the group using the .small and .large classes.

<div role="group" class="button-group small outlined">
<button class="button">Small</button>
<button class="button">Small</button>
<button class="button">Small</button>
</div>
<div role="group" class="button-group outlined">
<button class="button">Default</button>
<button class="button">Default</button>
<button class="button">Default</button>
</div>
<div role="group" class="button-group large outlined">
<button class="button">Large</button>
<button class="button">Large</button>
<button class="button">Large</button>
</div>

Vertical orientation

Change the layout of the group with the .vertical class.

<div class="example-row">
<div class="button-group vertical" role="group">
<button aria-label="Up" class="button">
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none"
stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<line x1="12" y1="5" x2="12" y2="19"></line>
<line x1="5" y1="12" x2="19" y2="12"></line>
</svg>
</button>
<button aria-label="Decrease" class="button">
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none"
stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<line x1="5" y1="12" x2="19" y2="12"></line>
</svg>
</button>
</div>
<div class="button-group outlined vertical" role="group">
<button aria-label="Up" class="button">
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none"
stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<line x1="12" y1="5" x2="12" y2="19"></line>
<line x1="5" y1="12" x2="19" y2="12"></line>
</svg>
</button>
<button aria-label="Decrease" class="button">
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none"
stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<line x1="5" y1="12" x2="19" y2="12"></line>
</svg>
</button>
</div>
<div class="button-group tonal vertical" role="group">
<button aria-label="Up" class="button">
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none"
stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<line x1="12" y1="5" x2="12" y2="19"></line>
<line x1="5" y1="12" x2="19" y2="12"></line>
</svg>
</button>
<button aria-label="Decrease" class="button">
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none"
stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<line x1="5" y1="12" x2="19" y2="12"></line>
</svg>
</button>
</div>
<div class="button-group filled vertical" role="group">
<button aria-label="Up" class="button">
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none"
stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<line x1="12" y1="5" x2="12" y2="19"></line>
<line x1="5" y1="12" x2="19" y2="12"></line>
</svg>
</button>
<button aria-label="Decrease" class="button">
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none"
stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<line x1="5" y1="12" x2="19" y2="12"></line>
</svg>
</button>
</div>
</div>
<div class="example-row">
<div class="button-group vertical" role="group">
<button class="button">Up</button>
<button class="button">Down</button>
</div>
<div class="button-group outlined vertical" role="group">
<button class="button">Up</button>
<button class="button">Down</button>
</div>
<div class="button-group tonal vertical" role="group">
<button class="button">Up</button>
<button class="button">Down</button>
</div>
<div class="button-group filled vertical" role="group">
<button class="button">Up</button>
<button class="button">Down</button>
</div>
</div>

Disabled

Disable individual buttons within a group by adding the disabled attribute to each <button>.

<div role="group" class="button-group filled">
<button class="button">Enabled</button>
<button class="button" disabled>Disabled</button>
<button class="button">Enabled</button>
</div>
<div role="group" class="button-group filled primary">
<button class="button">Enabled</button>
<button class="button" disabled>Disabled</button>
<button class="button">Enabled</button>
</div>

Anatomy

  1. Container: <element role="group" class="button-group">
  2. Buttons: Button
<div class="button-group anatomy" role="group">
<button class="button">Button</button><button class="button">Button</button
><button class="button">Button</button>
</div>

API

Button group

Type Modifiers Default Description
Colors .critical, .primary - Color modifiers; cascade to every button in the group. Default is a neutral gray.
Orientation .vertical - Orientation modifier.
Sizes .small, .large - Size modifiers.
Variants .outlined, .tonal, .filled - Style modifiers.

Button

Type Modifiers Default Description
Sizes .small, default, .large - The size of the element.
Variants default, .outlined, .tonal, .filled - The variant to use.
Colors .critical, .primary - Color modifiers. Default is a neutral gray.

Browser support

Full support Supported since v111. Full support Supported since v113. Full support Supported since v16.2.

See also the full browser support guide.

Installation

@layer components.extended {
:where([role="group"].button-group) {
--_border-radius: var(--button-border-radius);
border-radius: var(--_border-radius);
display: inline-flex;
min-width: max-content;
/* Button */
button {
border-radius: 0;
/* button.css > --_accent-tonal */
--_divider-color: light-dark(oklch(from var(--_accent-tonal) calc(l - 0.1) c h),
oklch(from var(--_accent-tonal) calc(l + 0.1) c h));
&.outlined {
--_divider-color: var(--_border-color);
}
&.filled {
--_divider-color: currentColor;
}
&:focus-visible {
outline-offset: -4px;
}
/* Color inheritance from Button Group — shared interaction model.
The .critical scope class in theme.css redirects --palette-source so
--color-6 below becomes a tint of the active color. */
:where(.button-group.critical,
.button-group.primary) & {
--_color-contrast: var(--gray-1);
--_color-tonal: var(--color-6);
--_accent-tonal-contrast: var(--text-primary-contrast);
--_default-hover-bg-color: oklch(from var(--_accent) l c h / 15%);
--_default-active-bg-color: oklch(from var(--_accent) l c h / 25%);
--_filled-hover-bg-color: oklch(from var(--_accent) calc(l - 0.1) c h);
--_filled-active-bg-color: oklch(from var(--_accent) calc(l - 0.15) c h);
--_outlined-active-bg-color: oklch(from var(--_accent) calc(l - 0.1) c h);
}
:where(.button-group.critical) & {
--_color: var(--critical);
}
:where(.button-group.primary) & {
--_color: var(--primary);
}
:where(.button-group.small) & {
--_min-height: 1.875rem;
padding-block: 0;
padding-inline: 1ex;
}
:where(.button-group.large) & {
--_min-height: 2.875rem;
padding-inline: 4ex;
}
:where(.button-group.outlined) & {
--_border-color: var(--_accent);
--_divider-color: var(--_accent);
&:where(:not([disabled])) {
&:where(:not(:active):hover) {
--_bg-color: var(--_accent);
--_border-color: var(--_accent);
--_text-color: var(--_accent-contrast);
}
&:where(:active) {
--_bg-color: var(--_outlined-active-bg-color);
--_border-color: var(--_outlined-active-bg-color);
--_text-color: var(--_accent-contrast);
}
}
}
:where(.button-group.tonal) & {
--_bg-color: var(--_accent-tonal);
--_text-color: var(--_accent-tonal-contrast);
&:where(:not([disabled])) {
&:where(:not(:active):hover) {
--_bg-color: var(--_accent);
--_text-color: var(--_accent-contrast);
}
&:where(:active) {
--_bg-color: var(--_outlined-active-bg-color);
--_text-color: var(--_accent-contrast);
}
}
}
:where(.button-group.filled) & {
--_bg-color: var(--_accent);
--_text-color: var(--_accent-contrast);
--_divider-color: currentColor;
:where(.button-group.critical,
.button-group.primary) & {
--_divider-color: light-dark(oklch(from var(--_accent) calc(l - 0.1) c h),
oklch(from var(--_accent) calc(l + 0.1) c h));
}
&:where(:not([disabled])) {
&:where(:not(:active):hover) {
--_bg-color: var(--_filled-hover-bg-color);
}
&:where(:active) {
--_bg-color: var(--_filled-active-bg-color);
}
}
}
}
&:not(.vertical) {
button {
&:first-of-type {
border-end-start-radius: var(--_border-radius);
border-start-start-radius: var(--_border-radius);
}
&:last-of-type {
border-end-end-radius: var(--_border-radius);
border-start-end-radius: var(--_border-radius);
}
/* Siblings */
&+& {
border-inline-start-color: var(--_divider-color);
border-inline-width: 1px;
margin-inline-start: -1px;
&[disabled] {
border-inline-start-color: color-mix(in oklch, var(--_divider-color) 40%, transparent);
}
}
}
}
&.vertical {
flex-direction: column;
button {
padding: var(--size-2);
&:has(svg) {
aspect-ratio: 1;
padding: var(--size-1);
}
&:first-of-type {
border-start-start-radius: var(--_border-radius);
border-start-end-radius: var(--_border-radius);
}
&:last-of-type {
border-end-start-radius: var(--_border-radius);
border-end-end-radius: var(--_border-radius);
}
&+& {
border-block-start: 1px solid var(--_divider-color);
margin-block-start: -1px;
&[disabled] {
border-block-start-color: color-mix(in oklch, var(--_divider-color) 40%, transparent);
}
}
}
}
}
}