32 CSS Floating Action Button Designs 02 / 32

Speed Dial FAB Menu

CSS-only speed dial radial FAB menu using checkbox hack with vertical and horizontal expansion variants.

Pure CSS MIT licensed
Live Demo Open in tab
Open in playground

The code

<div class="fb02">
<h1>Speed Dial FAB Menu</h1>
<p class="fb02-sub">Pure CSS radial floating action button menu — checkbox hack, zero JavaScript, staggered reveal animation.</p>

<div class="fb02-demos">

  <!-- Demo 1: Vertical speed dial -->
  <div class="fb02-demo-well">
    <span class="fb02-demo-well-label">Vertical · checkbox hack</span>

    <div class="fb02-speed-dial">
      <!-- scrim -->
      <label class="fb02-sd-scrim" for="fb02-sd1"></label>

      <input type="checkbox" class="fb02-sd-check" id="fb02-sd1">

      <div class="fb02-sd-actions">
        <div class="fb02-sd-item">
          <span class="fb02-sd-item-lbl">Share link</span>
          <button class="fb02-sd-btn fb02-sd-btn--share" aria-label="Share">
            <svg viewBox="0 0 24 24"><path d="M18 16.08c-.76 0-1.44.3-1.96.77L8.91 12.7c.05-.23.09-.46.09-.7s-.04-.47-.09-.7l7.05-4.11A3 3 0 0021 5a3 3 0 00-3-3 3 3 0 00-3 3c0 .24.04.47.09.7L8.04 9.81A3 3 0 005 9a3 3 0 00-3 3 3 3 0 003 3 3 3 0 003.04-.81l7.12 4.16c-.05.21-.08.43-.08.65 0 1.61 1.31 2.92 2.92 2.92 1.61 0 2.92-1.31 2.92-2.92S19.61 16.08 18 16.08z"/></svg>
          </button>
        </div>
        <div class="fb02-sd-item">
          <span class="fb02-sd-item-lbl">Take photo</span>
          <button class="fb02-sd-btn fb02-sd-btn--camera" aria-label="Camera">
            <svg viewBox="0 0 24 24"><path d="M12 15.2A3.2 3.2 0 018.8 12 3.2 3.2 0 0112 8.8a3.2 3.2 0 013.2 3.2A3.2 3.2 0 0112 15.2m0-8.2a5 5 0 00-5 5 5 5 0 005 5 5 5 0 005-5 5 5 0 00-5-5m6.5-8H5.5A2.5 2.5 0 003 1.5V18a2.5 2.5 0 002.5 2.5h13A2.5 2.5 0 0021 18V1.5A2.5 2.5 0 0018.5-1zM9 3l.83-1H14.2L15 3H9z"/></svg>
          </button>
        </div>
        <div class="fb02-sd-item">
          <span class="fb02-sd-item-lbl">Upload photo</span>
          <button class="fb02-sd-btn fb02-sd-btn--photo" aria-label="Photo">
            <svg viewBox="0 0 24 24"><path d="M21 19V5c0-1.1-.9-2-2-2H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2zM8.5 13.5l2.5 3.01L14.5 12l4.5 6H5l3.5-4.5z"/></svg>
          </button>
        </div>
        <div class="fb02-sd-item">
          <span class="fb02-sd-item-lbl">New document</span>
          <button class="fb02-sd-btn fb02-sd-btn--doc" aria-label="Document">
            <svg viewBox="0 0 24 24"><path d="M14 2H6a2 2 0 00-2 2v16a2 2 0 002 2h12a2 2 0 002-2V8l-6-6zm4 18H6V4h7v5h5v11z"/></svg>
          </button>
        </div>
      </div>

      <label class="fb02-sd-trigger" for="fb02-sd1" aria-label="Toggle actions">
        <span class="fb02-icon-wrap">
          <span class="fb02-icon-bar"></span>
        </span>
      </label>
    </div>
  </div>

  <!-- Demo 2: Horizontal speed dial -->
  <div class="fb02-demo-well">
    <span class="fb02-demo-well-label">Horizontal · slide-in</span>

    <div class="fb02-speed-dial fb02-speed-dial--h">
      <input type="checkbox" class="fb02-sd-check fb02-sd-check--h" id="fb02-sd2">

      <div class="fb02-sd-actions fb02-sd-actions--h">
        <div class="fb02-sd-item">
          <button class="fb02-sd-btn fb02-sd-btn--share" aria-label="Share">
            <svg viewBox="0 0 24 24"><path d="M18 16.08c-.76 0-1.44.3-1.96.77L8.91 12.7c.05-.23.09-.46.09-.7s-.04-.47-.09-.7l7.05-4.11A3 3 0 0021 5a3 3 0 00-3-3 3 3 0 00-3 3c0 .24.04.47.09.7L8.04 9.81A3 3 0 005 9a3 3 0 00-3 3 3 3 0 003 3 3 3 0 003.04-.81l7.12 4.16c-.05.21-.08.43-.08.65 0 1.61 1.31 2.92 2.92 2.92 1.61 0 2.92-1.31 2.92-2.92S19.61 16.08 18 16.08z"/></svg>
          </button>
          <span class="fb02-sd-item-lbl">Share</span>
        </div>
        <div class="fb02-sd-item">
          <button class="fb02-sd-btn fb02-sd-btn--camera" aria-label="Camera">
            <svg viewBox="0 0 24 24"><path d="M12 15.2A3.2 3.2 0 018.8 12 3.2 3.2 0 0112 8.8a3.2 3.2 0 013.2 3.2A3.2 3.2 0 0112 15.2m0-8.2a5 5 0 00-5 5 5 5 0 005 5 5 5 0 005-5 5 5 0 00-5-5m6.5-8H5.5A2.5 2.5 0 003 1.5V18a2.5 2.5 0 002.5 2.5h13A2.5 2.5 0 0021 18V1.5A2.5 2.5 0 0018.5-1zM9 3l.83-1H14.2L15 3H9z"/></svg>
          </button>
          <span class="fb02-sd-item-lbl">Camera</span>
        </div>
        <div class="fb02-sd-item">
          <button class="fb02-sd-btn fb02-sd-btn--doc" aria-label="Document">
            <svg viewBox="0 0 24 24"><path d="M14 2H6a2 2 0 00-2 2v16a2 2 0 002 2h12a2 2 0 002-2V8l-6-6zm4 18H6V4h7v5h5v11z"/></svg>
          </button>
          <span class="fb02-sd-item-lbl">Doc</span>
        </div>
      </div>

      <label class="fb02-sd-trigger fb02-sd-trigger--h" for="fb02-sd2" aria-label="Toggle actions">
        <svg viewBox="0 0 24 24"><path d="M19 11h-6V5h-2v6H5v2h6v6h2v-6h6z"/></svg>
      </label>
    </div>
  </div>

