htmlcssbackground-colorparallax

CSS to change background color of fixed header on scroll


Is there a CSS-only technique to change the background color of a fixed menu bar once the user has scrolled up the page?

Example where color changes from silver to gold:
https://codepen.io/dpilafian/pen/pwREjR

Below is the JavaScript solution I am currently using:

HTML

<body>
   <header>
      <nav>Navigation Bar</nav>
   </header>
   <main>
      <h1>The Main Event</h1>
      <h2>Scroll this page up.</h2>
      <p>Content goes here.</p>
   </main>
   <footer>
      Footer
   </footer>
</body>

CSS (LESS)

body {
   padding-top: 30px;
   >header, >footer {
      background-color: silver;
      }
   }
body >header {
   position: fixed;
   top: 0px;
   width: 100%;
   transition: all 3s;
   &.scrolled {
      background-color: gold;
      }
   }

JavaScript (with jQuery)

const elem = $('body >header');
const scrolled = () => {
   const threshold = $(document).scrollTop() > 50;
   elem.toggleClass('scrolled', threshold);
   };
$(window).on({ scroll: scrolled });

It would be convenient to replace the above JavaScript solution with some kind of CSS parallax solution if possible.


Solution

  • You could do a bit of a hack, place a transparent absolute positioned div with an estimation on the scrolling distance desired translated into top coordinates. This would trigger the background change when you scroll to it and hover it.

    This is a generic example but you can tweak coordinates and sizes to your benefit (hoverable div has borders just for visual reference).

    body {
      font-family: sans-serif;
      margin: 0px;
      padding-top: 30px;
    }
    
    body header,
    body footer {
      text-align: center;
      background-color: silver;
      padding: 10px;
    }
    
    body header {
      position: fixed;
      top: 0px;
      width: 100%;
      transition: all 3s;
    }
    
    .scrolled {
      background-color: gold;
    }
    
    .hoverEffect {
      position: absolute;
      height: 200px;
      background: transparent;
      border: 1px solid lightgray;
      text-align: center;
      line-height: 200px;
      top: 432px;
      left: 0px;
      right: 0px;
    }
    
    .hoverEffect:hover+header {
      background: orange;
    }
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
    <div class="hoverEffect">scroll/hover to this part</div>
    <header>
      <nav>Navigation Bar</nav>
    </header>
    <main>
      <h1>The Main Event</h1>
      <h2>Scroll this page up.</h2>
      <p>Content goes here.</p>
      <p>Content goes here.</p>
      <p>Content goes here.</p>
      <p>Content goes here.</p>
      <p>Content goes here.</p>
      <p>Content goes here.</p>
      <p>Content goes here.</p>
      <p>Content goes here.</p>
      <p>Content goes here.</p>
      <p>Content goes here.</p>
      <p>Content goes here.</p>
      <p>Content goes here.</p>
      <p>Content goes here.</p>
      <p>Content goes here.</p>
    </main>
    <footer>
      Footer
    </footer>