patbied
patbied

Reputation: 53

How to change navbar background color in react when I scroll

I would like to make my navbar start out as transparent but when a user scrolls the navbar will change color / background-color. I am using a bootstrap navbar and react.

jsx code:

import React, { Component } from 'react';
import '../css/nav.scss';
import { Link, NavLink } from 'react-router-dom';
import 'react-bootstrap';

class Navbar extends Component {
  state = {};

  render() {
    return (
      <nav className="navbar sticky-top navbar-expand-lg ">
        <NavLink
          to="/"
          class="navbar-brand"
          activeClassName="navbar-brand--active"
        >
          Web_Env
        </NavLink>
        <button
          class="navbar-toggler"
          type="button"
          data-toggle="collapse"
          data-target="#navbarNavDropdown"
          aria-controls="navbarNavDropdown"
          aria-expanded="false"
          aria-label="Toggle navigation"
        >
          <span class="navbar-toggler-icon"></span>
        </button>
        <div class="collapse navbar-collapse" id="navbarNavDropdown">
          <ul class="navbar-nav mr-auto">
            <li class="nav-item">
              <a class="nav-link" href="#">
                Create post
              </a>
            </li>
          </ul>
          <ul class="navbar-nav ml-auto">
            <li class="nav-item">
              <NavLink
                to="/login"
                className="nav-link"
                activeClassName="nav-link--active"
              >
                Login
              </NavLink>
            </li>
            <li className="nav-item">
              <NavLink
                to="/register"
                className="nav-link"
                activeClassName="nav-link--active"
              >
                Register
              </NavLink>
            </li>
          </ul>
        </div>
      </nav>
    );
  }
}

export default Navbar;


css code:

$color1: #aceca1;
$bgcolor1: #629460;
.navbar {
  background-color: $bgcolor1 !important;
  .navbar-brand {
    color: lighten($color1, 10%);
    font-weight: bold;
    font-size: 2em;
    .navbar-brand--active {
      color: white;
      font-weight: bold;
      font-size: 2em;
    }
  }

  .nav-link {
    color: $color1;
    font-size: 1.1em;
    transition: 200ms;
  }
  .nav-link--active {
    color: white !important;
    transform: scale(1.1);
    font-weight: 10px;
  }
  .nav-link:hover {
    color: white !important;
    transform: scale(1.1);
    text-decoration: none !important;
    font-weight: 10px;
  }
}

I have looked at a previous post about this from 2 years ago but being a beginner I didn't really understand any of it. If possible an explanations alongside the code would help me very much.

Upvotes: 3

Views: 22145

Answers (3)

Platinum
Platinum

Reputation: 98

In js

  useEffect(() => {
    document.addEventListener("scroll", () => {
      let header = document.querySelector('.Header');
      if (window.scrollY > 150) {
        header?.classList.add('scrolled');
      } else {
        header?.classList.remove('scrolled');
      }
    },[]);

In Css


.Header {
  /* How it will look before scrolled */
  position: fixed;
  background-color: #002241 !important;

  /* To give smoote change */
    -webkit-transition: all ease-out .5s;
  -moz-transition: all ease-out .5s;
  -o-transition: all ease-out .5s;
  transition: all ease-out .5s;
}
.Header.scrolled {
  /* How it will look when scrolled */
  background-color: #FFFFFF !important;
}

The header itself:

    <div className='Header'>
      The Header content
    </div>

Upvotes: 0

Amir Rezvani
Amir Rezvani

Reputation: 1504

Here is An Example: https://codesandbox.io/s/nifty-newton-f4j0j

you can use document.scrollingElement.scrollTop for detecting how much user scroll from top of the page. in this case 120 from top.

you put this into the componentDidMount and save this in a variable so u can remove this listener later in ComponentWillUnmount.

and because this listener fired up each time scroll occurs it is good for having a better performance we check the value of the state and updated it just when it's necessary.

this.listener = document.addEventListener("scroll", e => {
      var scrolled = document.scrollingElement.scrollTop;
      if (scrolled >= 120) {
        if (this.state.status !== "amir") this.setState({ status: "amir" })
      } else {
        if (this.state.status !== "top") this.setState({ status: "top" })
    }
 });

For anyone needs a solution using functional-based components

  let listener = null
  const [scrollState, setScrollState] = useState("top")

  useEffect(() => {
    listener = document.addEventListener("scroll", e => {
      var scrolled = document.scrollingElement.scrollTop
      if (scrolled >= 120) {
        if (scrollState !== "amir") setScrollState("amir")
      } else {
        if (scrollState !== "top") setScrollState("top")
      }
    })
    return () => {
      document.removeEventListener("scroll", listener)
    }
  }, [scrollState])

Upvotes: 12

Alex
Alex

Reputation: 3991

You should add something like this

componentDidMount() {
    document.addEventListener("scroll", () => {
      const backgroundcolor = window.scrollY < 100 ? "red" : "blue";

      this.setState({ navBackground: backgroundcolor });
    });
  }

to your code.

The scroll event fires when the document view or an element has been scrolled.
check this sample

Upvotes: 0

Related Questions