unique navbar color transition effect specifically for the homepage

I have successfully created a function called changeColour in my code that changes the color of the navbar when scrolling past a certain point. However, I am encountering an issue where I only want this effect to be applied on the Home page. I would like all other pages (AboutUs, Shop, ContactUs) to maintain their default styles using the selectors

.navbarbg .nav-list-green a .nav-list-green a:hover
.

Below is the current state of my code:

Please find below my initial implementation inside const changeColour {}.

Navbar.jsx

'use client'

import React, { useState, useEffect } from 'react'
import { Link } from 'react-router-dom'
import Logo from './Logo.jsx'
import '../App.css'

const Navbar = () => {
    const state = useState()

    const navigation = [ 
      {_id:101, title: 'ABOUT US', href: '/AboutUs'},
      {_id:102, title: 'SHOP', href: '/Shop'},
      {_id:103, title: 'MENU', href: '/Menu'},
      {_id:104, title: 'CONTACT US', href: '/ContactUs'},
    ];
    
    const [colour, setColour] = useState(false)

    useEffect(() => {
      const changeColour = () => {
        if (isItHomePage()) setColour(window.scrollY >= 650)
      };
        function isItHomePage() {
          return window.location.href.indexOf("/") === 
       0;
     }


      window.addEventListener('scroll', changeColour);

      return () => {
        window.removeEventListener('scroll', changeColour)
      }
    }, [])
    

  return (
    <div className={colour ? 'navbar navbarbg' : 'navbar'}>
      <div className="container">
        <Logo />
        <ul className={colour ? 'nav-list-beige nav-list-green' : 'nav-list-beige'}
          >
          {
            navigation.map((item) => (
              <Link to={item?.href} key={item._id}>
                <li className={colour ? 'nav-link nav-link-colour' : 'nav-link'}>
                  {item?.title}
                  <span className={`${item?.href === state && 'style=color: blue;'}`}></span>
                </li>
              </Link>
            ))
          }
        </ul>
        <div>
          
        </div>
      </div>
    </div>
  )
}

export default Navbar

My App.css

/* navbar.jsx CSS */
.navbarbg {
  background-color: hsl(0, 0%, 100%);
  backdrop-filter: blur(30px); 
  box-shadow: 1px 1px 5px 1px hsl(0, 0%, 63%);
  transition-duration: 500ms;
}

.navbar {
  /* (green) background-color: hsl(96, 24%, 44%, 90%); */
  /* background-color: hsl(49, 87%, 88%); */
  /* border-bottom: 1px solid black; */
  position: fixed; top: 0px;
  height: 80px;
  width: 100%;
  z-index:99;
  transition-duration: 500ms
}

.nav-list-beige {
  display: flex;
  gap: 50px;
  list-style-type: none;
  justify-content: center;
  font-size: larger;
  display: flex;
  position: relative; top: -30px; left: 350px;
}

.nav-list-beige a {
  color: hsl(48, 54%, 89%);
  text-decoration: none;
  transition-duration: 500ms;
}

.nav-list-beige a:hover {
  color: hsl(48, 100%, 85%);
  transition-duration: 300ms;
  text-shadow: 0px 0px 2px;
}

.nav-list-green a {
  color: hsl(0, 0%, 0%);
}

.nav-list-green a:hover {
  color: hsl(96, 24%, 44%);
}

I would greatly appreciate any suggestions you may have. Thank you.

Answer №1

When working on this particular section, consider implementing a conditional statement as shown below:

      const updateColor = () => {
        setTheme(window.scrollY >= 650)
      };

You can add a condition by utilizing the function isHomePage, like so:

      const updateColor = () => {
        if (checkIfHomePage()) setTheme(window.scrollY >= 650)
      };

Make sure to define the checkIfHomePage function, which looks something like this:

function checkIfHomePage() {
    return window.location.href.indexOf("your home url") === 0;
}

Answer №2

Utilize the useLocation hook to gain access to the current pathname value and use the matchPath utility to check if the current pathname matches a specific path, such as a "home page" on "/". The pathname should be included as a dependency in the useEffect hook to update the current pathname value within the changeColor function when setting up the scroll event listeners.

Example:

import React, { useState, useEffect } from "react";
import { Link, matchPath, useLocation } from "react-router-dom";

...

const { pathname } = useLocation();

useEffect(() => {
  const changeColour = () => {
    const isHome = matchPath("/", pathname);
    
    setColour(isHome && window.scrollY >= 650);
  };

  // Check for initial scroll position
  changeColour();
  window.addEventListener("scroll", changeColour);

  return () => {
    window.removeEventListener("scroll", changeColour);
  };
}, [pathname]);

...

Complete code:

import React, { useState, useEffect } from "react";
import { Link, matchPath, useLocation } from "react-router-dom";

