Search code examples
htmlcssscrollgrid

How to make an element sticky but scrollable to its full (variable) height with sibling element?


I am trying to replicate the basic grid layout such as which is seen on Twitter. It seems to be working fine so far but I can't get the right sidebar to stop scrolling once it has scrolled to its full variable height.

In the image below the white space should not appear and once the element has scrolled to its full height it should stick.

* {
  margin: 0;
  padding: 0;
  box-sizing: border-box;
}

.container {
  position: relative;
  display: grid;
  grid-template-columns: 1fr 3fr;
  min-height: 100vh;
  font-size: 2rem;
}

.inner-grid-container {
  display: grid;
  grid-template-columns: 1fr 1fr;
}

.left-sidebar,
.right-sidebar,
.main {
  margin: 0 1rem;
}

.left-sidebar,
.content {
  display: flex;
  flex-direction: column;
  justify-content: space-between;
}

.content {
  height: 95%;
  margin-top: 2.5rem;
}

.left-sidebar {
  background-color: burlywood;
  height: 100vh;
  position: sticky;
  top: 0;
}

.main {
  background-color: tomato;
  height: 1500px;
}

.right-sidebar {
  background-color: cadetblue;
  height: 900px;
}

.fixed-header {
  background-color: black;
  color: white;
  position: fixed;
  width: auto;
  top: 0;
}
<div class="container">
  <div class="left-sidebar">
    <div>
      <div>left sidebar</div>
      <div>top</div>
    </div>
    <div>bottom</div>
  </div>
  <div class="inner-grid-container">
    <div class="main">
      <div class="fixed-header">fixed header</div>
      <div class="content">
        <div>
          <div>main</div>
          <div>top</div>
        </div>
        <div>bottom</div>
      </div>
    </div>
    <div class="right-sidebar">
      <div class="fixed-header">fixed header</div>
      <div class="content">
        <div>
          <div>right sideabar</div>
          <div>top</div>
        </div>
        <div>bottom</div>
      </div>
    </div>
  </div>
</div>

enter image description here


Solution

  • Add

    position: sticky;
    bottom: 0;
    margin-top: auto;
    

    to the right sidebar

    * {
      margin: 0;
      padding: 0;
      box-sizing: border-box;
    }
    
    .container {
      position: relative;
      display: grid;
      grid-template-columns: 1fr 3fr;
      min-height: 100vh;
      font-size: 2rem;
    }
    
    .inner-grid-container {
      display: grid;
      grid-template-columns: 1fr 1fr;
    }
    
    .left-sidebar,
    .right-sidebar,
    .main {
      margin: 0 1rem;
    }
    
    .left-sidebar,
    .content {
      display: flex;
      flex-direction: column;
      justify-content: space-between;
    }
    
    .content {
      height: 95%;
      margin-top: 2.5rem;
    }
    
    .left-sidebar {
      background-color: burlywood;
      height: 100vh;
      position: sticky;
      top: 0;
    }
    
    .main {
      background-color: tomato;
      height: 1500px;
    }
    
    .right-sidebar {
      background-color: cadetblue;
      height: 900px;
      position: sticky;
      bottom: 0;
      margin-top: auto;
    }
    
    .fixed-header {
      background-color: black;
      color: white;
      position: fixed;
      width: auto;
      top: 0;
    }
    <div class="container">
      <div class="left-sidebar">
        <div>
          <div>left sidebar</div>
          <div>top</div>
        </div>
        <div>bottom</div>
      </div>
      <div class="inner-grid-container">
        <div class="main">
          <div class="fixed-header">fixed header</div>
          <div class="content">
            <div>
              <div>main</div>
              <div>top</div>
            </div>
            <div>bottom</div>
          </div>
        </div>
        <div class="right-sidebar">
          <div class="fixed-header">fixed header</div>
          <div class="content">
            <div>
              <div>right sideabar</div>
              <div>top</div>
            </div>
            <div>bottom</div>
          </div>
        </div>
      </div>
    </div>