</div>
</div>
.fb02, .fb02 *, .fb02 *::before, .fb02 *::after { box-sizing: border-box; margin: 0; padding: 0; }
.fb02 {
    font-family: 'Space Grotesk', sans-serif;
    background: #09090b;
    min-height: 100vh;
    display: grid;
    place-items: center;
    padding: 40px 20px;
    color: #e4e4e7;
  }

  h1 {
    font-size: clamp(1.6rem, 5vw, 2.6rem);
    font-weight: 700;
    text-align: center;
    letter-spacing: -.02em;
    color: #fafafa;
    margin-bottom: 8px;
  }
  p.fb02-sub {
    text-align: center;
    color: #52525b;
    font-size: .9rem;
    max-width: 40ch;
    margin: 0 auto 48px;
    line-height: 1.6;
  }

  /* ── page layout ── */
  .fb02-demos {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
    gap: 24px;
    width: min(900px, 100%);
  }

  .fb02-demo-well {
    background: #141417;
    border: 1px solid #27272a;
    border-radius: 20px;
    height: 380px;
    position: relative;
    overflow: hidden;
    display: flex;
    align-items: flex-end;
    justify-content: flex-end;
    padding: 28px;
  }
  .fb02-demo-well-label {
    position: absolute;
    top: 16px;
    left: 20px;
    font-size: .72rem;
    letter-spacing: .1em;
    text-transform: uppercase;
    color: #3f3f46;
    font-weight: 600;
  }

  /* ── SPEED DIAL (vertical, checkbox hack) ── */
  .fb02-speed-dial {
    position: relative;
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 0;
  }

  /* hidden checkbox */
  .fb02-sd-check { position: absolute; opacity: 0; pointer-events: none; width: 0; height: 0; }

  /* action items — hidden by default */
  .fb02-sd-actions {
    display: flex;
    flex-direction: column-reverse;
    align-items: center;
    gap: 14px;
    margin-bottom: 16px;
    pointer-events: none;
  }

  .fb02-sd-item {
    display: flex;
    align-items: center;
    gap: 10px;
    opacity: 0;
    transform: translateY(16px) scale(.85);
    transition: opacity .22s ease, transform .22s cubic-bezier(.34,1.56,.64,1);
    pointer-events: none;
    flex-direction: row-reverse;
  }

  /* labels */
  .fb02-sd-item-lbl {
    font-size: .78rem;
    font-weight: 600;
    color: #a1a1aa;
    background: #1f1f23;
    border: 1px solid #3f3f46;
    border-radius: 6px;
    padding: 4px 10px;
    white-space: nowrap;
  }

  /* mini sub-button */
  .fb02-sd-btn {
    width: 46px;
    height: 46px;
    border-radius: 50%;
    border: none;
    display: grid;
    place-items: center;
    cursor: pointer;
    box-shadow: 0 4px 14px rgba(0,0,0,.45);
    transition: transform .15s ease, box-shadow .15s ease;
  }
  .fb02-sd-btn:hover { transform: scale(1.1); }
  .fb02-sd-btn svg { width: 20px; height: 20px; fill: #fff; }

  .fb02-sd-btn--share  { background: linear-gradient(135deg, #6366f1, #8b5cf6); }
  .fb02-sd-btn--camera { background: linear-gradient(135deg, #06b6d4, #0ea5e9); }
  .fb02-sd-btn--photo  { background: linear-gradient(135deg, #f43f5e, #e11d48); }
  .fb02-sd-btn--doc    { background: linear-gradient(135deg, #f59e0b, #d97706); }

  /* staggered reveal when checked */
  .fb02-sd-check:checked ~ .fb02-sd-actions { pointer-events: auto; }
  .fb02-sd-check:checked ~ .fb02-sd-actions .fb02-sd-item:nth-child(1) { opacity: 1; transform: none; transition-delay: .00s; pointer-events: auto; }
  .fb02-sd-check:checked ~ .fb02-sd-actions .fb02-sd-item:nth-child(2) { opacity: 1; transform: none; transition-delay: .06s; pointer-events: auto; }
  .fb02-sd-check:checked ~ .fb02-sd-actions .fb02-sd-item:nth-child(3) { opacity: 1; transform: none; transition-delay: .12s; pointer-events: auto; }
  .fb02-sd-check:checked ~ .fb02-sd-actions .fb02-sd-item:nth-child(4) { opacity: 1; transform: none; transition-delay: .18s; pointer-events: auto; }

  /* main trigger */
  .fb02-sd-trigger {
    width: 60px;
    height: 60px;
    border-radius: 50%;
    background: linear-gradient(135deg, #6366f1 0%, #8b5cf6 100%);
    border: none;
    cursor: pointer;
    display: grid;
    place-items: center;
    box-shadow: 0 6px 20px rgba(99,102,241,.45), inset 0 1px 0 rgba(255,255,255,.18);
    transition: transform .28s cubic-bezier(.34,1.56,.64,1), box-shadow .22s ease;
    position: relative;
  }
  .fb02-sd-trigger:hover { box-shadow: 0 10px 28px rgba(99,102,241,.6), inset 0 1px 0 rgba(255,255,255,.22); }

  /* plus → × morph */
  .fb02-sd-trigger .fb02-icon-wrap {
    position: relative;
    width: 24px;
    height: 24px;
  }
  .fb02-sd-trigger .fb02-icon-wrap::before,
  .fb02-sd-trigger .fb02-icon-wrap::after {
    content: '';
    position: absolute;
    inset: 50% 0;
    height: 2.5px;
    background: #fff;
    border-radius: 2px;
    margin-top: -1.25px;
    transition: transform .28s cubic-bezier(.34,1.56,.64,1);
  }
  .fb02-sd-trigger .fb02-icon-wrap::before { transform: rotate(0deg); }
  .fb02-sd-trigger .fb02-icon-wrap::after  { transform: rotate(90deg); }

  /* vertical bar of the plus */
  .fb02-sd-trigger .fb02-icon-bar {
    position: absolute;
    top: 0; bottom: 0;
    left: 50%;
    width: 2.5px;
    background: #fff;
    border-radius: 2px;
    margin-left: -1.25px;
    transition: transform .28s cubic-bezier(.34,1.56,.64,1), opacity .2s;
  }

  .fb02-sd-check:checked ~ .fb02-sd-trigger .fb02-icon-wrap::before { transform: rotate(45deg); }
  .fb02-sd-check:checked ~ .fb02-sd-trigger .fb02-icon-wrap::after  { transform: rotate(-45deg); }
  .fb02-sd-check:checked ~ .fb02-sd-trigger .fb02-icon-bar { opacity: 0; }
  .fb02-sd-check:checked ~ .fb02-sd-trigger { transform: rotate(45deg); box-shadow: 0 8px 24px rgba(99,102,241,.5), inset 0 1px 0 rgba(255,255,255,.18); }

  /* overlay scrim (optional) */
  .fb02-sd-scrim {
    position: absolute;
    inset: 0;
    background: rgba(0,0,0,0);
    pointer-events: none;
    transition: background .3s;
    border-radius: 20px;
  }
  .fb02-sd-check:checked ~ .fb02-sd-scrim { background: rgba(0,0,0,.4); pointer-events: auto; }

  /* ── HORIZONTAL speed dial ── */
  .fb02-speed-dial--h {
    flex-direction: row;
    align-items: center;
  }
  .fb02-speed-dial--h .fb02-sd-actions {
    flex-direction: row;
    margin-bottom: 0;
    margin-right: 14px;
  }
  .fb02-speed-dial--h .fb02-sd-item {
    flex-direction: column;
    gap: 8px;
    transform: translateX(20px) scale(.85);
  }
  .fb02-sd-check--h:checked ~ .fb02-sd-actions--h { pointer-events: auto; }
  .fb02-sd-check--h:checked ~ .fb02-sd-actions--h .fb02-sd-item:nth-child(1) { opacity: 1; transform: none; transition-delay: .00s; pointer-events: auto; }
  .fb02-sd-check--h:checked ~ .fb02-sd-actions--h .fb02-sd-item:nth-child(2) { opacity: 1; transform: none; transition-delay: .07s; pointer-events: auto; }
  .fb02-sd-check--h:checked ~ .fb02-sd-actions--h .fb02-sd-item:nth-child(3) { opacity: 1; transform: none; transition-delay: .14s; pointer-events: auto; }
  .fb02-sd-check--h:checked ~ .fb02-sd-trigger--h { transform: rotate(45deg); }

  .fb02-sd-trigger--h {
    width: 60px; height: 60px; border-radius: 50%;
    background: linear-gradient(135deg, #f43f5e, #fb7185);
    border: none; cursor: pointer; display: grid; place-items: center;
    box-shadow: 0 6px 20px rgba(244,63,94,.4), inset 0 1px 0 rgba(255,255,255,.18);
    transition: transform .28s cubic-bezier(.34,1.56,.64,1);
    flex-shrink: 0;
  }
  .fb02-sd-trigger--h svg { width: 26px; height: 26px; fill: #fff; transition: transform .28s cubic-bezier(.34,1.56,.64,1); }

  @media (prefers-reduced-motion: reduce) {
    .fb02-sd-item, .fb02-sd-trigger, .fb02-sd-trigger--h { transition: none; }
  }

Search CodeFronts

Loading…