const navigation = [
  { _id: 100, title: "HOME", href: "/" },
  { _id: 101, title: "ABOUT US", href: "/AboutUs" },
  { _id: 102, title: "SHOP", href: "/Shop" },
  { _id: 103, title: "MENU", href: "/Menu" },
  { _id: 104, title: "CONTACT US", href: "/ContactUs" }
];

const Navbar = () => {
  const { pathname } = useLocation();

  const state = useState();
  const [colour, setColour] = useState(false);

  useEffect(() => {
    const changeColour = () => {
      const isHome = matchPath("/", pathname);

      setColour(isHome && window.scrollY >= 650);
    };

    changeColour();
    window.addEventListener("scroll", changeColour);

    return () => {
      window.removeEventListener("scroll", changeColour);
    };
  }, [pathname]);

  return (
    <div className={colour ? "navbar navbarbg" : "navbar"}>
      <div className="container">
        <Logo />
        <ul
          className={
            colour ? "nav-list-beige nav-list-green" : "nav-list-beige"
          }
        >
          {navigation.map((item) => (
            <Link to={item?.href} key={item._id}>
              <li className={colour ? "nav-link nav-link-colour" : "nav-link"}>
                {item?.title}
                <span
                  className={`${item?.href === state && "style=color: blue;"}`}
                ></span>
              </li>
            </Link>
          ))}
        </ul>
        <div></div>
      </div>
    </div>
  );
};

Answer №3

This is the solution I came up with to make it work eventually. I believe there might be a more efficient way to create variables for each page, but here's what I have accomplished so far:

Navbar.jsx

