25 CSS Button Groups
07 / 25

All 25 in 25 CSS Button Groups

  1. 01CSS Split Button with Anchor-Positioned Popover Menu (Popover API, No JS)
  2. 02CSS Segmented Control with Motion-Path Comet Thumb (offset-path Arc Travel)
  3. 03CSS View Transitions Toggle Button Group with Morphing Thumb (Shared-Element FLIP)
  4. 04CSS Pricing Toggle with Monthly / Yearly Switch (Pure CSS, No JavaScript)
  5. 05CSS Segmented Control with Sliding Thumb Indicator (iOS-Style, Pure CSS)
  6. 06CSS Split Button Dropdown with Native <details> (Primary Action + Menu)
  7. 07CSS Icon Button Group for Toolbar Actions (Accessible Tooltips, Pure CSS)
  8. 08CSS Pill Radio Button Group with Sliding Indicator (Filter Pills, Pure CSS)
  9. 09CSS Toggle Button Group with Radio Inputs (Single-Select Alignment Group)
  10. 10CSS Wallet Connect Button Grid for Web3 Sign-In (MetaMask, WalletConnect, Coinbase)
  11. 11CSS AI Model Selector Button Group with Provider Badges (LLM Model Picker)
  12. 12CSS Segmented Control with Liquid Mercury Thumb (Metallic Stretch Animation)
  13. 13CSS Button Group with Subgrid Underline Beam (Perfectly Aligned Tab Indicator)
  14. 14CSS Multi-Select Chip Buttons with Acid Glow (Toggleable Tag Filters)
  15. 15CSS Split Button with Quantum Chevron Reveal (Animated Menu Materialize)
  16. 16CSS Format Toggle Button Group with Conic Fill (Radial Sweep Select)
  17. 17CSS Pixel Matrix Button Group with LED Segment Glow (Retro Display Buttons)
  18. 18CSS Multi-Action Button Group with Gradient Flow Progress (Animated CTA Bar)
  19. 19CSS Icon Segmented Control with Holographic Sheen (Iridescent View Switcher)
  20. 20CSS Vertical Button Stack with 3D Hover Depth (Tilting Card Buttons)
  21. 21CSS Floating Action Button with Radial Sub-Button Menu (Arc Fan-Out, Pure CSS)
  22. 22CSS Filter Button Group with RGB-Split Glitch Active State (Cyberpunk Toggle)
  23. 23CSS Pill Button Group with Rotating Conic Plasma Border (Animated Gradient Ring)
  24. 24CSS Action Button Row with Radar Shockwave Click Feedback (Ripple Pulse)
  25. 25CSS Date-Range Preset Button Group with Cursor-Following Glow (Spotlight Hover)
Pure CSSMIT licensed

CSS Icon Button Group for Toolbar Actions (Accessible Tooltips, Pure CSS)

A fused icon toolbar like the ones in Figma, Notion and Google Docs: bold / italic / underline / link / code as a segmented row of icon buttons with hover tooltips, pressed states and proper labels. The complete 'CSS icon button group toolbar' pattern — every icon button keeps a real accessible name, a 44px hit area and a keyboard focus ring.

Live Demo
Plain CSSTailwind v4
Try it

Build UI like this from scratch: Flexbox, Grid, animations & responsive CSS

ZTM · The CSS Bootcamp · 30‑day money-back guarantee · Affiliate link

10% off at checkout with code
Check ZTM Course

The code

