34 CSS Floating Buttons
25 / 34

All 34 in 34 CSS Floating Buttons

  1. 01Material Design 3 Floating Action Button (FAB)
  2. 02iOS-Style Compose Floating Button
  3. 03WhatsApp Floating Message Button CSS
  4. 04Intercom / Drift Chat Bubble Floating Button
  5. 05Accessible WAI-ARIA Floating Action Button (WCAG 2.2)
  6. 06Extended FAB with Icon and Label (Material Design 3)
  7. 07Speed Dial Radial Menu FAB with Backdrop
  8. 08Pure CSS FAB Speed Dial (No JavaScript)
  9. 09Material Gradient Floating Action Button CSS
  10. 10Vertical and Horizontal Speed Dial FAB Menu CSS
  11. 11Morphing FAB Button That Expands to Pill CSS
  12. 12Scroll-to-Top Floating Button with SVG Progress Ring
  13. 13Floating Chat Widget FAB with Notification Panel
  14. 14Fan and Arc Radial Spread FAB Menu CSS
  15. 15Apple Squircle Superellipse Floating Button CSS
  16. 16Social Share Floating Button Cluster CSS
  17. 17Glassmorphism Floating Action Button with Backdrop Blur
  18. 18Cyberpunk Neon Glow Floating Button CSS
  19. 19Floating Compose Button with Tooltip on Hover CSS
  20. 20Draggable Floating Action Button with Corner Snap CSS
  21. 21Notification Bell Floating Button with Badge Counter
  22. 22Floating Cart Button with Live Badge Counter CSS
  23. 23Magnetic Cursor Follower Floating Button CSS
  24. 24Dark Mode Theme Toggle Floating Button CSS
  25. 25Classic Gradient Circle Plus FAB CSS
  26. 26Pulse Ring Attention-Getter Floating Button CSS
  27. 27Pill-Shaped FAB with Icon and Text Label CSS
  28. 28Neo-Brutalist Hard Shadow Floating Button CSS
  29. 29Floating Button with Loading Spinner State CSS
  30. 30Draggable Floating Button with 6-Dot Grip Handle CSS
  31. 31Voice Recording Microphone Floating Button CSS
  32. 32Aurora Gradient Drift Premium Floating Button CSS
  33. 33Quick Emoji Reply Reaction Floating Button CSS
  34. 34Modern Squircle Rounded Square FAB CSS
Pure CSSMIT licensed

Classic Gradient Circle Plus FAB CSS

The one everybody needs first: a round gradient FAB with a plus, done to a standard you can ship. The plus is drawn with two pseudo-elements rather than an icon file, so it rotates into an X, scales with the button and inherits colour. Two rules of CSS, three states, and a shadow that changes with elevation instead of staying flat.

Live Demo
Try it

Nucleo: 44,000+ SVG icons in five families · All Icons Bundle $149

Nucleo · Affiliate link

Get the Nucleo bundle

The code

<section class="fb-25" aria-label="Classic gradient circle plus floating action button demo">
  <div class="fb-25__stage">
    <p class="fb-25__eyebrow">pseudo-element icon · elevation states</p>
    <h2 class="fb-25__title">The plus is two rectangles</h2>
    <p class="fb-25__sub">No icon file, no font, no flash of missing glyph. It inherits colour, scales with the button, and rotates into a close mark on hover.</p>
    <div class="fb-25__row">
      <div class="fb-25__cell"><button class="fb-25__fab fb-25__fab--sm" type="button" aria-label="Add item, compact"></button><span class="fb-25__cap">48</span></div>
      <div class="fb-25__cell"><button class="fb-25__fab" type="button" aria-label="Add item"></button><span class="fb-25__cap">56</span></div>
      <div class="fb-25__cell"><button class="fb-25__fab fb-25__fab--lg" type="button" aria-label="Add item, prominent"></button><span class="fb-25__cap">64</span></div>
      <div class="fb-25__cell"><button class="fb-25__fab fb-25__fab--alt" type="button" aria-label="Add item, alternate palette"></button><span class="fb-25__cap">alt</span></div>
      <div class="fb-25__cell"><button class="fb-25__fab fb-25__fab--out" type="button" aria-label="Add item, outlined"></button><span class="fb-25__cap">outline</span></div>
    </div>
    <div class="fb-25__states" aria-hidden="true">
      <span><i class="fb-25__sw fb-25__sw--rest"></i>rest · 10/24</span>
      <span><i class="fb-25__sw fb-25__sw--hov"></i>hover · 16/36 −2px</span>
      <span><i class="fb-25__sw fb-25__sw--act"></i>active · 4/10 ×0.94</span>
    </div>
    <p class="fb-25__chip">currentColor bars · 150° gradient · hue-matched shadow</p>
  </div>
