0

This was pretty simple in Vanilla JS but I'm struggling to implement this in React.

I have Navbar with some links. Upon hovering over each link, I'd like the background color of the entire Navbar (classname: nav-section) to change accordingly. And by default I want to have a black color for the page. Anytime the cursor is not on any of the links, the navbar should be back to black again.

Say, my simplified Navbar.js is like this:

const Navbar = () => {
 return (
    <nav className='nav-section'>
    <div className="nav-list">
            <a className="list-item one">
              <div className="navlink-text">Red</div>
            </a>
            <a className="list-item two">
              <div className="navlink-text">Blue</div>
            </a>
            <a className="list-item three">
              <div className="navlink-text">Aqua</div>
            </a>
            <a className="list-item four">
              <div className="navlink-text">Cyan</div>
            </a>
          </div>
    </nav>
 );
};

export default Navbar;

I have an external css file styling the navbar and other elements that I have in it. What is the most efficient way to achieve what I want, with React? I tried to use emotion/css but I couldn't make it work. Any guidance is well appreciated.

  • https://github.com/nikeshnaik/entertainment_app-react/blob/main/src/components/Navbar/navbar.jsx – niko Aug 11 '22 at 07:49
  • @niko could you please explain a bit more? How to achieve what I want in a simple way? I just need to change the background color –  Aug 11 '22 at 07:58
  • https://spectacular-scone-be3880.netlify.app/ – niko Aug 11 '22 at 09:08

3 Answers3

1

If I understand it correctly there are 2 possible solutions I wrote;

  1. with css =>

.nav-section {
  pointer-events: none;
  background-color: black;
}

.nav-section:hover {
  pointer-events: none;
    background-color: red;
}

.nav-section > .nav-list {
  display: inline-flex;
  flex-direction: column;
}

.nav-section > .nav-list > .list-item {
  display: inline-block;
  pointer-events: auto;
  background-color: aqua;
}

.nav-section > .nav-list > .list-item:hover {
  background-color: rgb(154, 225, 225);
}
  1. with react =>

const Navbar = () => {
  const [isHover, setIsHover] = useState(false);

  const handleHover = (_isHover) => setIsHover(_isHover);

  return (
    <nav className={`nav-section ${isHover ? "nav-hover" : ""}`}>
      <div className="nav-list">
        <a
          className="list-item one"
          onMouseOver={() => handleHover(true)}
          onMouseLeave={() => handleHover(false)}
        >
          <div className="navlink-text">Red</div>
        </a>
        <a
          className="list-item two"
          onMouseOver={() => handleHover(true)}
          onMouseLeave={() => handleHover(false)}
        >
          <div className="navlink-text">Blue</div>
        </a>
        <a
          className="list-item three"
          onMouseOver={() => handleHover(true)}
          onMouseLeave={() => handleHover(false)}
        >
          <div className="navlink-text">Aqua</div>
        </a>
        <a
          className="list-item four"
          onMouseOver={() => handleHover(true)}
          onMouseLeave={() => handleHover(false)}
        >
          <div className="navlink-text">Cyan</div>
        </a>
      </div>
    </nav>
  );
};

export default Navbar;

and its style =>

.nav-section {
  background-color: black;
}

.nav-section.nav-hover {
   background-color: red;
}
 
.nav-section > .nav-list {
  display: inline-flex;
  flex-direction: column;
}

.nav-section > .nav-list > .list-item {
  display: inline-block;
  background-color: aqua;
}

.nav-section > .nav-list > .list-item:hover {
  background-color: rgb(154, 225, 225);
}

And also it can be done with useRef, but it seems a bit complicated to me

  • The background color should be different upon hovering on each link... how to achieve that? –  Aug 11 '22 at 13:04
  • In addition to second solution you can pass different classnames to nav from react side and define these classes in css like nav-hover1, nav-hover2. For instance when you hover item3, pass nav-hover3 to nav element. And define each of them like nav-section.nav-hover {} as it shown. I couldn't think of a simpler solution :) – Bahar Yılmaz Aug 16 '22 at 07:48
0

Take a look at useRef() in react. It's a great way to access style properties of an element. Therefore you could change the background of the navbar.

Of course you could also use the native css property :hover to change the backgound on hover.

yanseil
  • 61
  • 5
  • Native css to change background on parent on hovering child element?! Share the code snippet please, how is it possible –  Aug 11 '22 at 07:53
  • It might not be the answer you are searching for but this is a work around I found. https://stackoverflow.com/questions/8114657/how-to-style-the-parent-element-when-hovering-a-child-element I would suggest using refs tho – yanseil Aug 11 '22 at 07:56
  • Nah this won't work, I need pointer events in the parent for some other features –  Aug 11 '22 at 08:04
  • Could you maybe attach the css you got so far in the question so I can try to reproduce? – yanseil Aug 11 '22 at 08:28
0

Leaving this for anyone who comes across this post,

I solved it using Emotion.

/** @jsxImportSource @emotion/react */
import { useState } from "react";
import "./navbar.css";
import { css } from "@emotion/react";


const Navbar = () => {
  const [background, setBackground] = useState("#410099");
  const setStyle = (background) => {
    setBackground(background);
  };

  return (
    <nav css={css`
    position: sticky;
    left: 0;
    top: 0;
    right: 0;
    bottom: auto;
    z-index: 998;
    background-color: ${background};
    display: flex;
    flex-direction: column;
    padding: 0px 60px;
  `}
    >
<div className="nav-list">
            <a
              className="list-item one"
              onMouseEnter={() => setStyle("#424246")}
              onMouseLeave={() => setStyle("#410099")}
            >
              <div className="navlink-text">Color</div>
            </a>
            <a className="list-item two"
            onMouseEnter={() => setStyle("#424246")}
            onMouseLeave={() => setStyle("#410099")}>
              <div className="navlink-text">Color</div>
            </a>
            <a className="list-item three"
            onMouseEnter={() => setStyle("#424246")}
            onMouseLeave={() => setStyle("#410099")}>
              <div className="navlink-text">Color</div>
            </a>
            <a className="list-item four"
            onMouseEnter={() => setStyle("#424246")}
            onMouseLeave={() => setStyle("#410099")}>
              <div className="navlink-text">Color</div>
            </a>
          </div>
    </nav>
  );
};

export default Navbar;

Customize this as needed. :)