Scroll Animated Website

Web Development

In this JavaScript Tutorial you will create a website with scroll animation using HTML CSS and JavaScript Intersection Observer API.

The main object of this tutorial is to demonstrate how the intersection Observer API works

Getting started with the tutorial project

down below you can find the complete HTML for the project which you need to copy in your index.html file.

Just a quick NOTE!

I have added a navigation for demonstration purposes only, this part is not covert in this tutorial but in a previous one. Please fell free to check out the previous tutorial for more information.

Blog Post :

YouTube Video

Now lest got over our HTML file quickly.

After the navigation bar comes a section for the header, then multiple section tags witch all have the class=”hide”. This class will be targeted later using JS to toggle the section visible or not using the intersection observer API.

One of the section also containes a list of

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <link
      rel="stylesheet"
      href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.2.0/css/all.min.css"
      integrity="sha512-xh6O/CkQoPOWDdYTDqeRdPCVd1SpvCA9XXcUnZS2FmJNp1coAFzvtCN9BmamE+4aHK8yyUHUSCcJHgXloTyT2A=="
      crossorigin="anonymous"
      referrerpolicy="no-referrer"
    />
    <link rel="stylesheet" href="style.css" />
    <script defer src="animate.js"></script>
    <title>Scroll animated website</title>
  </head>
  <body>
    <!-- Navigation -->
    <nav id="main-nav" class="navbar bg-color">
      <div class="navbar-logo">
        <a class="navbar-brand" href="#">Navbar</a>
        <button class="btn navbar-toggler">
          <i class="nav-icon fa-solid fa-bars"></i>
        </button>
      </div>
      <div class="navbar-collapse">
        <ul class="navbar-nav me-auto">
          <li class="nav-item">
            <a class="nav-link active" href="#">Home</a>
          </li>
          <li class="nav-item">
            <a class="nav-link" href="#">About</a>
          </li>
          <li class="nav-item">
            <a class="nav-link" href="#">Contact</a>
          </li>
        </ul>
      </div>
    </nav>
    <!-- Header -->
    <section class="hide">
      <h1 class="title">
        Scroll <br />
        Animation
      </h1>
    </section>
    <section class="hide">
      <h2>Learn Web development</h2>
      <ul>
        <li class="hide"><i class="fa-brands fa-html5"></i></li>
        <li class="hide"><i class="fa-brands fa-css3-alt"></i></li>
        <li class="hide"><i class="fa-brands fa-js"></i></li>
      </ul>
      <p>
        Lorem ipsum dolor sit amet consectetur adipisicing elit. Illo possimus
        cupiditate ducimus eveniet in! Inventore iusto explicabo possimus rem
        deleniti illum quis expedita obcaecati incidunt. Quibusdam totam illum
        adipisci iusto.
      </p>
    </section>
    <section class="hide">
      <h2>Section 2</h2>
      <p>
        Lorem ipsum dolor sit amet consectetur adipisicing elit. Illo possimus
        cupiditate ducimus eveniet in! Inventore iusto explicabo possimus rem
        deleniti illum quis expedita obcaecati incidunt. Quibusdam totam illum
        adipisci iusto.
      </p>
    </section>
    <section class="hide">
      <h2>Section 3</h2>
      <p>
        Lorem ipsum dolor sit amet consectetur adipisicing elit. Illo possimus
        cupiditate ducimus eveniet in! Inventore iusto explicabo possimus rem
        deleniti illum quis expedita obcaecati incidunt. Quibusdam totam illum
        adipisci iusto.
      </p>
    </section>
    <section class="hide">
      <h2>Section 4</h2>
      <p>
        Lorem ipsum dolor sit amet consectetur adipisicing elit. Illo possimus
        cupiditate ducimus eveniet in! Inventore iusto explicabo possimus rem
        deleniti illum quis expedita obcaecati incidunt. Quibusdam totam illum
        adipisci iusto.
      </p>
    </section>
    <section class="hide">
      <h2>Section 5</h2>
      <p>
        Lorem ipsum dolor sit amet consectetur adipisicing elit. Illo possimus
        cupiditate ducimus eveniet in! Inventore iusto explicabo possimus rem
        deleniti illum quis expedita obcaecati incidunt. Quibusdam totam illum
        adipisci iusto.
      </p>
    </section>
    <section class="hide">
      <h2>Subscribe Like & Share</h2>
      <p>
        Lorem ipsum dolor sit amet consectetur adipisicing elit. Illo possimus
        cupiditate ducimus eveniet in! Inventore iusto explicabo possimus rem
        deleniti illum quis expedita obcaecati incidunt. Quibusdam totam illum
        adipisci iusto.
      </p>
    </section>
    <script src="nav.js"></script>
  </body>
</html>

Navigation CSS

/*Navigation*/

@import url("https://fonts.googleapis.com/css2?family=Aboreto&display=swap");
* {
  margin: 0;
  padding: 0;
  list-style: none;
  text-decoration: none;
  font-family: "Aboreto", cursive;
}
header {
  margin-top: 30vh;
}
.title {
  text-align: center;
  margin: 4rem 0;
  font-size: 6rem;
  text-shadow: 1px 3px 4px rgba(0, 0, 0, 0.45);
}
h2 {
  text-align: center;
  margin: 2rem 0;
  font-size: 3rem;
  text-shadow: 1px 3px 4px rgba(0, 0, 0, 0.45);
}
.navbar {
  display: flex;
  justify-content: center;
  align-items: center;
  background-color: #333;
  color: #eee;
  box-shadow: 0 2px 4px rgba(0, 0, 0, 0.3);
  justify-content: space-between;
  align-items: center;
  padding: 1rem;
  user-select: none;
}
.navbar-logo {
  width: 100%;
  display: flex;
  justify-content: center;
  align-items: center;
  justify-content: space-between;
  margin-right: 1rem;
  font-weight: 900;
}
.navbar-brand {
  margin-left: 1rem;
  color: inherit;
}

