DEV Community

Cover image for Create Scroll sensitive navbar in ReactJs [functional component]
Tathagat
Tathagat

Posted on

Create Scroll sensitive navbar in ReactJs [functional component]

Hey peers,
I was surfing the web and had seen some of the website with navbar that show and hide itself based on user's scrolling behavior. This is pretty much the standard practice for the almost all the website UX nowadays, this certainly improves user's experience. Naturally I wanted to implement this on to my React project, But there was only one problem, I did not know how to do that, I searched on Google, YouTube, GitHub, DEV.to, stackoverflow and so on, but no success in getting straight forward answer.
This is post is for that, it is very simple, and I will tell you how to do this.

  1. Listen for scrolling event.
window.addEventListener("scroll", handleScroll, { passive: true });
Enter fullscreen mode Exit fullscreen mode
  1. Create a function that handles the event, at this point our work is almost done.
const handleScroll = () => {
      const currentScrollY = window.scrollY;
      if (scrollPosition < currentScrollY && goingUp) {
        setGoingUp(false);
      }
      if (scrollPosition > currentScrollY && !goingUp) {
        setGoingUp(true);
      }
      setScrollPosition(currentScrollY);
    };

Enter fullscreen mode Exit fullscreen mode
  1. Just make a CSS class which hide and shows the navbar (Give some transition effect for getting cool animation).

Finally, the wait is over and we have created a scroll-sensitive navbar in React.

code-

  1. AppNavbar.js
import { Link } from "react-scroll";
import { useEffect, useState } from "react";
import { Container } from "react-bootstrap";
import "./style.css";

const AppNavbar = () => {
  const [scrollPosition, setScrollPosition] = useState(0);
  const [goingUp, setGoingUp] = useState(true);
  useEffect(() => {
    const handleScroll = () => {
      const currentScrollY = window.scrollY;
      if (scrollPosition < currentScrollY && goingUp) {
        setGoingUp(false);
      }
      if (scrollPosition > currentScrollY && !goingUp) {
        setGoingUp(true);
      }
      setScrollPosition(currentScrollY);
    };
    window.addEventListener("scroll", handleScroll, { passive: true });
    return () => window.removeEventListener("scroll", handleScroll);
  }, [goingUp, scrollPosition]);

  return (
    <div className={`app-nav ${!goingUp ? `hide` : `show`}`}>
      <Container className='d-flex flex-row align-items-center'>
        <div className='logo'>
          <Link to='section-1' duration={600}>
            Logo
          </Link>
        </div>
        <div className='ms-auto'>
          <Link to='section-2' duration={600}>
            Details
          </Link>
        </div>
        <div>
          <Link to='section-3' duration={600}>
            Register
          </Link>
        </div>
        <div>
          <Link to='section-4' duration={600}>
            Contact Us
          </Link>
        </div>
      </Container>
    </div>
  );
};

export default AppNavbar;

Enter fullscreen mode Exit fullscreen mode

Please ignore react-scroll component (Link) if your requirement is not same as mine, you can replace it with tag of your choice.

2.style.scss

.app-nav {
  position: fixed;
  top: 0;
  right: 0;
  width: 100%;
  display: inline-flex;
  align-items: center;
  font-size: larger;
  background-color: rgba(46, 46, 46, 0);
  backdrop-filter: blur(20px);
  .logo {
    font-size: 2.5rem;
  }
  div {
    cursor: pointer;
    color: $accent-color;
    text-align: center;
    padding: 8px 16px;
  }
}

.hide {
  top: -100px;
  transition: ease 0.3s;
}
.show {
  top: 0px;
  transition: ease 0.3s;
}
Enter fullscreen mode Exit fullscreen mode

OUTPUT-

Final output

πŸ–οΈπŸ–οΈ BYE πŸ–οΈπŸ–οΈ

Top comments (2)

Collapse
 
lazylad profile image
Tathagat

Thanks, you have made some absolutely valid points, I'll definitely optimise the code for better performance. thanks for the feedback.

Collapse
 
jwachtel96 profile image
Jesse Wachtel

I'm a new developer. I appreciate this!