javascripthtmlcssfixedonscroll

How can I make multiple on scroll fixed headers/navbars that stick at the very top of the page?


Does anyone know how to make multiple on scroll fixed headers? I've already checked answers such as this.

I want the first header, that's already fixed at the top of the screen, to stop before the second header, and when the first header gets scrolled past, the second header should be taking the first header's place and stick at the very top of the screen.

But such answers don't work for me because they're using libraries that I'm not working with, such as jQuery, or they are overly, overly complicated. I've got it to work, so far, with getBoundingClientRect(), but with only 2 headers.

I've provided the HTML&CSS part here:

html, body {
  margin: 0;
  padding: 0;
  width: 100%;
  height: 100%;
  font-family: 'Roboto', sans-serif;
}

@import url("https://fonts.googleapis.com/css?family=Roboto:100");

h1 {
  letter-spacing: 3px;
  margin: 0;
  padding-left: 10px;
  padding-top: 10px;
  color: #fff;
  font-weight: 100;
}

.header {
  width: 100%;
  height: 50px;
}

.header:nth-of-type(1){
   background-color: dodgerblue;
    position: fixed;
}

.header:nth-of-type(2){
   background-color: rebeccapurple;
}

.header:nth-of-type(3){
   background-color: chartreuse;
}

.content {
  width: 100%;
  height: 100%;
  background: linear-gradient(70deg, orange, crimson);
  padding-top: 50px;
    
}
<header class="header"><h1>HEADER 1</h1></header>
<div class="content"><h1>CONTENT</h1></div>
<header class="header"><h1>HEADER 2</h1></header>
<div class="content"><h1>CONTENT</h1></div>
<header class="header"><h1>HEADER 3</h1></header>
<div class="content"><h1>CONTENT</h1></div>


Solution

  • Demo:

    html,
    body {
      margin: 0;
      padding: 0;
      width: 100%;
      height: 100%;
      font-family: 'Roboto', sans-serif;
    }
    
    @import url("https://fonts.googleapis.com/css?family=Roboto:100");
    h1 {
      letter-spacing: 3px;
      margin: 0;
      padding-left: 10px;
      padding-top: 10px;
      color: #fff;
      font-weight: 100;
    }
    
    .content {
      width: 100%;
      height: 100%;
      background: linear-gradient(70deg, orange, crimson);
    }
    
    .content .header {
      width: 100%;
      height: 50px;
      position: sticky;
      top: 0;
    }
    
    .content:nth-of-type(1) .header {
      background-color: dodgerblue;
    }
    
    .content:nth-of-type(2) .header {
      background-color: rebeccapurple;
    }
    
    .content:nth-of-type(3) .header {
      background-color: chartreuse;
    }
    <div class="content">
      <header class="header">
        <h1>HEADER 1</h1>
      </header>
      <div class="content-inner">
        <h1>CONTENT</h1>
      </div>
    </div>
    
    <div class="content">
      <header class="header">
        <h1>HEADER 2</h1>
      </header>
      <div class="content-inner">
        <h1>CONTENT</h1>
      </div>
    </div>
    
    <div class="content">
      <header class="header">
        <h1>HEADER 3</h1>
      </header>
      <h1>CONTENT</h1>
    </div>

    View on jsFiddle

    Explanation:

    position: sticky with correct markup will do the work

    PS: I know there is already an answer using position: sticky but in that solution the previous header doesn't stop but overlaps with the next one. In my solution is stops before the next sticking.