Search code examples
htmlcsscss-positioncss-gridsticky

Position Sticky not working with CSS Grid item


I have found several articles:

https://melanie-richards.com/blog/css-grid-sticky/

https://ishadeed.com/article/position-sticky-css-grid/

That address an "issue" when trying to use position:sticky on a CSS Grid item. I set up this pen to show the issue. I think I am following what the articles listed above are telling me, but for some reason, my nav tag will not stick to the stop when the site is scrolled.

header {
  display: grid;
  grid-auto-columns: 16pz auto 16px;
  grid-template-areas: ". header .";
}
header > div {
  grid-area: header;
  display: grid;
  grid-auto-columns: repeat(2, 1fr);
  grid-template-areas: "logo logo" "nav guide";
}
header > div #logo-container {
  grid-area: logo;
  text-align: center;
  margin-bottom: 50px;
}
header > div #nav-container {
  grid-area: nav;
  position: sticky;
  align-self: start;
  top: 1em;
}
header > div #nav-container nav ul {
  display: flex;
}
header > div #nav-container nav ul li {
  list-style: none;
  margin-right: 50px;
}
header > div #nav-container nav ul li a {
  background-color: black;
  padding: 15px;
  color: white;
}
header > div #guide-container {
  grid-area: guide;
}

#hero {
  background-color: red;
  height: 100vh;
}
<header>
    <div>
    <section id="logo-container">
      <a href="#hero">Logo</a>
    </section>
    <section id="nav-container">
      <nav id="main-nav">
        <ul>
          <li><a href="#history">History</a></li>
          <li><a href="#skills">Skills</a></li>
          <li><a href="#skynet">Skynet</a></li>
        </ul>
      </nav>
    </section>
    <section id="guide-container">
      <button class="show-md" id="guide-text-btn">Survival Guide</button>
    </section>
  </div>
</header>

<section id="hero"></section>

https://codepen.io/icekomo/pen/zYMgrpQ?editors=1100


Solution

  • You are assigning position: sticky to your #nav-container but its parent has just the height of the header and is not scollable.

    If you want to use position: sticky, it needs to live inside an element, that has a parent with a scrollable content.

    In your case this rule would only apply to the body. So, if you asign on the direct child (in this case <header>) your position: sticky, it will work.

    header {
      display: grid;
      grid-auto-columns: 16px auto 16px;
      grid-template-areas: ". header .";
      position: sticky;
      top: 1em;
    }