COLOR CHANGE OF FIXED ELEMENTS WHEN SCROLLING OVER A DARK SECTION

by davidxmartins

HTML

<!--
--------------------------
Logo
--------------------------
-->

<svg class="logo-icon colour-change" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 120 120">
  <title>Logo Icon</title>
  <path d="M42.847,59.222H.02c0,.26-.02.517-.02.778A59.722,59.722,0,0,0,7.394,88.865Z"/>
  <path d="M42.1,75.391,14.19,98.729A60.05,60.05,0,0,0,42.1,117.284Z"/>
  <path d="M44.295,47.3,13.761,21.766A59.777,59.777,0,0,0,1.36,47.3Z"/>
  <path d="M118.64,47.3a59.777,59.777,0,0,0-12.4-25.529L75.706,47.3Z"/>
  <path d="M77.887,75.382v41.905a60.05,60.05,0,0,0,27.923-18.558Z"/>
  <path d="M77.153,59.222l35.453,29.643A59.722,59.722,0,0,0,120,60c0-.261-.016-.518-.02-.778Z"/>
  <path d="M60,0A59.737,59.737,0,0,0,22.285,13.347L54.032,39.89V119.7c1.963.194,3.954.3,5.968.3s4-.1,5.959-.3V39.9L97.715,13.347A59.737,59.737,0,0,0,60,0Zm0,28.548A10.584,10.584,0,1,1,70.584,17.964,10.584,10.584,0,0,1,60,28.548Z"/>
</svg>


<!--
--------------------------
Menu items and content
--------------------------
-->
<div id="menu" class="menu-icon colour-change" onclick="changeIcon(this)">
  <div class="bar1"></div>
  <div class="bar2"></div>
  <div class="bar3"></div>
</div>



<!--
--------------------------
Back-to-Top Button
--------------------------
-->

<a class="backtotop-icon colour-change" href="#backtotop-anchor">
  <div class="arrow-head"></div>
  <div class="arrow-line"></div>
</a>


<div class="white padding"><h1>COLOR CHANGE OF FIXED ELEMENTS WHEN SCROLLING OVER A DARK SECTION</h1>
<h2>With Commented JS - Final Version</h2>
<h3>Explanation</h3>
<p>Change color of children of fixed elements with class ".colour-change" when, while scrolling, they overlap a dark-section with class ".replace".<br><br>This JS version targets the children so you only need to add the class ".change-colour" to the parent.<br><br>Aditionally this version also targets the color of three different attributs depending on what child element uses; "background-color", which is...

CSS

/* Logo-Icon ______________ */

.logo-icon {
  position: fixed;
  width: 52px;
  height: auto;
  left: 15px;
  top: 15px;
  z-index: 9;
}
.logo-icon path {
  fill: green;
  transition: 0.2s;
}

/* Menu-Icon ______________ */

.menu-icon {
  position: fixed;
  display: inline-block;
  cursor: pointer;
  right: 15px;
  top: 10px;
  padding: 5px;
  z-index: 9;
}

.bar1, .bar2, .bar3 {
  width: 35px;
  height: 5px;
  background-color: green;
  margin: 6px 0;
  transition: 0.2s;
}


/* Responsive Styles */

@media (max-width: 1400px) {
  .logo-mini {
    visibility: hidden;
  }
  .menu-icon {
    position: fixed;
    right: 10px;
    top: 10px;
    z-index: 9;
  }
}

/* Back to top icon ________________ */

.backtotop-icon {
  position: fixed;
  bottom: 20px;
  right: 20px;
  cursor: pointer;
  width: 20px;
  height: 20px;
  z-index: 2;
}
.arrow-head {
  border: solid green;
  border-width: 4px 4px 0 0;
  display: inline-block;
  transform: rotate(-45deg);
  -webkit-transform: rotate(-45deg);
  padding: 10px;
  position: absolute;
  transition: 0.2s;
}
.arrow-line {
  width: 4px;
  height: 25px;
  background: green;
  margin-left: 10px;
  position: absolute;
  transition: 0.2s;
}

/* ------------- */

.container { height: 400px;}
.white { background: white; }
.green { background: green; }

a { 
text-decoration: none;
color: inherit;
}

.padding { padding: 100px; }
body {
  border: 0;
  margin: 0;
  font-family: sans-serif;
}

JavaScript

// Get all the elements with class '.replace'
const darkSections = document.querySelectorAll('.replace');
// Get all elements that will change color
const colorChangeElements = document.querySelectorAll('.colour-change');

let handleScroll = () => {
  // Iterate through each color-changing element
  colorChangeElements.forEach(element => {

    // Get all child elements of the current color-changing element
    const elementChildren = element.querySelectorAll('*');

    // By default, set the color of all children to brand color
    elementChildren.forEach(child => changeColor(child, 'green'));

    // For each dark section ('.replace')
    darkSections.forEach((section) => {

      // Get the size and position of the replace section and the color-changing element
      const darkSectionRect = section.getBoundingClientRect();
      const elementRect = element.getBoundingClientRect();

      // Calculate the intersection area between the color-changing element and the replace section
      const intersectionArea = Math.max(0, Math.min(darkSectionRect.bottom, elementRect.bottom) - Math.max(darkSectionRect.top, elementRect.top));

      // If the intersection area is more than 50% of the height of the color-changing element
      if (intersectionArea / (elementRect.bottom - elementRect.top) > 0.5) {

        // Change the color to white
        elementChildren.forEach(child => changeColor(child, 'white'));
      }
    });
  });
};

// Function to change the color of an element based on its type
let changeColor = (element, color) => {
  const tagName = element.tagName.toLowerCase();

  // If the element is a path (SVG), change the fill color
  if (tagName === 'path') {
    element.style.fill = color;
  } 
  // If the element has a border, change the border color
  else if (window.getComputedStyle(element, null).getPropertyValue("border-top-style") !== 'none') {
    element.style.borderColor = color;
  } 
  // For all...