20 CSS Hamburger Menus 02 / 20
Hamburger Menu with Morphing Icon Animations
An icon gallery showcasing three distinct morph personalities (bars→X, fold, pinch) with different spring/easing curves.
The code
<div class="chm-02">
<div class="chm-02__scene">
<div class="chm-02__aurora"></div>
<div class="chm-02__veil"></div>
<div class="chm-02__dock">
<div class="chm-02__morph" id="chm-02-ma"><svg viewBox="0 0 30 30"><line class="chm-02__a1" x1="3" y1="8" x2="27" y2="8"/><line class="chm-02__a2" x1="3" y1="15" x2="27" y2="15"/><line class="chm-02__a3" x1="3" y1="22" x2="27" y2="22"/></svg><span class="chm-02__tag">BARS → X</span></div>
<div class="chm-02__morph" id="chm-02-mb"><svg viewBox="0 0 30 30"><line class="chm-02__b1" x1="3" y1="8" x2="27" y2="8"/><line class="chm-02__b2" x1="3" y1="22" x2="27" y2="22"/><line class="chm-02__b3" x1="3" y1="15" x2="27" y2="15"/></svg><span class="chm-02__tag">FOLD</span></div>
<div class="chm-02__morph" id="chm-02-mc"><svg viewBox="0 0 30 30"><line class="chm-02__c1" x1="3" y1="15" x2="27" y2="15"/><line class="chm-02__c2" x1="3" y1="15" x2="27" y2="15" transform="translate(0,-7)"/><line class="chm-02__c3" x1="3" y1="15" x2="27" y2="15"/></svg><span class="chm-02__tag">PINCH</span></div>
</div>
<div class="chm-02__scrim" id="chm-02-scrim"></div>
<aside class="chm-02__drawer" id="chm-02-drawer">
<div class="chm-02__lbl">// MICRO-INTERACTIONS</div>
<nav>
<a href="#"><span>01</span>Overview</a>
<a href="#"><span>02</span>Motion Lab</a>
<a href="#"><span>03</span>Easing Curves</a>
<a href="#"><span>04</span>Showcase</a>
</nav>
</aside>
<div class="chm-02__stage">
<div class="chm-02__hero">
<h1>MORPH<br>STATE</h1>
<p>Tap any icon · three easing personalities</p>
</div>
</div>
<div class="chm-02__note">ANIMATED_ICONS // 2030</div>
</div>
</div> <div class="chm-02">
<div class="chm-02__scene">
<div class="chm-02__aurora"></div>
<div class="chm-02__veil"></div>
<div class="chm-02__dock">
<div class="chm-02__morph" id="chm-02-ma"><svg viewBox="0 0 30 30"><line class="chm-02__a1" x1="3" y1="8" x2="27" y2="8"/><line class="chm-02__a2" x1="3" y1="15" x2="27" y2="15"/><line class="chm-02__a3" x1="3" y1="22" x2="27" y2="22"/></svg><span class="chm-02__tag">BARS → X</span></div>
<div class="chm-02__morph" id="chm-02-mb"><svg viewBox="0 0 30 30"><line class="chm-02__b1" x1="3" y1="8" x2="27" y2="8"/><line class="chm-02__b2" x1="3" y1="22" x2="27" y2="22"/><line class="chm-02__b3" x1="3" y1="15" x2="27" y2="15"/></svg><span class="chm-02__tag">FOLD</span></div>
<div class="chm-02__morph" id="chm-02-mc"><svg viewBox="0 0 30 30"><line class="chm-02__c1" x1="3" y1="15" x2="27" y2="15"/><line class="chm-02__c2" x1="3" y1="15" x2="27" y2="15" transform="translate(0,-7)"/><line class="chm-02__c3" x1="3" y1="15" x2="27" y2="15"/></svg><span class="chm-02__tag">PINCH</span></div>
</div>
<div class="chm-02__scrim" id="chm-02-scrim"></div>
<aside class="chm-02__drawer" id="chm-02-drawer">
<div class="chm-02__lbl">// MICRO-INTERACTIONS</div>
<nav>
<a href="#"><span>01</span>Overview</a>
<a href="#"><span>02</span>Motion Lab</a>
<a href="#"><span>03</span>Easing Curves</a>
<a href="#"><span>04</span>Showcase</a>
</nav>
</aside>
<div class="chm-02__stage">
<div class="chm-02__hero">
<h1>MORPH<br>STATE</h1>
<p>Tap any icon · three easing personalities</p>
</div>
</div>
<div class="chm-02__note">ANIMATED_ICONS // 2030</div>
</div>
</div>@import url('https://fonts.googleapis.com/css2?family=Syne:[email protected]&family=JetBrains+Mono:wght@400;600&display=swap');
.chm-02, .chm-02 *, .chm-02 *::before, .chm-02 *::after {
box-sizing: border-box;
margin: 0;
padding: 0;
}
.chm-02{
--bg:#070b14;--bg2:#0d1424;--foam:#e8f4ff;--plasma:#7afcff;--magenta:#ff4ecd;--gold:#ffd166;
min-height:460px;display:grid;place-items:stretch;
font-family:'Syne',sans-serif;background:var(--bg);color:var(--foam);
position:relative;
}
.chm-02__scene{position:relative;width:100%;min-height:460px;height:100%;overflow:hidden}
.chm-02__aurora{position:absolute;inset:-20%;z-index:0;filter:blur(70px);opacity:.55;
background:
radial-gradient(40% 40% at 25% 30%,var(--plasma),transparent 70%),
radial-gradient(45% 45% at 75% 65%,var(--magenta),transparent 70%),
radial-gradient(35% 35% at 55% 20%,var(--gold),transparent 70%);
animation:chm-02-drift 16s ease-in-out infinite alternate;}
@keyframes chm-02-drift{to{transform:translate(4%,-4%) scale(1.12) rotate(8deg)}}
.chm-02__veil{position:absolute;inset:0;z-index:1;background:linear-gradient(180deg,rgba(7,11,20,.4),rgba(7,11,20,.85))}
.chm-02__stage{position:relative;z-index:2;min-height:460px;display:grid;place-items:center;text-align:center;padding:24px}
.chm-02__hero h1{font-size:clamp(2rem,7vw,5rem);font-weight:800;letter-spacing:-.03em;line-height:.92;
background:linear-gradient(120deg,var(--foam),var(--plasma) 60%,var(--magenta));-webkit-background-clip:text;background-clip:text;color:transparent}
.chm-02__hero p{font-family:'JetBrains Mono',monospace;margin-top:18px;font-size:11px;letter-spacing:.35em;text-transform:uppercase;color:rgba(232,244,255,.55)}
.chm-02__dock{position:absolute;top:24px;right:24px;z-index:50;display:flex;gap:10px}
.chm-02__morph{
width:54px;height:54px;border-radius:16px;cursor:pointer;
background:rgba(232,244,255,0.05);
border:1px solid rgba(232,244,255,0.12);
backdrop-filter:blur(12px);
display:grid;place-items:center;position:relative;
transition:transform .4s cubic-bezier(.34,1.56,.64,1),border-color .3s,background .3s;
}
.chm-02__morph:hover{transform:translateY(-3px);border-color:var(--plasma)}
.chm-02__morph.is-active{border-color:var(--magenta);background:rgba(255,78,205,0.08)}
.chm-02__morph svg{width:26px;height:26px;overflow:visible}
.chm-02__morph line, .chm-02__morph path{stroke:var(--foam);stroke-width:2.4;stroke-linecap:round;
transition:all .55s cubic-bezier(.68,-.4,.27,1.4);
/* transform-box: fill-box anchors transform-origin to the SHAPE's own
bounding box. Without it, transform-origin:center on an SVG <line>
resolves to the SVG viewport center (15,15) — which means lines at
y=8 and y=22 rotate around (15,15) instead of their own centers,
producing a scattered look instead of a clean bars→X morph. With
transform-box:fill-box, each line rotates around its own center,
and the translateY adjustments correctly carry it to the X-formation. */
transform-box: fill-box; transform-origin: center;}
#chm-02-ma.is-active .chm-02__a1{transform:translateY(7px) rotate(45deg)}
#chm-02-ma.is-active .chm-02__a2{opacity:0;transform:scaleX(0)}
#chm-02-ma.is-active .chm-02__a3{transform:translateY(-7px) rotate(-45deg)}
/* FOLD morph: top bar tilts down + bottom bar tilts up to meet at the
middle bar, forming a "<" / arrow / fold-back shape. With
transform-box:fill-box each line rotates around its own center, and
the translateY moves the rotated line vertically toward y=15. */
#chm-02-mb.is-active .chm-02__b1{transform:translateY(7px) rotate(-30deg) scaleX(.7)}
#chm-02-mb.is-active .chm-02__b2{transform:translateY(-7px) rotate(30deg) scaleX(.7)}
#chm-02-mb.is-active .chm-02__b3{transform:scaleX(.5)}
#chm-02-mc .chm-02__c1,#chm-02-mc .chm-02__c2,#chm-02-mc .chm-02__c3{stroke-dasharray:24;}
#chm-02-mc.is-active .chm-02__c1{transform:rotate(45deg)}
#chm-02-mc.is-active .chm-02__c3{transform:rotate(-45deg)}
#chm-02-mc.is-active .chm-02__c2{opacity:0}
.chm-02__tag{font-family:'JetBrains Mono',monospace;position:absolute;bottom:-18px;left:50%;transform:translateX(-50%);font-size:8px;letter-spacing:.2em;color:rgba(232,244,255,.4);white-space:nowrap}
.chm-02__drawer{position:absolute;top:0;right:0;height:100%;width:min(340px,86%);z-index:40;
background:linear-gradient(160deg,rgba(13,20,36,.9),rgba(7,11,20,.96));
backdrop-filter:blur(28px);border-left:1px solid rgba(122,252,255,0.18);
transform:translateX(110%);transition:transform .7s cubic-bezier(.16,1,.3,1);
padding:96px 32px 32px;display:flex;flex-direction:column}
.chm-02__drawer.is-open{transform:translateX(0)}
.chm-02__lbl{font-family:'JetBrains Mono',monospace;font-size:10px;letter-spacing:.4em;color:var(--plasma);margin-bottom:24px}
.chm-02__drawer nav a{display:flex;align-items:baseline;gap:12px;font-size:1.4rem;font-weight:700;color:var(--foam);text-decoration:none;padding:12px 0;border-bottom:1px solid rgba(232,244,255,0.07);transition:color .3s,padding-left .3s;opacity:0;transform:translateX(30px)}
.chm-02__drawer.is-open nav a{opacity:1;transform:translateX(0)}
.chm-02__drawer nav a:nth-child(1){transition:.5s .15s}
.chm-02__drawer nav a:nth-child(2){transition:.5s .22s}
.chm-02__drawer nav a:nth-child(3){transition:.5s .29s}
.chm-02__drawer nav a:nth-child(4){transition:.5s .36s}
.chm-02__drawer nav a span{font-family:'JetBrains Mono',monospace;font-size:.7rem;color:var(--magenta)}
.chm-02__drawer nav a:hover{color:var(--plasma);padding-left:8px}
.chm-02__scrim{position:absolute;inset:0;z-index:35;background:rgba(7,11,20,.5);opacity:0;pointer-events:none;transition:opacity .5s;backdrop-filter:blur(2px)}
.chm-02__scrim.is-show{opacity:1;pointer-events:auto}
.chm-02__note{font-family:'JetBrains Mono',monospace;position:absolute;bottom:18px;left:24px;z-index:5;font-size:10px;letter-spacing:.3em;color:rgba(232,244,255,.4)}
@media (prefers-reduced-motion: reduce){
.chm-02__aurora{animation:none !important}
.chm-02__morph,.chm-02__morph line,.chm-02__morph path,.chm-02__drawer,.chm-02__drawer nav a,.chm-02__scrim{transition:none !important}
} @import url('https://fonts.googleapis.com/css2?family=Syne:[email protected]&family=JetBrains+Mono:wght@400;600&display=swap');
.chm-02, .chm-02 *, .chm-02 *::before, .chm-02 *::after {
box-sizing: border-box;
margin: 0;
padding: 0;
}
.chm-02{
--bg:#070b14;--bg2:#0d1424;--foam:#e8f4ff;--plasma:#7afcff;--magenta:#ff4ecd;--gold:#ffd166;
min-height:460px;display:grid;place-items:stretch;
font-family:'Syne',sans-serif;background:var(--bg);color:var(--foam);
position:relative;
}
.chm-02__scene{position:relative;width:100%;min-height:460px;height:100%;overflow:hidden}
.chm-02__aurora{position:absolute;inset:-20%;z-index:0;filter:blur(70px);opacity:.55;
background:
radial-gradient(40% 40% at 25% 30%,var(--plasma),transparent 70%),
radial-gradient(45% 45% at 75% 65%,var(--magenta),transparent 70%),
radial-gradient(35% 35% at 55% 20%,var(--gold),transparent 70%);
animation:chm-02-drift 16s ease-in-out infinite alternate;}
@keyframes chm-02-drift{to{transform:translate(4%,-4%) scale(1.12) rotate(8deg)}}
.chm-02__veil{position:absolute;inset:0;z-index:1;background:linear-gradient(180deg,rgba(7,11,20,.4),rgba(7,11,20,.85))}
.chm-02__stage{position:relative;z-index:2;min-height:460px;display:grid;place-items:center;text-align:center;padding:24px}
.chm-02__hero h1{font-size:clamp(2rem,7vw,5rem);font-weight:800;letter-spacing:-.03em;line-height:.92;
background:linear-gradient(120deg,var(--foam),var(--plasma) 60%,var(--magenta));-webkit-background-clip:text;background-clip:text;color:transparent}
.chm-02__hero p{font-family:'JetBrains Mono',monospace;margin-top:18px;font-size:11px;letter-spacing:.35em;text-transform:uppercase;color:rgba(232,244,255,.55)}
.chm-02__dock{position:absolute;top:24px;right:24px;z-index:50;display:flex;gap:10px}
.chm-02__morph{
width:54px;height:54px;border-radius:16px;cursor:pointer;
background:rgba(232,244,255,0.05);
border:1px solid rgba(232,244,255,0.12);
backdrop-filter:blur(12px);
display:grid;place-items:center;position:relative;
transition:transform .4s cubic-bezier(.34,1.56,.64,1),border-color .3s,background .3s;
}
.chm-02__morph:hover{transform:translateY(-3px);border-color:var(--plasma)}
.chm-02__morph.is-active{border-color:var(--magenta);background:rgba(255,78,205,0.08)}
.chm-02__morph svg{width:26px;height:26px;overflow:visible}
.chm-02__morph line, .chm-02__morph path{stroke:var(--foam);stroke-width:2.4;stroke-linecap:round;
transition:all .55s cubic-bezier(.68,-.4,.27,1.4);
/* transform-box: fill-box anchors transform-origin to the SHAPE's own
bounding box. Without it, transform-origin:center on an SVG <line>
resolves to the SVG viewport center (15,15) — which means lines at
y=8 and y=22 rotate around (15,15) instead of their own centers,
producing a scattered look instead of a clean bars→X morph. With
transform-box:fill-box, each line rotates around its own center,
and the translateY adjustments correctly carry it to the X-formation. */
transform-box: fill-box; transform-origin: center;}
#chm-02-ma.is-active .chm-02__a1{transform:translateY(7px) rotate(45deg)}
#chm-02-ma.is-active .chm-02__a2{opacity:0;transform:scaleX(0)}
#chm-02-ma.is-active .chm-02__a3{transform:translateY(-7px) rotate(-45deg)}
/* FOLD morph: top bar tilts down + bottom bar tilts up to meet at the
middle bar, forming a "<" / arrow / fold-back shape. With
transform-box:fill-box each line rotates around its own center, and
the translateY moves the rotated line vertically toward y=15. */
#chm-02-mb.is-active .chm-02__b1{transform:translateY(7px) rotate(-30deg) scaleX(.7)}
#chm-02-mb.is-active .chm-02__b2{transform:translateY(-7px) rotate(30deg) scaleX(.7)}
#chm-02-mb.is-active .chm-02__b3{transform:scaleX(.5)}
#chm-02-mc .chm-02__c1,#chm-02-mc .chm-02__c2,#chm-02-mc .chm-02__c3{stroke-dasharray:24;}
#chm-02-mc.is-active .chm-02__c1{transform:rotate(45deg)}
#chm-02-mc.is-active .chm-02__c3{transform:rotate(-45deg)}
#chm-02-mc.is-active .chm-02__c2{opacity:0}
.chm-02__tag{font-family:'JetBrains Mono',monospace;position:absolute;bottom:-18px;left:50%;transform:translateX(-50%);font-size:8px;letter-spacing:.2em;color:rgba(232,244,255,.4);white-space:nowrap}
.chm-02__drawer{position:absolute;top:0;right:0;height:100%;width:min(340px,86%);z-index:40;
background:linear-gradient(160deg,rgba(13,20,36,.9),rgba(7,11,20,.96));
backdrop-filter:blur(28px);border-left:1px solid rgba(122,252,255,0.18);
transform:translateX(110%);transition:transform .7s cubic-bezier(.16,1,.3,1);
padding:96px 32px 32px;display:flex;flex-direction:column}
.chm-02__drawer.is-open{transform:translateX(0)}
.chm-02__lbl{font-family:'JetBrains Mono',monospace;font-size:10px;letter-spacing:.4em;color:var(--plasma);margin-bottom:24px}
.chm-02__drawer nav a{display:flex;align-items:baseline;gap:12px;font-size:1.4rem;font-weight:700;color:var(--foam);text-decoration:none;padding:12px 0;border-bottom:1px solid rgba(232,244,255,0.07);transition:color .3s,padding-left .3s;opacity:0;transform:translateX(30px)}
.chm-02__drawer.is-open nav a{opacity:1;transform:translateX(0)}
.chm-02__drawer nav a:nth-child(1){transition:.5s .15s}
.chm-02__drawer nav a:nth-child(2){transition:.5s .22s}
.chm-02__drawer nav a:nth-child(3){transition:.5s .29s}
.chm-02__drawer nav a:nth-child(4){transition:.5s .36s}
.chm-02__drawer nav a span{font-family:'JetBrains Mono',monospace;font-size:.7rem;color:var(--magenta)}
.chm-02__drawer nav a:hover{color:var(--plasma);padding-left:8px}
.chm-02__scrim{position:absolute;inset:0;z-index:35;background:rgba(7,11,20,.5);opacity:0;pointer-events:none;transition:opacity .5s;backdrop-filter:blur(2px)}
.chm-02__scrim.is-show{opacity:1;pointer-events:auto}
.chm-02__note{font-family:'JetBrains Mono',monospace;position:absolute;bottom:18px;left:24px;z-index:5;font-size:10px;letter-spacing:.3em;color:rgba(232,244,255,.4)}
@media (prefers-reduced-motion: reduce){
.chm-02__aurora{animation:none !important}
.chm-02__morph,.chm-02__morph line,.chm-02__morph path,.chm-02__drawer,.chm-02__drawer nav a,.chm-02__scrim{transition:none !important}
}(() => {
const root = document.querySelector('.chm-02');
if (!root) return;
const morphs = root.querySelectorAll('.chm-02__morph');
const drawer = root.querySelector('#chm-02-drawer');
const scrim = root.querySelector('#chm-02-scrim');
function closeAll(){
morphs.forEach(m => m.classList.remove('is-active'));
drawer.classList.remove('is-open');
scrim.classList.remove('is-show');
}
morphs.forEach(el => {
el.addEventListener('click', () => {
const wasActive = el.classList.contains('is-active');
morphs.forEach(m => m.classList.remove('is-active'));
if (wasActive) { closeAll(); return; }
el.classList.add('is-active');
drawer.classList.add('is-open');
scrim.classList.add('is-show');
});
});
scrim.addEventListener('click', closeAll);
})(); (() => {
const root = document.querySelector('.chm-02');
if (!root) return;
const morphs = root.querySelectorAll('.chm-02__morph');
const drawer = root.querySelector('#chm-02-drawer');
const scrim = root.querySelector('#chm-02-scrim');
function closeAll(){
morphs.forEach(m => m.classList.remove('is-active'));
drawer.classList.remove('is-open');
scrim.classList.remove('is-show');
}
morphs.forEach(el => {
el.addEventListener('click', () => {
const wasActive = el.classList.contains('is-active');
morphs.forEach(m => m.classList.remove('is-active'));
if (wasActive) { closeAll(); return; }
el.classList.add('is-active');
drawer.classList.add('is-open');
scrim.classList.add('is-show');
});
});
scrim.addEventListener('click', closeAll);
})();More from 20 CSS Hamburger Menus
Mobile Bottom Nav Bar with Floating HamburgerMulti-Level Dropdown Hamburger Menu (Nested Accordion)Flexbox Navbar with Right-Aligned Hamburger IconCircular Expand / Radial Ripple Mobile MenuFixed Sticky Header with Shrinking Hamburger IconNeumorphic Hamburger Menu Toggle ButtonBrutalist CSS Bordered Hamburger Menu3D Rotating Canvas Mobile Hamburger MenuPure CSS Hamburger Menu (No JavaScript)Bootstrap 5 Responsive Navbar with HamburgerCSS Slide Down Dropdown Hamburger MenuMinimalist 3-Line CSS Menu Icon with Hover Effects
View the full collection →