skip to Main Content

I am having an issue with my code for my Navbar.jsx component. I have implemented a function the navbar background and text changes colour on scroll which works fine but what I want is for the :hover colours to take effect as well but only one hover colour takes effect.

so far, only the ‘nav-list’ a:hover selector takes effect but after scrolling past 650px, its still using ‘nav-list’ a:hover when I want it use ‘nav-list-colour’ a:hover selector at that point.

Navbar.jsx component

import React, { useState } from 'react'
import Logo from './Logo.jsx'
import '../App.css'

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

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

    const changeColour = () => {
      if (window.scrollY >= 650) {
        setColour(true) 
      } else {
        setColour(false)
      }
    }

    window.addEventListener('scroll', changeColour)

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

export default Navbar

This is my style.css file

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

.nav-list a {
  /* color: hsl(96, 24%, 44%); */
  color: hsl(48, 54%, 89%);
  text-decoration: none;
  text-underline-offset: 0.2em;
  transition-duration: 500ms;
}

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

.nav-list-colour a:hover {
  color: rgb(200, 181, 103);
}

.nav-list a:hover {
  /* color: rgb(200, 181, 103); */
  color: hsl(96, 24%, 44%);
  text-underline-offset: 0.4em;
  transition-duration: 300ms;
  text-shadow: 0px 0px 3px;
}

I have tried setting up another function with an if statement effecting colour ONLY but it stopped showing changes all together. Any help will be appreciated. Thank you.

2

Answers


  1. This could be a CSS specificity issue. Try changing the UL component to

    <ul className={colour ? 'nav-list colour' : 'nav-list'} >
    

    And update the CSS to this

    .nav-list.colour a:hover {
      color: rgb(200, 181, 103);
    }
    
    Login or Signup to reply.
  2. The issue here is CSS selector specificity. ".nav-list a:hover" and ".nav-list-colour a:hover" have the same specificity and so it seems the rule defined later in CSS is what is applied.

    You have at least a couple options to resolve this:

    1. Reorder the CSS rules so the ".nav-list-colour" rules are defined after the ".nav-list" rules.

      .nav-list {
        font-weight: bold;
        display: flex;
        gap: 50px;
        list-style-type: none;
        justify-content: center;
        font-size: larger;
        position: relative; top: -30px; left: 300px;
      }
      
      .nav-list a {
        color: hsl(48, 54%, 89%);
        text-decoration: none;
        text-underline-offset: 0.2em;
        transition-duration: 500ms;
      }
      
      .nav-list a:hover {
        color: hsl(96, 24%, 44%);
        text-underline-offset: 0.4em;
        transition-duration: 300ms;
        text-shadow: 0px 0px 3px;
      }
      
      .nav-list-colour a {
        color: hsl(96, 24%, 44%);
      }
      
      .nav-list-colour a:hover {
        color: rgb(200, 181, 103);
      }
      
    2. Bump the selector specificity of the ".nav-list-colour" selectors so that they are more specific.

      .nav-list {
        font-weight: bold;
        display: flex;
        gap: 50px;
        list-style-type: none;
        justify-content: center;
        font-size: larger;
        position: relative; top: -30px; left: 300px;
      }
      
      .nav-list a {
        /* color: hsl(96, 24%, 44%); */
        color: hsl(48, 54%, 89%);
        text-decoration: none;
        text-underline-offset: 0.2em;
        transition-duration: 500ms;
      }
      
      .nav-list.nav-list-colour a { // <-- higher specificity
        color: hsl(96, 24%, 44%);
      }
      
      .nav-list.nav-list-colour a:hover { // <-- higher specificity
        color: rgb(200, 181, 103);
      }
      
      .nav-list a:hover {
        /* color: rgb(200, 181, 103); */
        color: hsl(96, 24%, 44%);
        text-underline-offset: 0.4em;
        transition-duration: 300ms;
        text-shadow: 0px 0px 3px;
      }
      

    Between these two options I would recommend bumping the specificity so the order of the CSS rules is less important.

    Unrelated but highly recommended suggestion: Update the logic in the Navbar to apply the scroll event listener in a useEffect hook so that it’s not creating new lister instances each time the component renders.

    Example:

    const Navbar = () => {
      ...
      const [colour, setColour] = useState(false);
    
      useEffect(() => {
        const changeColour = () => {
          setColour(window.scrollY >= 650);
        };
    
        window.addEventListener("scroll", changeColour);
    
        return () => {
          window.removeEventListener("scroll", changeColour);
        };
      }, []);
    
      ...
    };
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search