<section class="btn-07" aria-label="Icon button group toolbar demo">
  <div class="btn-07__bar" role="toolbar" aria-label="Text formatting">
    <button type="button" class="btn-07__tool" aria-label="Bold" aria-pressed="true" data-tip="Bold"><svg viewBox="0 0 24 24" width="19" height="19" fill="none" stroke="currentColor" stroke-width="2.4"><path d="M7 5h6a3.5 3.5 0 0 1 0 7H7zM7 12h7a3.5 3.5 0 0 1 0 7H7z"/></svg></button>
    <button type="button" class="btn-07__tool" aria-label="Italic" data-tip="Italic"><svg viewBox="0 0 24 24" width="19" height="19" fill="none" stroke="currentColor" stroke-width="2.4"><path d="M14 5h-4M14 5l-4 14M14 19h-4"/></svg></button>
    <button type="button" class="btn-07__tool" aria-label="Underline" data-tip="Underline"><svg viewBox="0 0 24 24" width="19" height="19" fill="none" stroke="currentColor" stroke-width="2.4"><path d="M7 4v7a5 5 0 0 0 10 0V4M6 21h12"/></svg></button>
    <span class="btn-07__div"></span>
    <button type="button" class="btn-07__tool" aria-label="Insert link" data-tip="Link"><svg viewBox="0 0 24 24" width="19" height="19" fill="none" stroke="currentColor" stroke-width="2.2"><path d="M10 13a4 4 0 0 0 5.7.6l2.6-2.6a4 4 0 0 0-5.6-5.7l-1.5 1.5M14 11a4 4 0 0 0-5.7-.6L5.7 13a4 4 0 0 0 5.6 5.7l1.5-1.5"/></svg></button>
    <button type="button" class="btn-07__tool" aria-label="Inline code" data-tip="Code"><svg viewBox="0 0 24 24" width="19" height="19" fill="none" stroke="currentColor" stroke-width="2.2"><path d="M9 8l-5 4 5 4M15 8l5 4-5 4"/></svg></button>
    <span class="btn-07__div"></span>
    <button type="button" class="btn-07__tool" aria-label="Clear formatting" data-tip="Clear"><svg viewBox="0 0 24 24" width="19" height="19" fill="none" stroke="currentColor" stroke-width="2.2"><path d="M6 5h12M9 5l-2 14M15 5l1 7M5 19l14-14"/></svg></button>
  </div>
</section>
.btn-07,
.btn-07 *,
.btn-07 *::before,
.btn-07 *::after {
  box-sizing: border-box;
  margin: 0;
  padding: 0;
}