</section>
.fb-25 {
  width: 100%;
  min-height: 100vh;
  min-height: 100svh;
  display: block;
  background: var(--fb-25-bg);
  --fb-25-bg: oklch(0.97 0.01 300);
  --fb-25-a: oklch(0.7 0.19 330);
  --fb-25-b: oklch(0.5 0.2 288);
  --fb-25-ink: oklch(0.23 0.03 300);
  --fb-25-mut: oklch(0.53 0.02 300);
  --fb-25-size: 56px;
  font-family: 'Segoe UI',system-ui,-apple-system,sans-serif;
  color: var(--fb-25-ink);
  display: grid;
  place-items: center;
  padding: clamp(20px,5vw,56px);
}

.fb-25 *,
.fb-25 *::before,
.fb-25 *::after {
  box-sizing: border-box;
  margin: 0;
  padding: 0;
}

.fb-25__stage {
  width: min(100%,58ch);
  display: grid;
  gap: clamp(18px,3vw,28px);
  justify-items: center;
  text-align: center;
}

.fb-25__eyebrow {
  font-family: ui-monospace,Menlo,Consolas,monospace;
  font-size: 11.5px;
  letter-spacing: .16em;
  text-transform: uppercase;
  color: var(--fb-25-b);
}

.fb-25__title {
  font-size: clamp(26px,4.6vw,44px);
  line-height: 1.05;
  letter-spacing: -.03em;
  font-weight: 700;
  text-wrap: balance;
}

.fb-25__sub {
  max-width: 50ch;
  font-size: clamp(13.5px,1.7vw,16.5px);
  line-height: 1.62;
  color: var(--fb-25-mut);
  text-wrap: pretty;
}

.fb-25__row {
  display: flex;
  flex-wrap: wrap;
  gap: clamp(16px,4vw,34px);
  justify-content: center;
  align-items: center;
}

.fb-25__cell {
  display: grid;
  gap: 10px;
  justify-items: center;
}

.fb-25__cap {
  font-family: ui-monospace,Menlo,Consolas,monospace;
  font-size: 11px;
  color: var(--fb-25-mut);
}

.fb-25__fab {
  position: relative;
  inline-size: var(--fb-25-size);
  block-size: var(--fb-25-size);
  border: 0;
  border-radius: 50%;
  cursor: pointer;
  color: oklch(0.99 0.01 330);
  background: linear-gradient(150deg,var(--fb-25-a),var(--fb-25-b));
  box-shadow: 0 10px 24px -10px oklch(0.5 0.2 288/.75),0 2px 5px oklch(0.4 0.12 300/.25);
  transition: transform .3s cubic-bezier(.2,1.25,.4,1),box-shadow .3s ease,rotate .34s cubic-bezier(.3,1.3,.4,1);
}

.fb-25__fab::before,
.fb-25__fab::after {
  content: "";
  position: absolute;
  left: 50%;
  top: 50%;
  inline-size: calc(var(--fb-25-size) * .4);
  block-size: 2.6px;
  translate: -50% -50%;
  border-radius: 2px;
  background: currentColor;
}

.fb-25__fab::after {
  rotate: 90deg;
}

.fb-25__fab:hover {
  rotate: 90deg;
  box-shadow: 0 16px 36px -10px oklch(0.5 0.2 288/.85),0 2px 5px oklch(0.4 0.12 300/.25);
  translate: 0 -2px;
}

.fb-25__fab:active {
  transform: scale(.94);
  box-shadow: 0 4px 10px -4px oklch(0.5 0.2 288/.7);
}

.fb-25__fab:focus-visible {
  outline: 3px solid var(--fb-25-b);
  outline-offset: 3px;
}

.fb-25__fab--sm {
  --fb-25-size: 48px;
}

.fb-25__fab--lg {
  --fb-25-size: 64px;
}

.fb-25__fab--alt {
  --fb-25-a: oklch(0.82 0.16 90);
  --fb-25-b: oklch(0.6 0.18 35);
  color: oklch(0.2 0.05 45);
  box-shadow: 0 10px 24px -10px oklch(0.6 0.18 35/.7),0 2px 5px oklch(0.4 0.1 45/.22);
}

