Components
Button group
A container that joins related buttons, inputs and menus into one unit with shared borders.
<div class="btn-group" role="group" aria-label="Message actions">
<button class="btn btn-outline">Archive</button>
<button class="btn btn-outline">Report</button>
<button class="btn btn-outline">Snooze</button>
</div>
Use a button group for buttons that perform actions. For buttons that switch a state on and off (bold, italic, text alignment), use a toggle group.
Accessibility#
Give the container role="group" and an aria-label so assistive technology announces the
buttons as a set. For a group of groups, use role="toolbar" on the outer one.
Orientation#
Add .btn-group-vertical to stack the buttons.
<div class="btn-group btn-group-vertical" role="group" aria-label="Zoom">
<button class="btn btn-outline btn-icon" aria-label="Zoom in"><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" class="size-4" aria-hidden="true"><path d="M5 12h14M12 5v14"/></svg></button>
<button class="btn btn-outline btn-icon" aria-label="Zoom out"><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" class="size-4" aria-hidden="true"><path d="M5 12h14"/></svg></button>
</div>
<div class="btn-group btn-group-vertical" role="group" aria-label="Views">
<button class="btn btn-outline">Day</button>
<button class="btn btn-outline">Week</button>
<button class="btn btn-outline">Month</button>
</div>
Size#
.btn-group-sm and .btn-group-lg resize every button, input and text in the group, so you don't size them one by one.
<div class="btn-group btn-group-sm" role="group" aria-label="Small">
<button class="btn btn-outline">Small</button>
<button class="btn btn-outline">Group</button>
<button class="btn btn-outline btn-icon" aria-label="Add"><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" class="size-4" aria-hidden="true"><path d="M5 12h14M12 5v14"/></svg></button>
</div>
<div class="btn-group" role="group" aria-label="Default">
<button class="btn btn-outline">Default</button>
<button class="btn btn-outline">Group</button>
<button class="btn btn-outline btn-icon" aria-label="Add"><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" class="size-4" aria-hidden="true"><path d="M5 12h14M12 5v14"/></svg></button>
</div>
<div class="btn-group btn-group-lg" role="group" aria-label="Large">
<button class="btn btn-outline">Large</button>
<button class="btn btn-outline">Group</button>
<button class="btn btn-outline btn-icon" aria-label="Add"><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" class="size-4" aria-hidden="true"><path d="M5 12h14M12 5v14"/></svg></button>
</div>
Icons#
<div class="btn-group" role="group" aria-label="Post">
<button class="btn btn-outline"><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" class="size-4" aria-hidden="true"><path d="M11.525 2.295a.53.53 0 0 1 .95 0l2.31 4.679a2.123 2.123 0 0 0 1.595 1.16l5.166.756a.53.53 0 0 1 .294.904l-3.736 3.638a2.123 2.123 0 0 0-.611 1.878l.882 5.14a.53.53 0 0 1-.771.56l-4.618-2.428a2.122 2.122 0 0 0-1.973 0L6.396 21.01a.53.53 0 0 1-.77-.56l.881-5.139a2.122 2.122 0 0 0-.611-1.879L2.16 9.795a.53.53 0 0 1 .294-.906l5.165-.755a2.122 2.122 0 0 0 1.597-1.16z"/></svg> Star</button>
<button class="btn btn-outline"><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" class="size-4" aria-hidden="true"><path d="m19 21-7-4-7 4V5a2 2 0 0 1 2-2h10a2 2 0 0 1 2 2v16z"/></svg> Save</button>
<button class="btn btn-outline btn-icon" aria-label="Copy link"><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" class="size-4" aria-hidden="true"><path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"/><path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"/></svg></button>
</div>
Separator#
Buttons without a border of their own (secondary, primary) run into each other. Put a
.btn-group-separator between them.
<div class="btn-group" role="group" aria-label="Clipboard">
<button class="btn btn-secondary">Copy</button>
<div class="btn-group-separator" role="separator"></div>
<button class="btn btn-secondary">Paste</button>
</div>
<div class="btn-group btn-group-vertical" role="group" aria-label="Order">
<button class="btn btn-secondary btn-icon" aria-label="Move up"><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" class="size-4" aria-hidden="true"><path d="m18 15-6-6-6 6"/></svg></button>
<div class="btn-group-separator" role="separator"></div>
<button class="btn btn-secondary btn-icon" aria-label="Move down"><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" class="size-4" aria-hidden="true"><path d="m6 9 6 6 6-6"/></svg></button>
</div>
Nested#
Groups inside a group are spaced apart instead of joined: a toolbar.
<div class="btn-group" role="toolbar" aria-label="Pagination">
<div class="btn-group" role="group" aria-label="Pages">
<button class="btn btn-outline btn-sm">1</button>
<button class="btn btn-outline btn-sm">2</button>
<button class="btn btn-outline btn-sm">3</button>
</div>
<div class="btn-group" role="group" aria-label="Step">
<button class="btn btn-outline btn-sm btn-icon" aria-label="Previous"><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" class="size-4" aria-hidden="true"><path d="M19 12H5M12 19l-7-7 7-7"/></svg></button>
<button class="btn btn-outline btn-sm btn-icon" aria-label="Next"><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" class="size-4" aria-hidden="true"><path d="M5 12h14M12 5l7 7-7 7"/></svg></button>
</div>
</div>
With an input#
Inputs and selects join the group and fill the space left by the buttons.
<div class="btn-group w-full max-w-sm" role="group" aria-label="Search">
<input class="input" type="search" placeholder="Search…" aria-label="Search" />
<button class="btn btn-outline btn-icon" aria-label="Search"><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" class="size-4" aria-hidden="true"><circle cx="11" cy="11" r="8"/><path d="m21 21-4.3-4.3"/></svg></button>
</div>
<div class="btn-group w-full max-w-sm" role="group" aria-label="Website">
<span class="btn-group-text">https://</span>
<input class="input" placeholder="example.com" aria-label="Website" />
<div class="select w-24 flex-none" data-select>
<button type="button" id="bg-domain" class="select-trigger" data-select-trigger aria-haspopup="listbox" aria-expanded="false" aria-label="Domain">
<span class="select-value" data-placeholder="Select…">.com</span>
<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" class="size-4" aria-hidden="true"><path d="m6 9 6 6 6-6"/></svg>
</button>
<div class="select-content select-content-end" id="bg-domain-listbox" role="listbox" aria-label="Domain" hidden>
<span class="select-item" role="option" value=".com" aria-selected="true">.com<span class="select-check"><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" class="size-4" aria-hidden="true"><path d="M20 6 9 17l-5-5"/></svg></span></span>
<span class="select-item" role="option" value=".org" aria-selected="false">.org<span class="select-check"><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" class="size-4" aria-hidden="true"><path d="M20 6 9 17l-5-5"/></svg></span></span>
<span class="select-item" role="option" value=".net" aria-selected="false">.net<span class="select-check"><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" class="size-4" aria-hidden="true"><path d="M20 6 9 17l-5-5"/></svg></span></span>
</div>
</div>
</div>
With an input group#
An input group can sit in a button group too, with addons of its own.
<div class="btn-group w-full max-w-md" role="group" aria-label="Message">
<button class="btn btn-outline btn-icon" aria-label="Attach"><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" class="size-4" aria-hidden="true"><path d="M5 12h14M12 5v14"/></svg></button>
<div class="input-group">
<input class="input" placeholder="Send a message…" aria-label="Message" />
<span class="input-group-addon input-group-addon-inline-end"><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" class="spinner" role="status" aria-label="Loading"><path d="M21 12a9 9 0 1 1-6.22-8.56"/></svg></span>
</div>
<button class="btn btn-primary btn-icon" aria-label="Send"><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" class="size-4" aria-hidden="true"><path d="M14.536 21.686a.5.5 0 0 0 .937-.024l6.5-19a.496.496 0 0 0-.635-.635l-19 6.5a.5.5 0 0 0-.024.937l7.93 3.18a2 2 0 0 1 1.112 1.11z"/><path d="m21.854 2.147-10.94 10.939"/></svg></button>
</div>
Split button#
A main action plus a dropdown of related ones. The
.dropdown wrapper joins the group like a button.
<div class="btn-group" role="group" aria-label="Merge">
<button class="btn btn-primary">Merge pull request</button>
<div class="btn-group-separator" role="separator"></div>
<div class="dropdown" data-dropdown>
<button class="btn btn-primary btn-icon" data-dropdown-trigger aria-haspopup="menu" aria-expanded="false" aria-label="More merge options"><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" class="size-4" aria-hidden="true"><path d="m6 9 6 6 6-6"/></svg></button>
<div class="dropdown-menu dropdown-menu-end" role="menu" hidden>
<button class="dropdown-item" role="menuitem">Squash and merge</button>
<button class="dropdown-item" role="menuitem">Rebase and merge</button>
</div>
</div>
</div>
<div class="btn-group" role="group" aria-label="Follow">
<button class="btn btn-outline">Follow</button>
<div class="dropdown" data-dropdown>
<button class="btn btn-outline btn-icon" data-dropdown-trigger aria-haspopup="menu" aria-expanded="false" aria-label="More"><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" class="size-4" aria-hidden="true"><circle cx="12" cy="12" r="1"/><circle cx="19" cy="12" r="1"/><circle cx="5" cy="12" r="1"/></svg></button>
<div class="dropdown-menu dropdown-menu-end" role="menu" hidden>
<button class="dropdown-item" role="menuitem">Mute conversation</button>
<button class="dropdown-item" role="menuitem">Copy link</button>
<div class="dropdown-separator" role="separator"></div>
<button class="dropdown-item dropdown-item-destructive" role="menuitem">Report</button>
</div>
</div>
</div>
Popover#
A popover trigger works the same way, for content that isn't a menu.
Start a new task
Describe what you want done.
<div class="btn-group" role="group" aria-label="Copilot">
<button class="btn btn-outline"><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" class="size-4" aria-hidden="true"><path d="M12 8V4H8"/><rect width="16" height="12" x="4" y="8" rx="2"/><path d="M2 14h2M20 14h2M15 13v2M9 13v2"/></svg> Copilot</button>
<div class="popover" data-popover>
<button class="btn btn-outline btn-icon" data-popover-trigger aria-expanded="false" aria-label="Open popover"><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" class="size-4" aria-hidden="true"><path d="m6 9 6 6 6-6"/></svg></button>
<div class="popover-content popover-content-end" data-popover-content hidden>
<p class="popover-title">Start a new task</p>
<p class="popover-description">Describe what you want done.</p>
<textarea class="textarea mt-3" placeholder="Fix the flaky test in…" aria-label="Task" autofocus></textarea>
</div>
</div>
</div>
Reference#
| Class | Description |
|---|---|
.btn-group | Joins its children: inner corners squared, shared borders overlapped. Groups inside it are spaced instead. |
.btn-group-vertical | Stacks the children. |
.btn-group-sm / -lg | Resizes every button, input and text in the group. |
.btn-group-text | Static label styled to sit in a group, like https://. |
.btn-group-separator | 1px divider between buttons that have no border. |