Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

ReactJS Change Navbar color based on scroll to section with dynamic height

I just started to use ReactJS. I currently want to change my Navbar color when user scroll to different section. For example, my section one is red and section 2 is green then my section 3 is blue. I want to let the Nav know that once User enter/scroll to section 1 and it will change color to make the color red and for section 2 and section 3 as well.

Right now I used the window.scroll to achieve this function.

const changeBackground = () => {
if(window.scrollY >= 898 && window.scrollY <= 1997){
  //section = '1'
  setColor('red')
}
else if(window.scrollY >= 1998 && window.scrollY <= 3097) {
  //section = '2'
  setColor('green')

}
else if(window.scrollY >= 3098) {
  //section = '3'
  setColor('blue')
}

My Current problem is that my height is fixed so section 1 is between 898 and 1997px. However I want to set the height to 100vh so that each section fill up the screen, and based the the 100vh, the px will be different depends on the user screen size.

Any thoughts/tips to let the nav know which section it is on right now?

Thanks so much! happy coding.

like image 457
Naoki Kokubyakuin Avatar asked Sep 06 '25 03:09

Naoki Kokubyakuin


1 Answers

One possible solution could be by using intersectional observers. They allow us to observe when an element is visible. We can set a threshold which would make sure that it only triggers when given ratio is visible.

You can use the react-intersection-observer hook to check if each section is in view, once they are you can use that state to change navigation bar color.

You can test this out in the following sandbox: https://codesandbox.io/s/competent-rubin-nhqz6

This code is not production ready, but you should be able to get an idea of how we can use the intersection observer.

import "./styles.css";
import React from "react";
import { useInView } from "react-intersection-observer";

export default function App() {
  const [section1Ref, section1InView] = useInView({ threshold: 0.5 });
  const [section2Ref, section2InView] = useInView({ threshold: 0.5 });

  return (
    <div className="App">
      <nav
        className="NavBar"
        style={{
          backgroundColor: section1InView
            ? "red"
            : section2InView
            ? "blue"
            : "green"
        }}
      />
      <div className="Container">
        <section className="Section" ref={section1Ref}>
          Section 1
        </section>
        <section className="Section" ref={section2Ref}>
          Section 2
        </section>
        <section className="Section">Section</section>
      </div>
    </div>
  );
}

Style sheet is simply setting the height to be 100vh minus the header height. And it's ensuring that the scroll works as expeted.

.NavBar {
  width: 100%;
  height: 20px;
  background-color: red;
}

.Container {
  height: calc(100vh - 20px);
  overflow-y: scroll;
}

.Section {
  height: calc(100vh - 20px);
  border-bottom: 2px solid black;
}
like image 89
nipuna777 Avatar answered Sep 09 '25 04:09

nipuna777