const Navbar = () => {
    const { pathname } = useLocation();

    const state = useState()
    const [colour, setColour] = useState(false)

    useEffect(() => {
      const changeColour = () => {
       //variables created for each specific page based on the pathname
        const isHome = matchPath("/", pathname)
        const isAboutUs = matchPath("/AboutUs", pathname)

        // conditional statements for different scroll effects on each page
        if (isHome && window.scrollY >= 650) {
          setColour(true)
        } else if (isAboutUs && window.scrollY >= 0) {
          setColour(true)
        } else {
          setColour(false)
        }
      };
      
  
      changeColour();
      window.addEventListener('scroll', changeColour);

      return () => {
        window.removeEventListener('scroll', changeColour)
      }
    }, [pathname])

Full code:

'use client'

import React, { useState, useEffect } from 'react'
import { Link, matchPath, useLocation } from 'react-router-dom'
import Logo from './Logo.jsx'
import '../App.css'

// Array containing all required navlinks for mapping
const navigation = [ 
  {_id:102, title: 'ABOUT US', href: '/AboutUs'},
  {_id:103, title: 'SHOP', href: '/Shop'},
  {_id:104, title: 'MENU', href: '/Menu'},
  {_id:105, title: 'CONTACT US', href: '/ContactUs'},
];

const Navbar = () => {
    const { pathname } = useLocation();

    const state = useState()
    const [colour, setColour] = useState(false)

    useEffect(() => {
      const changeColour = () => {
        const isHome = matchPath("/", pathname)
        const isAboutUs = matchPath("/AboutUs", pathname)

        if (isHome && window.scrollY >= 650) {
          setColour(true)
        } else if (isAboutUs && window.scrollY >= 0) {
          setColour(true)
        } else {
          setColour(false)
        }
      };
      
      changeColour();
      window.addEventListener('scroll', changeColour);

      return () => {
        window.removeEventListener('scroll', changeColour)
      }
    }, [pathname])
    
  return (
    <div className={colour ? 'navbar navbarbg' : 'navbar'}>
      <div className="container">
        <Logo />
        <ul className={colour ? 'nav-list-beige nav-list-green' : 'nav-list-beige'}
          >
          {
            navigation.map((item) => (
              <Link to={item?.href} key={item._id}>
                <li className={`${item?.href === pathname && 'color: hsl(96, 24%, 44%)'}`}>
                  {item?.title}
                  <span className={`${item?.href === pathname && 'color: hsl(96, 24%, 44%)'}`}></span>
                </li>
              </Link>
            ))
          }
        </ul>
        <div>
          
        </div>
      </div>
    </div>
  )
}

export default Navbar

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Guide on setting up a MERN stack with a multi-tenant architecture

After successfully creating a full stack e-commerce website using React, Node, and MongoDB, I am now looking to deploy it with a multi-tenant architecture. Each store owner should have their own domain name. The Admin Dashboard will include various APIs s ...

Animate the expansion and shrinkage of a div instantly using jQuery

I am trying to create an animation effect using jQuery animate on a div element where it starts large and then becomes smaller. Here is the code I have written: $(this).animate({ opacity: 0, top: "-=100", width: "38px", height: "32px" }, 1 ...

React useParams is returning a null value

Currently, I am in the process of constructing a search engine leveraging the Marvel API. In this project, I have two main components: HeroComics and Home. I am attempting to transfer {character.name} from HeroComics to Home by utilizing the code snippet b ...

Utilizing Javascript for altering HTML elements

It seems this issue is quite puzzling and I believe another perspective could be beneficial in identifying the problem. Despite my efforts, I am unable to understand why the "Energy Calculator" does not return a value when submitted, whereas the "Battery C ...

What is the process of extracting a URL and inputting it into a form to enhance

Can anyone help with extracting a specific value (TEXT) from a URL and automatically paste it into an input form field? For example, if the URL is domain.com/page?code=123abc, I need to grab the code (in this case, 123abc) and have it automatically popula ...

What is the best method to consistently convert a deeply nested object into a tabular format that can be easily reversed

Imagine having a deeply nested object with an unknown structure until runtime, like: { "row-0" : { "rec-0" : { "date" : 20220121, "tags" : [ "val-0" ] }, ...

Angular Material's md-checkbox is a required component

I am working on a form that consists of checkboxes representing the days of the week. When the user hits submit without selecting any checkboxes, I want an error message to appear. Here is the HTML code snippet that I have: <form id="addEditForm" nam ...

How can JQuery and CSS brighten up buttons?

Is there a way for me to create an "enlightening" effect similar to the one seen in the "Tags" section on this website? I am not just looking to change the color of the background from gray to white, but instead, I want to progressively make the button li ...

What is the method to ensure background images are loaded with SSL from a different domain?

I run an online store and to improve performance, the images are hosted on a different domain. However, when I switch to secure mode using SSL on certain parts of the website, the background images disappear. Trying to view the image directly in the browse ...

Is there a bug with the CSS Safari selector for elements focused together?

Looking for a solution using the element+element-Selector to modify CSS for an element following a button. This code snippet functions in Chrome, Edge, and Firefox but not Safari on MacOS: .button:focus+.change{ color: red; } <p>When you focus ...

Error: The module cannot be found. Reason: Unable to resolve '../config' in '/vercel/path0/components'

Encountered an issue while deploying my next.js app through Vercel. The app runs smoothly locally using the 'npm run dev' command. However, when attempting to deploy it via Vercel with a remote GitHub repository, I encountered the following error ...

Tips for customizing the blinking cursor in a textarea

I am experimenting with creating a unique effect on my website. I have incorporated a textarea with transparent text overlaying a pre element that displays the typed text dynamically using JavaScript. This creates an illusion of the user typing in real-tim ...

Comparing two jQuery methods for looping through Ajax requests - which one is the best option?

Currently working on a blog project that involves integrating Isotope Jquery (for layout/filtering/sorting), Infinite Scroll, and dynamic loading of all blog excerpts via Ajax. The goal is to apply filtering and sorting to all excerpts before they are load ...

Instantly reveal menu by pressing button

Is there a way to make my mobile menu open immediately upon touching the button? I have used ontouchstart="" in both buttons to create an overlay on the content when the offcanvas menu is visible. This functions well as soon as the user touches either butt ...

"Encountering difficulties while trying to modify the QuillNoSSRWrapper value within a Reactjs

Currently, I am working on a project involving ReactJS and I have opted to use the Next.js framework. As of now, I am focused on implementing the "update module" (blog update) functionality with the editor component called QuillNoSSRWrapper. The issue I ...

The battle between percentages and pixels in fluid design

I am looking to create a flexible layout and would like to achieve the following: width:100%-200px; This means having a div that contains content, referred to as div id="content", with a fixed margin on each side. I have attempted to place the div id="co ...

Using Angular 6 to import GeoJSON into a Leaflet map

I am facing an issue while trying to import a GeoJson file into Leaflet in my Angular app version 6. Although the geojson is being successfully drawn on the leafletmap, I am encountering an error that is preventing me from building my app. Is there anyone ...

What could have caused the lack of output from the render function?

I've been working on generating my navigation drawer from JSON data and have everything functioning using components. Now, I'm in the process of refactoring to functions for better performance and to enhance my knowledge of React and JavaScript. ...

Reliable Dropdown Navigation Bars

Once I have successfully implemented three dynamic drop down menus using the combination of jQuery, AJAX, and PHP, the next challenge arises. After populating the dropdown menus based on user selections (e.g., selecting a value in the first dropdown menu ...

Using dots instead of lines for the carousel indicators in PrimeNG

I'm currently working on a carousel feature, but I want to change the indicators from lines to small dots. I know the solution lies within the CSS files, but I'm not sure how to implement it. I think I need to create a new CSS class, but I could ...