<!-- ======= Header ======= -->
<header>
  <nav>
    <h1>Animated scroll menu</h1>

    <ul>
      <li><a data-page="home" href="#">Home</a></li>
      <li><a data-page="about" href="#">About</a></li>
      <li><a data-page="contact" href="#">Contact</a></li>
      <div class="bubble"></div>
    </ul>
  </nav>
</header>

<!-- ======= Main ======= -->
<main>
  <section data-index="0" class="home">
    <h2>Home</h2>
  </section>
  <section data-index="1" class="about">
    <h2>About</h2>
  </section>
  <section data-index="2" class="contact">
    <h2>Contact</h2>
  </section>
</main>
/*--------------------------------------------------------------
# General
--------------------------------------------------------------*/
:root {
  --bg-header: white;
  --header-color: black;
  --main-color: white;
  --shadow-color: rgba(0, 0, 0, 0.3);

  --home-gradient-color1: #56ab2f;
  --home-gradient-color2: #a8e063;
  --about-gradient-color1: #06beb6;
  --about-gradient-color2: #48b1bf;
  --contact-gradient-color1: #fc4a1a;
  --contact-gradient-color2: #f7b733;
}

* {
  margin: 0;
  padding: 0;
  box-sizing: border-box;
}

body {
  font-family: sans-serif;
}

/*--------------------------------------------------------------
# Header
--------------------------------------------------------------*/
header {
  box-shadow: 0px 3px 10px var(--shadow-color);
  position: sticky;
  top: 0px;
  background-color: var(--bg-header);
}

nav {
  min-height: 10vh;
  margin: auto;
  width: 90%;
  display: flex;
  align-items: center;
  justify-content: space-between;
}

nav h1,
nav ul {
  font-size: 1.5rem;
  flex: 1;
}

nav ul {
  list-style-type: none;
  display: flex;
  justify-content: space-between;
}

nav a {
  color: var(--header-color);
  text-decoration: none;
}

@media (max-width: 800px) {
  nav h1,
  nav ul {
    font-size: 0.6rem;
  }
}


/*--------------------------------------------------------------
# Main
--------------------------------------------------------------*/
section {
  min-height: 100vh;
  display: flex;
  justify-content: center;
  align-items: center;
}

section h2 {
  font-size: 5rem;
  color: var(--main-color);
}

.home {
  background: linear-gradient(
    to right top,
    var(--home-gradient-color1),
    var(--home-gradient-color2)
  );
}

.about {
  background: linear-gradient(
    to right top,
    var(--about-gradient-color1),
    var(--about-gradient-color2)
  );
}

.contact {
  background: linear-gradient(
    to right top,
    var(--contact-gradient-color1),
    var(--contact-gradient-color2)
  );
}

.bubble {
  position: absolute;
  z-index: -2;
  background: linear-gradient(
    to right top,
    var(--home-gradient-color1),
    var(--home-gradient-color2)
  );
  transform: scale(2);
  transition: all 0.5s ease;
}
const sections = document.querySelectorAll('section');
const bubble = document.querySelector('.bubble');
const gradients = [
  'linear-gradient(to right top, var(--home-gradient-color1), var(--home-gradient-color2))',
  'linear-gradient(to right top, var(--about-gradient-color1), var(--about-gradient-color2))',
  'linear-gradient(to right top, var(--contact-gradient-color1), var(--contact-gradient-color2))',
];

const navCheck = (entries) => {
  entries.forEach((entry) => {
    const { className } = entry.target;
    const activeAnchor = document.querySelector(`[data-page=${className}]`);
    const gradientIndex = entry.target.getAttribute('data-index');
    const coords = activeAnchor.getBoundingClientRect();
    const directions = {
      height: coords.height,
      width: coords.width,
      top: coords.top,
      left: coords.left,
    };

    if (entry.isIntersecting) {
      bubble.style.setProperty('left', `${directions.left}px`);
      bubble.style.setProperty('top', `${directions.top}px`);
      bubble.style.setProperty('width', `${directions.width}px`);
      bubble.style.setProperty('height', `${directions.height}px`);
      bubble.style.background = gradients[gradientIndex];
    }
  });
};

const options = {
  threshold: 0.7,
};

const observer = new IntersectionObserver(navCheck, options);

sections.forEach((section) => {
  observer.observe(section);
});

External CSS

This Pen doesn't use any external CSS resources.

External JavaScript

This Pen doesn't use any external JavaScript resources.