<!-- beloved hamburger button -->
<button aria-label="Toggle Navigation">
  <svg viewBox="-50 -40 100 80" width="50" height="40">
    <defs>
      <path id="line" fill="none" stroke="currentColor" stroke-width="15" stroke-linecap="round" d="M -40 0 h 80" />
    </defs>
    <g>
      <g class="translate" transform="translate(0 -30)">
        <g class="rotate" transform="rotate(-45)">
          <use transform="rotate(45)" href="#line" />
        </g>
      </g>

      <g class="rotate" transform="rotate(45)">
        <use transform="rotate(-45)" href="#line" />
      </g>

      <g class="translate" transform="translate(0 30)">
        <g class="rotate" transform="rotate(-45)">
          <use transform="rotate(45)" href="#line" />
        </g>
      </g>
    </g>
  </svg>
</button>

<!-- navigation wrapping text elements within anchor elements -->
<nav>
  <svg viewBox="0 0 500 400" width="500" height="400">
    <defs>
      <path id="path" d="M -150 60 q 50 -20 100 0 t 100 0 100 0 100 0 100 0 100 0 100 0 100 0" fill="none" />
    </defs>
    <g transform="translate(0 0)">
      <a href="#home">
        <text>
          <textPath text-anchor="middle" href="#path" startOffset="0%">
            Home
          </textPath>
        </text>
      </a>
    </g>
    <g transform="translate(0 100)">
      <a href="#about">
        <text>
          <textPath text-anchor="middle" href="#path" startOffset="100%">
            About
          </textPath>
        </text>
      </a>
    </g>
    <g transform="translate(0 200)">
      <a href="#contact">
        <text>
          <textPath text-anchor="middle" href="#path" startOffset="0%">
            Contact
          </textPath>
        </text>
      </a>
    </g>
    <g transform="translate(0 300)">
      <a href="#dance">
        <text>
          <textPath text-anchor="middle" href="#path" startOffset="100%">
            Dance
          </textPath>
        </text>
      </a>
    </g>
  </svg>
</nav>
@import url("https://fonts.googleapis.com/css?family=Chango&display=swap");

* {
  box-sizing: border-box;
  padding: 0;
  margin: 0;
}
body {
  background: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 40 30' opacity='0.2' width='80' height='60'%3E%3Cpath d='M 0 15 q 10 -7 20 0 t 20 0' fill='none' stroke='hsl(0, 0%25, 100%25)' stroke-linecap='round' stroke-width='2' /%3E%3C/svg%3E"), #fb1f34;
  color: hsl(0, 0%, 100%);
  background-position-x: 50%;
  background-size: 50px;
  /* center the navigation in the viewport */
  min-height: 100vh;
  display: flex;
  align-items: center;
  justify-content: center;
}
/* position the hamburger button in the top right corner */
button {
  position: absolute;
  top: 1rem;
  right: 1rem;
  width: 4rem;
  height: 4rem;
  background: none;
  border: none;
  color: inherit;
  padding: 0.5rem;
}
button:focus {
  outline-color: currentColor;
}
/* when the button is toggled to .open, update the group elements to toggle between the hamburger and x symbol */
button svg {
  width: 100%;
  height: auto;
  display: block;
  filter: drop-shadow(5px 5px hsl(0, 0%, 20%));
}
button .translate {
  transition: transform 0.25s ease-in-out;
  transition-delay: 0.25s;
}
button .rotate {
  transition: transform 0.25s ease-in-out;
  transition-delay: 0s;
}
button.open .translate {
  transform: translateY(0);
  transition-delay: 0s;
}
button.open .rotate {
  transform: rotate(0);
  transition-delay: 0.25s;
}
/* expand the nav to consider the entire height/width, whichever's smaller */
nav {
  width: 100vmin;
  visibility: hidden;
}
nav svg {
  width: 100%;
  height: auto;
  display: block;
}
nav svg text {
  text-shadow: 0px 0.2rem hsl(0, 0%, 20%);
  font-family: "Chango", cursive;
  fill: currentColor;
  font-size: 2.255rem;
  letter-spacing: 0px;
  transition-property: letter-spacing, text-shadow;
  transition-duration: 0.5s;
  transition-timing-function: cubic-bezier(0.68, -0.55, 0.265, 1.55);
}
/* on hover/focus update the style of the text */
nav svg a {
  color: inherit;
  outline: none;
}
nav svg a:hover text,
nav svg a:focus text {
  letter-spacing: 5px;
  text-shadow: 0px 0.5rem hsl(0, 0%, 20%);
}
const button = document.querySelector('button');
const nav = document.querySelector('nav');

// toggle a class of open on the button and nav element
button.addEventListener('click', () => {
  nav.classList.toggle('open');
  button.classList.toggle('open');
  const isOpen = nav.classList.contains('open');

  // animate the text path to move in/out
  anime({
    targets: 'textPath',
    startOffset: (d, i) => {
      if (isOpen) {
        return i % 2 === 0 ? '60%' : '40%';
      }
      return i % 2 === 0 ? '0%' : '100%';
    },
    duration: 2500,
    // slight delay for the opening animation, to follow the hamburger menu
    delay: isOpen ? 200 + anime.stagger(50) : anime.stagger(50),
    // considering the class on the nav element, toggle its visibility to prevent focus events
    begin: () => {
      if (nav.classList.contains('open')) {
        nav.style.visibility = 'visible';
      }
    },
    complete: () => {
      if (!nav.classList.contains('open')) {
        nav.style.visibility = 'hidden';
      }
    },
  });
});

External CSS

This Pen doesn't use any external CSS resources.

External JavaScript

  1. https://unpkg.com/[email protected]/lib/anime.js