.btn {
  margin: 0.25rem 0.125rem;
  padding: 0.35rem 1.25rem;
  font-family: inherit;
  font-weight: 400;
  font-size: 1rem;
  letter-spacing: 0.6px;
  border-radius: 0.3rem;
  color: #fff;
  background-color: #000;
  border: none;
  box-shadow: 0 2px 5px rgba(51, 51, 51, 0.3);
  transition: 0.3s ease;
  transform: scale(0.8);
}
.btn:hover {
  cursor: pointer;
  box-shadow: none;
  transition: 0.3s ease;
  background: rgba(0, 0, 0, 0.75);
}

.navbar-toggler {
  display: none;
  margin-left: auto;
}
.navbar-nav {
  display: flex;
  justify-content: center;
  align-items: center;
}
@media screen and (max-width: 768px) {
  .navbar-toggler {
    display: block;
    margin-right: 1rem;
  }
  .navbar-nav {
    display: none;
  }
  .title {
    font-size: 3rem;
  }
}

/* @media screen and (max-width: 768px) {
} */
.navbar-nav .nav-item {
  margin-right: 1rem;
  transition: 0.3s ease-in-out;
}
.navbar-nav .nav-item:hover {
  text-shadow: 1px 3px 4px rgba(0, 0, 0, 0.45);
  transition: 0.3s ease-in-out;
}
.navbar-nav .nav-link {
  color: inherit;
}
.navbar-nav.showNavbar {
  display: flex;
  align-items: flex-start;
  flex-direction: column;
  gap: 15px;
  margin: 15px;
  width: 100%;
  animation: navFadeIn 0.4s ease-in-out;
}
.navbar.showNavbar {
  display: flex;
  align-items: flex-start;
  flex-direction: column;
}
@keyframes navFadeIn {
  0% {
    opacity: 0;
    transform: translateY(-30%);
  }
  100% {
    opacity: 1;

    transform: translateY(0);
  }
}
.fadeIn {
  animation: navFadeIn 0.4s ease-in-out;
}
.closeNav {
  animation: navFadeOut 0.4s ease-in-out;
}
@keyframes navFadeOut {
  0% {
    opacity: 1;
    transform: translateY(0);
  }
  100% {
    opacity: 0;
    transform: translateY(-30%);
  }
}
.nav-link.active {
  font-weight: 900;
  color: red;
}

Navigation JS

const navbar = document.querySelector(".navbar");

// resize the navigation

window.addEventListener("resize", () => {
  let WindowWidth = window.innerWidth;

  if (WindowWidth > 768) {
    navbarCollapse.classList.remove("showNavbar");
    navbar.classList.remove("showNavbar");
    if (navbarTogglerIcon.contains("fa-times")) {
      navbarTogglerIcon.remove("fa-times");
      navbarTogglerIcon.add("fa-bars");
    }
  }
});

const navbarToggler = document.querySelector(".navbar-toggler");
const navbarCollapse = document.querySelector(".navbar-nav");
let navbarTogglerIcon = navbarToggler.querySelector(".nav-icon").classList;

navbarToggler.addEventListener("click", function () {
  navbarCollapse.classList.toggle("showNavbar");
  navbar.classList.toggle("showNavbar");

  if (navbarTogglerIcon.contains("fa-bars")) {
    navbarTogglerIcon.remove("fa-bars");
    navbarTogglerIcon.add("fa-times");
  } else {
    navbarTogglerIcon.remove("fa-times");
    navbarTogglerIcon.add("fa-bars");
  }
});

const navLinks = document.querySelectorAll(".nav-link");

navLinks.forEach((navLink) =>
  navLink.addEventListener("click", function (e) {
    // remove .active from all nav links
    navLinks.forEach((navLink) => navLink.classList.remove("active"));
    // add .active to target element
    console.log(e.target);
    classToggler(e.target, "active");
  })
);

const title = document.querySelector(".title");

function classToggler(element, className) {
  if (element.classList.contains(className)) {
    element.classList.remove(className);
  } else {
    element.classList.add(className);
    title.innerHTML = element.innerHTML;
    title.classList.add("fadeIn");
    setTimeout(() => title.classList.remove("fadeIn"), 500);
  }
}

Sections CSS

/* Section  */
section {
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: center;
  min-height: 100vh;
  padding: 0 10vw;
}
.hide {
  opacity: 0;
  transition: all 2s ease-out;
  transform: translateX(-100%);
}
.animate-in {
  opacity: 1;
  transform: translateX(0);
}
section:nth-child(odd) {
  background-color: #333;
  color: #eee;
}
section ul {
  display: flex;
  margin-bottom: 2rem;
  font-size: 5rem;
  gap: 15vw;
}
section ul li:nth-child(1) {
  color: orangered;
  transition-delay: 1s;
}
section ul li:nth-child(2) {
  color: blue;
  transition-delay: 1.1s;
}
section ul li:nth-child(3) {
  color: yellow;
  transition-delay: 1.2s;
}

Scroll Animation Website using JavaScript

Now its time to use the Intersection Observer.

const observer = new IntersectionObserver((elements) =>
  elements.forEach((element) => {
    element.isIntersecting
      ? element.target.classList.add("animate-in")
      : element.target.classList.remove("animate-in");

    console.log(element);
  })
);

document
  .querySelectorAll(".hide")
  .forEach((animeEl) => observer.observe(animeEl));

What the complete project on YouTube

For more detailed information about the responsive navbar html css js project, check out the complete video tutorial on my YouTube channel.


Want to become a web developer ?

Love Podcast about web development?

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.