Button Group
actionUSWDS-derived
Groups buttons horizontally with proper spacing.
Reference: USWDS documentation ↗
Variants
Default
<ul class="flex-button-group">
<li class="flex-button-group__item">
<button class="flex-button" type="button">Primary</button>
</li>
<li class="flex-button-group__item">
<button class="flex-button" data-variant="outline" type="button">Secondary</button>
</li>
</ul>Segmented
<ul class="flex-button-group" data-variant="segmented">
<li class="flex-button-group__item">
<button class="flex-button" type="button">First</button>
</li>
<li class="flex-button-group__item">
<button class="flex-button" type="button">Middle</button>
</li>
<li class="flex-button-group__item">
<button class="flex-button" type="button">Last</button>
</li>
</ul>With Disabled
<ul class="flex-button-group">
<li class="flex-button-group__item">
<button class="flex-button" type="button">Active</button>
</li>
<li class="flex-button-group__item">
<button class="flex-button" data-variant="outline" type="button">Cancel</button>
</li>
<li class="flex-button-group__item">
<button class="flex-button" type="button" disabled="">Disabled</button>
</li>
</ul>Contract
Class mapping
| USWDS | Flex | Notes |
|---|---|---|
usa-button-group | .flex-button-group | Base button group list |
usa-button-group__item | .flex-button-group__item | List item wrapper for each button |
usa-button-group--segmented | data-variant="segmented" | Segmented variant with touching buttons |
Verified properties
displayflex-directionflex-wraplist-style-typepadding-leftmargin-topmargin-bottomBehavior promises
- ○ Buttons are arranged horizontally
- ○ Segmented variant buttons touch with no gap
Source CSS
/* flex-button-group -- USWDS Button Group conformance
Variants: default, segmented
Layout: horizontal flex with proper spacing */
.flex-button-group {
margin-block: 0;
display: flex;
flex-wrap: nowrap;
align-items: stretch;
flex-direction: row;
list-style-type: none;
margin-inline: -0.25rem;
padding-inline-start: 0;
/* --- Segmented variant --- */
&[data-variant="segmented"] {
flex-direction: row;
flex-wrap: nowrap;
justify-content: flex-start;
margin-inline: 0;
.flex-button-group__item {
margin-inline: 0;
}
.flex-button {
position: relative;
border-radius: 0;
&:hover,
&:active {
z-index: 2;
}
&:focus {
z-index: 3;
}
}
}
}
.flex-button-group__item {
margin: 0.25rem;
&:last-child {
margin-inline-end: 0;
}
.flex-button {
block-size: 100%;
margin-inline: 0;
}
}
/* First button: rounded start corners */
.flex-button-group[data-variant="segmented"] .flex-button-group__item:first-child
> .flex-button {
border-start-start-radius: var(--flex-radius-sm);
border-end-start-radius: var(--flex-radius-sm);
border-start-end-radius: 0;
border-end-end-radius: 0;
margin-inline-end: -1px;
}
/* Last button: rounded end corners */
.flex-button-group[data-variant="segmented"] .flex-button-group__item:last-child
> .flex-button {
border-start-start-radius: 0;
border-end-start-radius: 0;
border-start-end-radius: var(--flex-radius-sm);
border-end-end-radius: var(--flex-radius-sm);
margin-inline-start: -1px;
margin-inline-end: 0;
}
/* Middle buttons: no border radius, negative margins to overlap */
.flex-button-group[data-variant="segmented"] .flex-button-group__item:where(
:not(:first-child, :last-child))
> .flex-button {
border-radius: 0;
margin-inline: -1px;
}
/* Separator line between segmented buttons */
.flex-button-group[data-variant="segmented"] .flex-button-group__item:where(
:not(:last-child)
)
.flex-button::before {
border-inline-end: 1px solid
color-mix(in srgb, var(--flex-color-accent) 70%, black);
inset-block: 0;
content: "";
display: block;
block-size: 100%;
position: absolute;
inset-inline-end: 1px;
inline-size: 1px;
z-index: 3;
}
A digital services project by Flexion