.fb-25__fab--alt:hover {
  box-shadow: 0 16px 36px -10px oklch(0.6 0.18 35/.8);
}

.fb-25__fab--out {
  background: oklch(1 0 0);
  color: var(--fb-25-b);
  box-shadow: 0 10px 24px -14px oklch(0.5 0.2 288/.7),inset 0 0 0 2px color-mix(in oklch,var(--fb-25-b) 55%,transparent);
}

.fb-25__fab--out:hover {
  background: color-mix(in oklch,var(--fb-25-b) 8%,oklch(1 0 0));
  box-shadow: 0 16px 34px -14px oklch(0.5 0.2 288/.8),inset 0 0 0 2px var(--fb-25-b);
}

.fb-25__states {
  display: flex;
  flex-wrap: wrap;
  gap: 14px;
  justify-content: center;
  font-family: ui-monospace,Menlo,Consolas,monospace;
  font-size: 11px;
  color: var(--fb-25-mut);
}

.fb-25__states span {
  display: flex;
  align-items: center;
  gap: 7px;
}

.fb-25__sw {
  width: 26px;
  height: 26px;
  border-radius: 50%;
  background: linear-gradient(150deg,var(--fb-25-a),var(--fb-25-b));
}

.fb-25__sw--rest {
  box-shadow: 0 6px 14px -6px oklch(0.5 0.2 288/.75);
}

.fb-25__sw--hov {
  box-shadow: 0 10px 22px -6px oklch(0.5 0.2 288/.85);
  translate: 0 -2px;
}

.fb-25__sw--act {
  box-shadow: 0 2px 6px -2px oklch(0.5 0.2 288/.7);
  scale: .94;
}

.fb-25__chip {
  font-family: ui-monospace,Menlo,Consolas,monospace;
  font-size: 11px;
  color: var(--fb-25-mut);
  padding: 8px 14px;
  border: 1px solid oklch(0.23 0.03 300/.14);
  border-radius: 99px;
}

