0

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

pab
  • 971
  • 4
  • 17
  • 30

1 Answers1

2

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>
Adam
  • 5,495
  • 2
  • 7
  • 24
  • If the order of div B changed in the list, how would you get it to stick to the top right no matter where its position? – pab Jan 30 '23 at 16:55
  • I've edited it. I've added grid-row: 1 to the .b rule in the media query. The element with class 'b' will always appear at the top irrespective of where it appears in the html. Hope this helps. – Adam Jan 30 '23 at 17:10
  • thanks mate, also i applied the code to my app. What if each div has different heights? As I get a large gap between columns compared to the div on the left and the sidebar div? – pab Jan 30 '23 at 17:12
  • ie: http://jsfiddle.net/vL6759a0/ how can you prevent the div growing with the sidebar. So its flexible an works for all content, so I don't have the same heights? – pab Jan 30 '23 at 17:32
  • You can vary the height of each div but if the height of the very first grey div is less than the red div then use grid-row to span the elements. I've updated the answer above – Adam Jan 30 '23 at 17:33
  • Cool, think this is what im after: http://jsfiddle.net/0uvqnjc6/ setting the height to auto on divs a and b. Thanks for the help! – pab Jan 30 '23 at 17:45
  • Cool. Nice one! You're very welcome. Have a great day :-) – Adam Jan 30 '23 at 17:53