Search code examples
csscss-positioncss-grid

How to create a sticky header with CSS-grid?


I would like to make my header sticky when scrolling using CSS grid.

I have tried the solution proposed here: Sticky header on css grid Meaning:

position: sticky; 
top:0;

However it does not work...

.wrapper {
  display: grid;
  grid-template-areas: "header" "middle" "footer";
  grid-template-rows: auto 1fr auto;
  height: 100vh;
}


/* Header */

header {
  order: 1;
  grid-area: header;
  display: grid;
  grid-gap: 100px;
  grid-template-areas: "logo nav";
  grid-template-columns: auto 1fr;
  grid-auto-flow: column;
  position: sticky;
  top: 0;
}

nav {
  display: grid;
  grid-area: nav;
  grid-template-columns: repeat(auto-fit, minmax(100px, 1fr));
}


/* Middle */

.middle {
  order: 2;
  grid-area: middle;
  display: grid;
  grid-template-columns: 50px 1fr 50px;
}

.middle>* {
  grid-column: 2 / -2;
}


/* Footer */

footer {
  order: 3;
  grid-area: footer;
  display: grid;
  grid-template-columns: 1fr auto 1fr;
}

.footer-links {
  display: grid;
  grid-column: 2 /-2;
  grid-template-columns: 1fr;
  grid-auto-flow: column;
  align-items: center;
}
<body>
  <div class="wrapper">

    <!-- Header -->
    <header>
      <a href="./index.html" title="Welcome" class="logo"><img src="img/logo_jaeaess_glitch.png" alt="Logo of the VJ Jääß (Jess de Jesus)" style="width:42px;height:42px"></a>
      <nav>
        <a href="./index.html" title="Welcome" class="welcome active">Welcome</a>
        <a href="./about.html" title="About" class="about">About</a>
        <a href="./artwork.html" title="Art Work" class="artwork">Art Work</a>
        <a href="./events.html" title="Events" class="events">Events</a>
      </nav>
    </header>
    <!-- Middle -->
    <section class="middle">
    </section>

    <footer>
      <div class="footer-links">
        <a href="https://www.instagram.com/jaeaess/" target="_blank">Instagram</a>
        <p>&copy; 2019 Jääß</p>
      </div>
    </footer>
  </div>

</body>

Everything displays as I want it to, except that the header scroll down instead of staying fix...

(For those who wonder, I put the order just to move it within a media query at a later stage of development)

Thank you for your answers!


Solution

  • To make the header fixed when scrolling, you could make it position: fixed. This requires you to set a fixed height for your header. This will make the header element flow on top of the content and ignore scrolling relative to the window.

      
    .wrapper {
      /* the header will not take any vertical place so shift wrapper down a bit*/
      margin-top: 3rem; 
      display: grid;
      /*I removed the header area as we don't need it anymore and would not work with fixed position anways*/
      grid-template-areas: "middle" "footer";
      grid-template-rows: 1fr auto;
       /*I set the wrapper height to `200vw` so its easier to see the header not scrolling. Also take maring top into account*/
      height: calc(200vh - 3rem);
    }
    
    
    /* Header */
    
    header {
      display: grid;
      grid-gap: 100px;
      grid-template-areas: "logo nav";
      grid-template-columns: auto 1fr;
      grid-auto-flow: column;
      position: fixed;
      top: 0;
      height: 3rem;
      width: 100%;
    }
    
    nav {
      display: grid;
      grid-area: nav;
      grid-template-columns: repeat(auto-fit, minmax(100px, 1fr));
    }
    
    
    /* Middle */
    
    .middle {
      order: 2;
      grid-area: middle;
      display: grid;
      grid-template-columns: 50px 1fr 50px;
    }
    
    .middle>* {
      grid-column: 2 / -2;
    }
    
    
    /* Footer */
    
    footer {
      order: 3;
      grid-area: footer;
      display: grid;
      grid-template-columns: 1fr auto 1fr;
    }
    
    .footer-links {
      display: grid;
      grid-column: 2 /-2;
      grid-template-columns: 1fr;
      grid-auto-flow: column;
      align-items: center;
    }
    <div class="wrapper">
      <!-- Header -->
      <header>
        <a href="./index.html" title="Welcome" class="logo"><img src="img/logo_jaeaess_glitch.png" alt="Logo of the VJ Jääß (Jess de Jesus)" style="width:42px;height:42px" /></a>
        <nav>
          <a href="./index.html" title="Welcome" class="welcome active">Welcome</a
              >
              <a href="./about.html" title="About" class="about">About</a>
          <a href="./artwork.html" title="Art Work" class="artwork">Art Work</a>
          <a href="./events.html" title="Events" class="events">Events</a>
        </nav>
      </header>
      <!-- Middle -->
      <section class="middle"></section>
    
      <footer>
        <div class="footer-links">
          <a href="https://www.instagram.com/jaeaess/" target="_blank">Instagram</a
              >
              <p>&copy; 2019 Jääß</p>
            </div>
          </footer>
        </div>

    Ps.: You are kinda overusing the css grid at this moment. It is designed for 2 dimensional layouts. Your layout would be much(!) easier if you were using flexbox. Also making grid work in IE 11 is a pain.