@media (prefers-reduced-motion: reduce) {
  .fb-25__fab {
    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 Floating Button 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: Classic Gradient Circle Plus FAB CSS
Source: https://codefronts.com/components/css-floating-buttons/fb01/

The one everybody needs first: a round gradient FAB with a plus, done to a standard you can ship. The plus is drawn with two pseudo-elements rather than an icon file, so it rotates into an X, scales with the button and inherits colour. Two rules of CSS, three states, and a shadow that changes with elevation instead of staying flat.
## HTML
```html
<section class="fb-25" aria-label="Classic gradient circle plus floating action button demo">
  <div class="fb-25__stage">
    <p class="fb-25__eyebrow">pseudo-element icon · elevation states</p>
    <h2 class="fb-25__title">The plus is two rectangles</h2>
    <p class="fb-25__sub">No icon file, no font, no flash of missing glyph. It inherits colour, scales with the button, and rotates into a close mark on hover.</p>
    <div class="fb-25__row">
      <div class="fb-25__cell"><button class="fb-25__fab fb-25__fab--sm" type="button" aria-label="Add item, compact"></button><span class="fb-25__cap">48</span></div>
      <div class="fb-25__cell"><button class="fb-25__fab" type="button" aria-label="Add item"></button><span class="fb-25__cap">56</span></div>
      <div class="fb-25__cell"><button class="fb-25__fab fb-25__fab--lg" type="button" aria-label="Add item, prominent"></button><span class="fb-25__cap">64</span></div>
      <div class="fb-25__cell"><button class="fb-25__fab fb-25__fab--alt" type="button" aria-label="Add item, alternate palette"></button><span class="fb-25__cap">alt</span></div>
      <div class="fb-25__cell"><button class="fb-25__fab fb-25__fab--out" type="button" aria-label="Add item, outlined"></button><span class="fb-25__cap">outline</span></div>
    </div>
    <div class="fb-25__states" aria-hidden="true">
      <span><i class="fb-25__sw fb-25__sw--rest"></i>rest · 10/24</span>
      <span><i class="fb-25__sw fb-25__sw--hov"></i>hover · 16/36 −2px</span>
      <span><i class="fb-25__sw fb-25__sw--act"></i>active · 4/10 ×0.94</span>
    </div>
    <p class="fb-25__chip">currentColor bars · 150° gradient · hue-matched shadow</p>
  </div>
</section>
```
## CSS
```css
.fb-25 {
  width: 100%;
  min-height: 100vh;
  min-height: 100svh;
  display: block;
  background: var(--fb-25-bg);
  --fb-25-bg: oklch(0.97 0.01 300);
  --fb-25-a: oklch(0.7 0.19 330);
  --fb-25-b: oklch(0.5 0.2 288);
  --fb-25-ink: oklch(0.23 0.03 300);
  --fb-25-mut: oklch(0.53 0.02 300);
  --fb-25-size: 56px;
  font-family: 'Segoe UI',system-ui,-apple-system,sans-serif;
  color: var(--fb-25-ink);
  display: grid;
  place-items: center;
  padding: clamp(20px,5vw,56px);
}

.fb-25 *,
.fb-25 *::before,
.fb-25 *::after {
  box-sizing: border-box;
  margin: 0;
  padding: 0;
}

.fb-25__stage {
  width: min(100%,58ch);
  display: grid;
  gap: clamp(18px,3vw,28px);
  justify-items: center;
  text-align: center;
}

.fb-25__eyebrow {
  font-family: ui-monospace,Menlo,Consolas,monospace;
  font-size: 11.5px;
  letter-spacing: .16em;
  text-transform: uppercase;
  color: var(--fb-25-b);
}

.fb-25__title {
  font-size: clamp(26px,4.6vw,44px);
  line-height: 1.05;
  letter-spacing: -.03em;
  font-weight: 700;
  text-wrap: balance;
}

.fb-25__sub {
  max-width: 50ch;
  font-size: clamp(13.5px,1.7vw,16.5px);
  line-height: 1.62;
  color: var(--fb-25-mut);
  text-wrap: pretty;
}

.fb-25__row {
  display: flex;
  flex-wrap: wrap;
  gap: clamp(16px,4vw,34px);
  justify-content: center;
  align-items: center;
}

.fb-25__cell {
  display: grid;
  gap: 10px;
  justify-items: center;
}

.fb-25__cap {
  font-family: ui-monospace,Menlo,Consolas,monospace;
  font-size: 11px;
  color: var(--fb-25-mut);
}

.fb-25__fab {
  position: relative;
  inline-size: var(--fb-25-size);
  block-size: var(--fb-25-size);
  border: 0;
  border-radius: 50%;
  cursor: pointer;
  color: oklch(0.99 0.01 330);
  background: linear-gradient(150deg,var(--fb-25-a),var(--fb-25-b));
  box-shadow: 0 10px 24px -10px oklch(0.5 0.2 288/.75),0 2px 5px oklch(0.4 0.12 300/.25);
  transition: transform .3s cubic-bezier(.2,1.25,.4,1),box-shadow .3s ease,rotate .34s cubic-bezier(.3,1.3,.4,1);
}

.fb-25__fab::before,
.fb-25__fab::after {
  content: "";
  position: absolute;
  left: 50%;
  top: 50%;
  inline-size: calc(var(--fb-25-size) * .4);
  block-size: 2.6px;
  translate: -50% -50%;
  border-radius: 2px;
  background: currentColor;
}

.fb-25__fab::after {
  rotate: 90deg;
}

.fb-25__fab:hover {
  rotate: 90deg;
  box-shadow: 0 16px 36px -10px oklch(0.5 0.2 288/.85),0 2px 5px oklch(0.4 0.12 300/.25);
  translate: 0 -2px;
}

.fb-25__fab:active {
  transform: scale(.94);
  box-shadow: 0 4px 10px -4px oklch(0.5 0.2 288/.7);
}

.fb-25__fab:focus-visible {
  outline: 3px solid var(--fb-25-b);
  outline-offset: 3px;
}

.fb-25__fab--sm {
  --fb-25-size: 48px;
}

.fb-25__fab--lg {
  --fb-25-size: 64px;
}

.fb-25__fab--alt {
  --fb-25-a: oklch(0.82 0.16 90);
  --fb-25-b: oklch(0.6 0.18 35);
  color: oklch(0.2 0.05 45);
  box-shadow: 0 10px 24px -10px oklch(0.6 0.18 35/.7),0 2px 5px oklch(0.4 0.1 45/.22);
}

.fb-25__fab--alt:hover {
  box-shadow: 0 16px 36px -10px oklch(0.6 0.18 35/.8);
}

.fb-25__fab--out {
  background: oklch(1 0 0);
  color: var(--fb-25-b);
  box-shadow: 0 10px 24px -14px oklch(0.5 0.2 288/.7),inset 0 0 0 2px color-mix(in oklch,var(--fb-25-b) 55%,transparent);
}

.fb-25__fab--out:hover {
  background: color-mix(in oklch,var(--fb-25-b) 8%,oklch(1 0 0));
  box-shadow: 0 16px 34px -14px oklch(0.5 0.2 288/.8),inset 0 0 0 2px var(--fb-25-b);
}

.fb-25__states {
  display: flex;
  flex-wrap: wrap;
  gap: 14px;
  justify-content: center;
  font-family: ui-monospace,Menlo,Consolas,monospace;
  font-size: 11px;
  color: var(--fb-25-mut);
}

.fb-25__states span {
  display: flex;
  align-items: center;
  gap: 7px;
}

.fb-25__sw {
  width: 26px;
  height: 26px;
  border-radius: 50%;
  background: linear-gradient(150deg,var(--fb-25-a),var(--fb-25-b));
}

.fb-25__sw--rest {
  box-shadow: 0 6px 14px -6px oklch(0.5 0.2 288/.75);
}

.fb-25__sw--hov {
  box-shadow: 0 10px 22px -6px oklch(0.5 0.2 288/.85);
  translate: 0 -2px;
}

.fb-25__sw--act {
  box-shadow: 0 2px 6px -2px oklch(0.5 0.2 288/.7);
  scale: .94;
}

.fb-25__chip {
  font-family: ui-monospace,Menlo,Consolas,monospace;
  font-size: 11px;
  color: var(--fb-25-mut);
  padding: 8px 14px;
  border: 1px solid oklch(0.23 0.03 300/.14);
  border-radius: 99px;
}

@media (prefers-reduced-motion: reduce) {
  .fb-25__fab {
    transition: none;
  }
}
```

How this works

No SVG, no icon font — the plus is the button's own pseudo-elements:

.fab::before, .fab::after{ content:""; position:absolute;
  background:currentColor; border-radius:2px;
  inline-size:var(--bar); block-size:2.5px; }        /* horizontal */
.fab::after{ rotate:90deg }                            /* vertical  */
.fab:hover{ rotate:90deg }                             /* whole icon spins */

Because both bars use currentColor and a size derived from a custom property, changing --fb-25-size scales the icon proportionally, and changing the text colour recolours it. That is three fewer files than the icon-font approach and it never suffers a flash of missing glyph.

The gradient runs at 150° rather than a flat vertical, so the highlight lands at the top-left where the implied light source is — matching the shadow below it. A vertical gradient with a bottom-heavy shadow is the most common giveaway of a rushed button.

Elevation is a state, not a constant: rest is a 2-shadow stack at 10/24px, hover lifts to 16/36px with a 2px translate, and active drops to 4/10px with a 0.94 scale. Buttons that keep one shadow through every state feel like images rather than controls.

Make it yours

  • Icon swap: any 24px SVG drops into the same button; keep the pseudo-element version for plus/close since it can rotate between them.
  • Sizes: 48px compact, 56px standard, 64px prominent. Update the bar length with the same token so the icon stays at 40% of the button.
  • Colour: the two gradient stops plus the shadow hue are the only theme values. Match the shadow to the darker stop, never to black.
  • Outlined variant: transparent background, 2px gradient border via a background-clip trick, coloured text — the secondary action next to this one.

Gotchas — read before shipping

  • A pseudo-element icon requires the button to be position:relative with the bars absolutely centred; forgetting the centring shifts the plus by a pixel and it looks broken at small sizes.
  • Gradients on very small buttons band visibly. Below ~40px use a solid colour or add a 2% noise overlay.
  • Do not put the rotation transition on the whole button if it has a shadow — the shadow rotates too. Rotate an inner wrapper or accept a symmetrical shadow.
  • Rounded buttons still need a focus outline. outline-offset:3px on a circle looks intentional; a clipped outline does not.

Browser support

ChromeSafariFirefoxEdge
114+17.5+121+114+

Floor set by oklch(), color-mix(), text-wrap as this demo is written. The core technique itself goes back further — Chrome 111+.

Everything here except the oklch() tokens has been supported since 2015. Substituting hex colours makes this demo work in effectively any browser in use.

Search CodeFronts

Loading…