Search code examples
htmlcsssticky

Sticky sidebar on desktop and within content on mobile


Im having issues trying to create a sticky sidebar. On mobile the content just needs to flow within its container, then on desktop that div needs to break out into a sticky sidebar on the right, while the content flows on the left side as normal:

http://jsfiddle.net/sace510n/

Think its causing issues because the div for the sidebar is in the middle of each block.

  .a {
    position: sticky;
    top: 0;
    right: 0;
  }
}

enter image description here

Any ideas would be greatly appreciated, thanks


Solution

  • Grid is the way to go here imho. Just create a new grid with 2 columns for your desktop inside your media query then set grid-column for the grey items to the left and the red one to the right. Then use position: sticky to, er, make it sticky.

    The code should be self-explanatory but if not just drop me a comment on and I'll explain.

    Edited: If each element is a different size, and the right-hand element is bigger than the first left-hand element then the gaps may look uneven. To solve this use a grid-row span on the .b class rule and choose a span that's big enough to keep the gaps even. Unfortunately grid-row: 1/-1 doesn't work on implicit grids.

    body {
      background: #20262e;
      padding: 20px;
      font-family: Helvetica;
    }
    
    .content {
      display: grid;
      gap: 1rem;
      width: 100%;
      max-width: 800px;
      margin: 0 auto;
      outline: 1px solid lime;
    }
    
    .a,
    .b {
      padding: 15px;
      width: 200px;
      height: 100px;
      margin: 0 auto;
      display: block;
    }
    
    .a {
      background: grey;
    }
    
    .b {
      background: red;
      height: fit-content; /* added this during edit */
    }
    
    @media (min-width: 768px) {
      .content {
        grid-template-columns: repeat(2, 1fr);
      }
      .a {
        grid-column: 1/2;
      }
      .b {
        position: sticky;
        top: 0;
        grid-column: 2/3;
        grid-row: 1/ span 3; /* <- choose a number to give the RHS grid enough space so the gaps of the LHS items don't grow */
      }
    }
    .h0 {
      height: 2.5rem;
    }
    .h1 {
      height: 10rem;
    }
    .h2 {
      height: 13rem;
    }
    .h3 {
      height: 4rem;
    }
    <div class="content">
      <div class="a h0">title1</div>
      <div class="a">title2</div>
      <div class="a">title3</div>
      <div class="a">title4</div>
      <div class="a h1">title5</div>
      <div class="a h1">title6</div>
      <div class="a">title7</div>
      <div class="a h2">title8</div>
      <div class="b">here on mobile, sticky sidebar on desktop <br/>title<br />title<br />title<br />title<br />title<br />title<br /></div>
      <div class="a h1">title9</div>
      <div class="a h3">title10</div>
    </div>