I’m trying to create a navigation bar that is supposed to be transparent when the user is scrolled all the way to the top. When the user scrolls down from the top, the navigation bar changes background and text color so that the bar is visible. In my React project, I’m using TailwindCSS for almost all of my styling. My code works, I know that for a fact.
// src/components/Navbar.js
import React, { useState } from 'react';
const Navbar = () => {
const [navbarBackground, setNavbarBackground] = useState('transparent');
const [navbarTextColor, setNavbarTextColor] = useState('slate-200');
const handleScroll = () => {
const scrolled = window.scrollY;
if (scrolled > 20) {
setNavbarBackground('slate-200');
setNavbarTextColor('slate-800');
} else {
setNavbarBackground('transparent');
setNavbarTextColor('slate-200');
}
};
window.addEventListener('scroll', handleScroll);
return (
<nav
className={`flex justify-between p-4 fixed top-0 w-full z-50 transition bg-${navbarBackground}`}
>
<div className={`font-cursive text-${navbarTextColor}`}>Luca Cangelosi</div>
<div className="flex space-x-10">
<a className={`text-${navbarTextColor} font-semibold transition cursor-pointer`}>About</a>
<a className={`text-${navbarTextColor} font-semibold transition cursor-pointer`}>Store</a>
<a className={`text-${navbarTextColor} font-semibold transition cursor-pointer`}>Contact</a>
<div>
<i className={`text-${navbarTextColor} fas fa-shopping-cart transition cursor-pointer`}></i>
</div>
</div>
</nav>
);
};
export default Navbar;
All the code above does is, when the user scrolls, it checks the Y-position of the window. If the position is 0 (the user is at the top of the page), then the class on the navbar
is bg-transparent
and the text color of the links are text-slate-200
. Otherwise, the class on the navbar is bg-slate-200
and the link colors are text-slate-800
.
However, for some reason, when I first run npm start
, the code doesn’t seem to work. In fact, the background of the navigation bar is transparent (even after I scroll down), and the color of the links are either black or slate-800
(I can’t tell). Scrolling doesn’t change anything. However, when I set one of the links to always be slate-800
, or something similar, everything else seems to work fine. After that, I changed it back to be based off the scrolling, and it worked fine.
Basically, it didn’t work until I hard-set one of the colors to be permanently one color (not based off the scrolling), and then everything worked (background and link colors). Then, when I change it back to the original code, it continues to work.
Why does this happen? Why doesn’t it work the first time. I’m afraid that in production, this would be the case. How would I fix it?
Thanks!
2
Answers
I think you can try to use boolean for the state value. It’s more readable.
If you don’t use addEventListener inside useEffect, and instead use it directly in the component body, it can cause the event listener to be added multiple times.
By using addEventListener inside useEffect, we ensure that the event listener is only added once.
Finally, you can toggle the class name like this.
You must add your full className inside the
useState
hook.slate-400
❌text-slate-400
Orbg-slate-400
✅When you do
slate-400
tailwindcss is not generate the classNames for your component because this thing is not applicable for tailwindcss (According to Docs).Now your code should be: