Search code examples
javascriptforeachnavbar

How to change the navbar's color on request?


I want to change the navbar color when my specific div is hitting the top of the page. It only does it on my second request and not on my first, even though the console says it is working.

I can't find the reason it only works on the second 'box' of the forEach. Maybe it has something to do with that, but I also wrote it separately and it doesn't work.

const boxes = document.querySelectorAll('.Boxes');
const navContainer = document.querySelector('.nav-container');
const navItems = document.querySelectorAll('.nav-item');
const lines = document.querySelectorAll('.line');

window.addEventListener('scroll', function() {
  boxes.forEach((box) => {
    let boxRect = box.getBoundingClientRect();

    if (boxRect.top <= 100 && boxRect.bottom >= 100) {
      navContainer.style.backgroundColor = "#6a994e";
      //console.log(navContainer.style.backgroundColor);
      navItems.forEach((item) => {
        item.style.color = "white";
      })
      lines.forEach((line) => {
        line.style.backgroundColor = "white";
      })
    } else {
      navContainer.style.backgroundColor = "white";
      navItems.forEach((item) => {
        item.style.color = "#6a994e";
      })
      lines.forEach((line) => {
        line.style.backgroundColor = "#6a994e";
      })
    }
  })
});
body{
    margin: 0;
    padding: 0;
    font-family: Arial;
    overflow-x: clip;
}

.nav-container{
    width: 100%;
    height: 75px;
    display: grid;
    grid-template-columns: repeat(3, 1fr);
    grid-template-rows: 75px;
    padding: 10px 50px;
    background-color: white;
    color: black;
    position: fixed;
    top: 0;
    left: 0;
    z-index: 5;
    transition: all 0.5s linear;
}



.menu-container{
    display: inline-grid;
    justify-items: end;
    align-items: center;
}

.icon{
    position: relative;
    width: 40px;
    height: 40px;
    border: none;
    background-color: transparent;
    z-index: 2;
}

.menu-container .icon .line{
    width: 80%;
    height: 2px;
    background-color: #6a994e;
    position: absolute;
    transition: transform 0.6s linear;
}

.menu-container .icon .line1{
    top: 15px;
    left: 5px;
}
.menu-container .icon .line2{
    bottom: 15px;
    left: 5px;
}

.boxes{
    background-color: #6a994e;
    width: 100%;
    height: 100vh;
    display: flex;
    justify-content: center;
    align-items: center;
    flex-direction: column;
    overflow-x: hidden;
    animation: theater;
    animation-timeline: view();
    
}


@keyframes theater{
    0%{
        transform: scale(1);
    } 50% {
        transform: scale(2);
    }
}
<nav>
        <div class="nav-container">
            <a href=""><i class="fa-solid fa-paw nav-item"></i></a>
            <h1 class="nav-item">LOGO</h1>
            <div class ="menu-container">
                <button class="icon" id="toggle">
                    <div class="line line1"></div>
                    <div class="line line2"></div>
                </button>
                <ul class="nav-list">
                    <li><a href="">Home</a></li>
                    <li><a href="">Gallerij</a></li>
                    <li><a href="">Contact</a></li>
                </ul>
            </div>
        </div>
    </nav>

<section>
        <div class="boxes">
            <h1>text</h1>
        </div>
    </section>
  
  
<section>
        <div class="boxes">
            <h1>text</h1>
        </div>
    </section>


Solution

  • I assume you want the navbar to match the boxcolor on load too? If yes, we can simplify and reuse

    document.addEventListener('DOMContentLoaded', function() {
      const boxes = document.querySelectorAll('.Boxes');
      const navContainer = document.querySelector('.nav-container');
      const navItems = document.querySelectorAll('.nav-item');
      const lines = document.querySelectorAll('.line');
    
      function updateNavBar() {
        for (const box of boxes) {
          const boxRect = box.getBoundingClientRect();
          if (boxRect.top <= 100 && boxRect.bottom >= 100) {
            const boxColor = box.getAttribute('data-color');
            navContainer.style.backgroundColor = boxColor;
            // we can actually drop these if all text is white on whatever background
            navItems.forEach((item) => {
              item.style.color = "white";
            });
            lines.forEach((line) => {
              line.style.backgroundColor = "white";
            });
            return; // Exit the function once the matching box is found
          }
        }
      }
    
      // Run on page load
      updateNavBar();
    
      // Run on scroll
      window.addEventListener('scroll', updateNavBar);
    });
    body {
      margin: 0;
      font-family: Arial, sans-serif;
    }
    
    .nav-container {
      position: fixed;
      top: 0;
      width: 100%;
      background-color: white;
      display: flex;
      justify-content: space-around;
      align-items: center;
      padding: 10px 0;
      box-shadow: 0 2px 5px rgba(0, 0, 0, 0.1);
      transition: background-color 0.3s;
      z-index: 1000;
    }
    
    .nav-item {
      color: #6a994e;
      text-decoration: none;
      font-weight: bold;
      transition: color 0.3s;
    }
    
    .line {
      height: 2px;
      width: 50px;
      background-color: #6a994e;
      transition: background-color 0.3s;
    }
    
    .Boxes {
      height: 100vh;
      display: flex;
      justify-content: center;
      align-items: center;
      font-size: 2em;
      color: white;
    }
    
    .box1 {
      background-color: #a2d2ff;
    }
    
    .box2 {
      background-color: #ffafcc;
    }
    
    .box3 {
      background-color: #bde0fe;
    }
    
    .box4 {
      background-color: #ffc8dd;
    }
    <div class="nav-container">
      <a href="#" class="nav-item">Home</a>
      <a href="#" class="nav-item">About</a>
      <a href="#" class="nav-item">Services</a>
      <a href="#" class="nav-item">Contact</a>
      <div class="line"></div>
    </div>
    
    <div class="Boxes box1" data-color="#a2d2ff">Section 1</div>
    <div class="Boxes box2" data-color="#ffafcc">Section 2</div>
    <div class="Boxes box3" data-color="#bde0fe">Section 3</div>
    <div class="Boxes box4" data-color="#ffc8dd">Section 4</div>