skip to Main Content

I’m trying to create a web page using a grid, and I want a column on the left to be stickied at the top of the page when a row is being scrolled past, and then unstickied when the other content in the row goes off screen.

So far all I’ve done is create two divs for a row, and set the left one to have position: sticky and top: 0, so that when the row is being scrolled by, the div on the left stays at the top. This works for one row, but when I add another row to the grid both divs stay attached to the top of the screen.

.content {
  display: grid;
  grid-template-columns: 25vw 75vw;
  grid-template-rows: auto auto;
}

.sidebar {
  border-right: 1px solid lightgray;
  border-left: 10px solid lightgray;
  max-height: 100vh;
  position: sticky;
  top: 0;
}

.content {
  flex-direction: column;
  max-width: 70vw;
  gap: 2em;
}
<div class="grid">
  <div class="sidebar">
     <h1>I want this div to be attached to the top of the screen while the row next to it is being scrolled through</h1>
  </div>

  <div class="content">
     <h1>There is a lot of content here</h1>
     <h1>Stretching the entire height of the screen</h1>
  </div>
  <div class="sidebar">
     <h1>But when this row reaches the top, this overlaps with the first sidebar</h1>
  </div>

  <div class="content">
     <h1>There is a lot of content here</h1>
     <h1>Stretching the entire height of the screen</h1>
  </div>
</div>

The two sidebar divs will eventually overlap, and I want one to "detach" from the top of the screen when it gets to this point. Is there a way to do this in pure CSS, or do I have to use Javascript?

2

Answers


  1. You could just assign a background color and fixed height to your sidebar. It’s nothing elegant but it gets the job done.

    .content {
      display: grid;
      grid-template-columns: 25vw 75vw;
      grid-template-rows: auto auto;
    }
    
    .sidebar {
      border-right: 1px solid lightgray;
      border-left: 10px solid lightgray;
      background-color: white;
      height: 120px;
      position: sticky;
      top: 0;
    }
    
    .content {
      flex-direction: column;
      max-width: 70vw;
      gap: 2em;
    }
    <div class="grid">
      <div class="sidebar">
         <h1>I want this div to be attached to the top of the screen while the row next to it is being scrolled through</h1>
      </div>
    
      <div class="content">
         <h1>There is a lot of content here</h1>
         <h1>Stretching the entire height of the screen</h1>
      </div>
      <div class="sidebar">
         <h1>But when this row reaches the top, this overlaps with the first sidebar</h1>
      </div>
    
      <div class="content">
         <h1>There is a lot of content here</h1>
         <h1>Stretching the entire height of the screen</h1>
      </div>
    </div>
    Login or Signup to reply.
  2. For this to work, you need to separate .sidebar. For example, wrap them in a section (or div):

    .sidebar {
      border-right: 1px solid lightgray;
      border-left: 10px solid lightgray;
      position: sticky;
      top: 0;
      background: #fff;
    }
    
    .content {
      display: grid;
      grid-template-columns: 1fr 3fr;
      gap: 2em;
      min-height: 600px; /* just for example */
    }
    <section>
      <div class="sidebar">
        <h1>I want this div to be attached to the top of the screen while the row next to it is being scrolled through</h1>
      </div>
      <div class="content">
        <div>There is a lot of content here</div>
        <div>Stretching the entire height of the screen</div>
      </div>
    </section>
    <section>
      <div class="sidebar">
        <h1>But when this row reaches the top, this overlaps with the first sidebar</h1>
      </div>
      <div class="content">
        <div>There is a lot of content here</div>
        <div>Stretching the entire height of the screen</div>
      </div>
    </section>
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search