20 CSS Hamburger Menus 16 / 20

Circular Expand / Radial Ripple Mobile Menu

A floating circular button whose clip-path: circle() grows outward like an expanding bubble from the corner, with spring easing and sliding links.

CSS + JS MIT licensed
Live Demo Open in tab
Open in playground

The code

<div class="chm-16">
  <div class="chm-16__scene">
    <div class="chm-16__bg"></div>

    <div class="chm-16__ripple">
      <div class="chm-16__lbl">// radial reveal</div>
      <a href="#">Home</a>
      <a href="#">Drops</a>
      <a href="#">Lookbook</a>
      <a href="#">Contact</a>
    </div>

    <button class="chm-16__fab" aria-label="Toggle radial menu"><span class="chm-16__b"><i></i><i></i><i></i></span></button>

    <div class="chm-16__stage">
      <div class="chm-16__hero">
        <h1>Pop the<br><em>bubble.</em></h1>
        <p>clip-path circle expands from the button</p>
      </div>
    </div>
    <div class="chm-16__tag">RADIAL_RIPPLE // 2030</div>
  </div>
</div>
@import url('https://fonts.googleapis.com/css2?family=Familjen+Grotesk:wght@400;500;700&family=Martian+Mono:wght@400;500&display=swap');
.chm-16, .chm-16 *, .chm-16 *::before, .chm-16 *::after { box-sizing: border-box; margin: 0; padding: 0; }
.chm-16{
  --bg:#0b0a14;--bubble:#ff3e6c;--bubble2:#7c3aff;--mint:#2ff5c8;--fog:#f3f0ff;
  min-height:460px;display:grid;place-items:stretch;
  font-family:'Familjen Grotesk',sans-serif;background:var(--bg);color:var(--fog);
  position:relative;
}
.chm-16__scene{position:relative;width:100%;min-height:460px;height:100%;overflow:hidden}
.chm-16__bg{position:absolute;inset:0;background:radial-gradient(40% 40% at 18% 82%,rgba(124,58,255,.2),transparent 60%),radial-gradient(40% 40% at 82% 20%,rgba(47,245,200,.14),transparent 60%)}
.chm-16__stage{position:relative;z-index:2;min-height:460px;display:grid;place-items:center;text-align:center;padding:24px}
.chm-16__hero h1{font-size:clamp(2rem,7vw,4.4rem);font-weight:700;letter-spacing:-.03em;line-height:.92}
.chm-16__hero h1 em{font-style:normal;color:var(--bubble)}
.chm-16__hero p{font-family:'Martian Mono',monospace;margin-top:14px;font-size:10px;letter-spacing:.25em;text-transform:uppercase;color:rgba(243,240,255,.55)}
.chm-16__fab{position:absolute;bottom:26px;right:26px;z-index:60;width:60px;height:60px;border-radius:50%;cursor:pointer;border:none;
  background:linear-gradient(140deg,var(--bubble),var(--bubble2));display:grid;place-items:center;
  box-shadow:0 14px 38px rgba(255,62,108,.5);transition:transform .5s cubic-bezier(.34,1.56,.64,1)}
.chm-16__fab:hover{transform:scale(1.08)}
.chm-16__b{width:22px;height:14px;position:relative;display:inline-block}
.chm-16__b i{position:absolute;left:0;height:2.6px;width:100%;background:#fff;border-radius:3px;transition:transform .5s cubic-bezier(.7,0,.2,1),opacity .3s}
.chm-16__b i:nth-child(1){top:0}.chm-16__b i:nth-child(2){top:6px}.chm-16__b i:nth-child(3){top:12px}
.chm-16.is-open .chm-16__fab{transform:scale(1.05) rotate(90deg)}
.chm-16.is-open .chm-16__b i:nth-child(1){transform:translateY(6px) rotate(45deg)}
.chm-16.is-open .chm-16__b i:nth-child(2){opacity:0}
.chm-16.is-open .chm-16__b i:nth-child(3){transform:translateY(-6px) rotate(-45deg)}
.chm-16__ripple{position:absolute;inset:0;z-index:50;
  background:radial-gradient(circle at bottom right,var(--bubble2),var(--bubble) 55%,#1c0f2e);
  -webkit-clip-path:circle(0px at calc(100% - 56px) calc(100% - 56px));
  clip-path:circle(0px at calc(100% - 56px) calc(100% - 56px));
  transition:clip-path .8s cubic-bezier(.76,0,.24,1),-webkit-clip-path .8s cubic-bezier(.76,0,.24,1);pointer-events:none;
  display:flex;flex-direction:column;justify-content:center;align-items:flex-start;padding:0 10%;gap:4px}
.chm-16.is-open .chm-16__ripple{-webkit-clip-path:circle(150% at calc(100% - 56px) calc(100% - 56px));clip-path:circle(150% at calc(100% - 56px) calc(100% - 56px));pointer-events:auto}
.chm-16__lbl{font-family:'Martian Mono',monospace;font-size:10px;letter-spacing:.4em;text-transform:uppercase;color:var(--mint);margin-bottom:22px;opacity:0;transition:.4s .4s}
.chm-16.is-open .chm-16__lbl{opacity:1}
.chm-16__ripple a{font-size:clamp(1.8rem,6vw,3.4rem);font-weight:700;color:#fff;text-decoration:none;line-height:1.1;letter-spacing:-.02em;transition:transform .3s,opacity .3s;opacity:0;transform:translateX(-40px)}
.chm-16.is-open .chm-16__ripple a{opacity:1;transform:none}
.chm-16.is-open .chm-16__ripple a:nth-child(2){transition:.5s .42s}
.chm-16.is-open .chm-16__ripple a:nth-child(3){transition:.5s .5s}
.chm-16.is-open .chm-16__ripple a:nth-child(4){transition:.5s .58s}
.chm-16.is-open .chm-16__ripple a:nth-child(5){transition:.5s .66s}
.chm-16__ripple a:hover{color:var(--mint)}
.chm-16__tag{position:absolute;bottom:18px;left:24px;z-index:5;font-family:'Martian Mono',monospace;font-size:10px;letter-spacing:.3em;color:rgba(243,240,255,.45)}

@media (prefers-reduced-motion: reduce){
  .chm-16__fab,.chm-16__b i,.chm-16__ripple,.chm-16__ripple a,.chm-16__lbl{transition:none !important}
}
(() => {
  const root = document.querySelector('.chm-16');
  if (!root) return;
  const btn = root.querySelector('.chm-16__fab');
  btn.addEventListener('click', () => root.classList.toggle('is-open'));
})();

Search CodeFronts

Loading…