.btn-07 {
  --accent: oklch(0.7 0.17 135);
  --ink: #1a2415;
  font-family: 'Segoe UI',system-ui,sans-serif;
  width: 100%;
  min-height: 100vh;
  display: flex;
  align-items: flex-start;
  justify-content: center;
  background: linear-gradient(150deg,#20261c,#2c3626);
  padding: 130px 20px;
}

.btn-07__bar {
  display: inline-flex;
  align-items: center;
  gap: 2px;
  padding: 6px;
  background: #f4f7f0;
  border-radius: 16px;
  box-shadow: 0 20px 44px -20px rgba(0,0,0,.7),inset 0 0 0 1px rgba(255,255,255,.6);
}

.btn-07__tool {
  position: relative;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 44px;
  height: 44px;
  border: none;
  background: none;
  color: #485a3d;
  border-radius: 11px;
  cursor: pointer;
  transition: background .14s,color .14s;
}

.btn-07__tool:hover {
  background: #e5ecdd;
  color: var(--ink);
}

.btn-07__tool[aria-pressed=true] {
  background: var(--accent);
  color: #12200a;
}

.btn-07__div {
  width: 1px;
  height: 26px;
  background: #d4ddca;
  margin: 0 4px;
}

.btn-07__tool::after {
  content: attr(data-tip);
  position: absolute;
  bottom: calc(100% + 10px);
  left: 50%;
  translate: -50% 0;
  background: var(--ink);
  color: #eef4e8;
  font-size: 12px;
  font-weight: 600;
  padding: 5px 9px;
  border-radius: 7px;
  white-space: nowrap;
  opacity: 0;
  pointer-events: none;
  transition: opacity .15s,translate .15s;
}

.btn-07__tool::before {
  content: "";
  position: absolute;
  bottom: calc(100% + 5px);
  left: 50%;
  translate: -50% 0;
  border: 5px solid transparent;
  border-top-color: var(--ink);
  opacity: 0;
  transition: opacity .15s;
}

.btn-07__tool:hover::after,
.btn-07__tool:focus-visible::after {
  opacity: 1;
  translate: -50% -3px;
}

.btn-07__tool:hover::before,
.btn-07__tool:focus-visible::before {
  opacity: 1;
}

.btn-07__tool:focus-visible {
  outline: 3px solid var(--accent);
  outline-offset: 2px;
  z-index: 1;
}

@media (prefers-reduced-motion: reduce) {
  .btn-07__tool,
    .btn-07__tool::after {
    transition: none;
  }
}
Paste this into ChatGPT, Claude, Cursor, or any coding assistant. The block below is pre-framed with everything the AI needs to integrate this demo into your project — markup, styles, scoping notes, and the source URL. Hit Copy and paste straight into your chat.
Here's a working CSS Button Group from CodeFronts. Use it as-is or adapt to your framework. All classes are scoped under a unique prefix so the code won't collide with your existing styles. MIT licensed.
Demo: CSS Icon Button Group for Toolbar Actions (Accessible Tooltips, Pure CSS)
Source: https://codefronts.com/components/css-button-groups/css-icon-button-group-for-toolbar-actions-accessible-tooltips-pure-css/

A fused icon toolbar like the ones in Figma, Notion and Google Docs: bold / italic / underline / link / code as a segmented row of icon buttons with hover tooltips, pressed states and proper labels. The complete 'CSS icon button group toolbar' pattern — every icon button keeps a real accessible name, a 44px hit area and a keyboard focus ring.
## HTML
```html
<section class="btn-07" aria-label="Icon button group toolbar demo">
  <div class="btn-07__bar" role="toolbar" aria-label="Text formatting">
    <button type="button" class="btn-07__tool" aria-label="Bold" aria-pressed="true" data-tip="Bold"><svg viewBox="0 0 24 24" width="19" height="19" fill="none" stroke="currentColor" stroke-width="2.4"><path d="M7 5h6a3.5 3.5 0 0 1 0 7H7zM7 12h7a3.5 3.5 0 0 1 0 7H7z"/></svg></button>
    <button type="button" class="btn-07__tool" aria-label="Italic" data-tip="Italic"><svg viewBox="0 0 24 24" width="19" height="19" fill="none" stroke="currentColor" stroke-width="2.4"><path d="M14 5h-4M14 5l-4 14M14 19h-4"/></svg></button>
    <button type="button" class="btn-07__tool" aria-label="Underline" data-tip="Underline"><svg viewBox="0 0 24 24" width="19" height="19" fill="none" stroke="currentColor" stroke-width="2.4"><path d="M7 4v7a5 5 0 0 0 10 0V4M6 21h12"/></svg></button>
    <span class="btn-07__div"></span>
    <button type="button" class="btn-07__tool" aria-label="Insert link" data-tip="Link"><svg viewBox="0 0 24 24" width="19" height="19" fill="none" stroke="currentColor" stroke-width="2.2"><path d="M10 13a4 4 0 0 0 5.7.6l2.6-2.6a4 4 0 0 0-5.6-5.7l-1.5 1.5M14 11a4 4 0 0 0-5.7-.6L5.7 13a4 4 0 0 0 5.6 5.7l1.5-1.5"/></svg></button>
    <button type="button" class="btn-07__tool" aria-label="Inline code" data-tip="Code"><svg viewBox="0 0 24 24" width="19" height="19" fill="none" stroke="currentColor" stroke-width="2.2"><path d="M9 8l-5 4 5 4M15 8l5 4-5 4"/></svg></button>
    <span class="btn-07__div"></span>
    <button type="button" class="btn-07__tool" aria-label="Clear formatting" data-tip="Clear"><svg viewBox="0 0 24 24" width="19" height="19" fill="none" stroke="currentColor" stroke-width="2.2"><path d="M6 5h12M9 5l-2 14M15 5l1 7M5 19l14-14"/></svg></button>
  </div>
</section>
```
## CSS
```css
.btn-07,
.btn-07 *,
.btn-07 *::before,
.btn-07 *::after {
  box-sizing: border-box;
  margin: 0;
  padding: 0;
}

.btn-07 {
  --accent: oklch(0.7 0.17 135);
  --ink: #1a2415;
  font-family: 'Segoe UI',system-ui,sans-serif;
  width: 100%;
  min-height: 100vh;
  display: flex;
  align-items: flex-start;
  justify-content: center;
  background: linear-gradient(150deg,#20261c,#2c3626);
  padding: 130px 20px;
}

.btn-07__bar {
  display: inline-flex;
  align-items: center;
  gap: 2px;
  padding: 6px;
  background: #f4f7f0;
  border-radius: 16px;
  box-shadow: 0 20px 44px -20px rgba(0,0,0,.7),inset 0 0 0 1px rgba(255,255,255,.6);
}

.btn-07__tool {
  position: relative;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 44px;
  height: 44px;
  border: none;
  background: none;
  color: #485a3d;
  border-radius: 11px;
  cursor: pointer;
  transition: background .14s,color .14s;
}

.btn-07__tool:hover {
  background: #e5ecdd;
  color: var(--ink);
}

.btn-07__tool[aria-pressed=true] {
  background: var(--accent);
  color: #12200a;
}

.btn-07__div {
  width: 1px;
  height: 26px;
  background: #d4ddca;
  margin: 0 4px;
}

.btn-07__tool::after {
  content: attr(data-tip);
  position: absolute;
  bottom: calc(100% + 10px);
  left: 50%;
  translate: -50% 0;
  background: var(--ink);
  color: #eef4e8;
  font-size: 12px;
  font-weight: 600;
  padding: 5px 9px;
  border-radius: 7px;
  white-space: nowrap;
  opacity: 0;
  pointer-events: none;
  transition: opacity .15s,translate .15s;
}

.btn-07__tool::before {
  content: "";
  position: absolute;
  bottom: calc(100% + 5px);
  left: 50%;
  translate: -50% 0;
  border: 5px solid transparent;
  border-top-color: var(--ink);
  opacity: 0;
  transition: opacity .15s;
}

.btn-07__tool:hover::after,
.btn-07__tool:focus-visible::after {
  opacity: 1;
  translate: -50% -3px;
}

.btn-07__tool:hover::before,
.btn-07__tool:focus-visible::before {
  opacity: 1;
}

.btn-07__tool:focus-visible {
  outline: 3px solid var(--accent);
  outline-offset: 2px;
  z-index: 1;
}

@media (prefers-reduced-motion: reduce) {
  .btn-07__tool,
    .btn-07__tool::after {
    transition: none;
  }
}
```

How this works

The toolbar is a display:flex group of <button> elements sharing one rounded shell; inner corners are squared and a hairline divider separates each. Icons are inline SVG (crisp at any scale, currentColor-aware). Every button carries an aria-label so screen readers announce the action even though the visible content is only a glyph.

Toggle buttons (bold/italic) use aria-pressed and a CSS :has()-free approach: here the pressed look is driven by the demo's static markup, but in production you toggle the attribute. Tooltips are pure CSS — a ::after label + ::before arrow revealed on hover and :focus-visible, so keyboard users see them too.

.tool[aria-pressed=true]{ background:var(--accent); color:#fff }
.tool:hover::after,.tool:focus-visible::after{ opacity:1 }

Techniques used: fused flex button group with shared shell + inner dividers · inline SVG icons with currentColor · aria-label names + aria-pressed toggles · pure-CSS ::after tooltips on hover AND focus · 44px minimum hit targets

Make it yours

  • --accent tints active/pressed buttons and focus rings.
  • Add or reorder tools freely — the flex shell and dividers self-adjust.
  • Tooltip text comes from each button's data-tip attribute.
  • Show tooltips below instead of above by flipping the ::after position.

Gotchas — read before shipping

  • An icon button with no accessible name is invisible to screen readers — every one needs aria-label or visually-hidden text.
  • Toggle buttons must expose state via aria-pressed, not color alone (WCAG 1.4.1).
  • Never shrink icon buttons below a 44×44px hit area on touch (WCAG 2.5.8).
  • Tooltips built only on :hover exclude keyboard users — always include :focus-visible as done here.

Browser support

ChromeSafariFirefoxEdge
111+15.4+113+111+

Floor set by oklch() as this demo is written. The core technique itself goes back further — Chrome all.

Pure CSS + inline SVG + ARIA attributes — works in every modern browser with no feature dependencies.

Techniques used in this demo

Search CodeFronts

Loading…