2

I have looked around the internet for help with this issue; often even encountering solutions for other problems, but I still cannot achieve what I am looking for. I want a sticky side-bar that will stay with the main content of my page. Later, I will add functionality to that sidebar to enable it to link to various parts of the content (like a table of contents).

.content-container {
  display: flex
}

.sticky {
  position: sticky;
  top: 0
}

.main {
  flex-grow: 1
}
<div class="content-container"> .

  <div class="sticky">
    <div> Section Header 1</div>
    <div> Section Header 2 </div>
    <div> Section Header 3 </div>
    <div> Section Header 4 </div>
  </div>

  <div class="main">
    <div> Test </div>
    <div> Test </div>
    <div> Test </div>
    <div> Test </div>
    <div> Test </div>
    <div> Test </div>
    <div> Test </div>
    <div> Test </div>
    <div> Test </div>
    <div> Test </div>
    <div> Test </div>
  </div>
  
</div>

As of right now, the flex containers are doing their job nicely (putting the two divs side by side), but the sticky section is not working like a sticky element, because it's inside a flex-box. Any help would be greatly appreciated.

tacoshy
  • 10,642
  • 5
  • 17
  • 34

2 Answers2

0

Your height is .sticky for the entire page, and for this reason the sticky block does not work. The sticky block needs space to move.

Add margin-bottom: auto to .sticky (or you can set align-self: flex-start to the same class):

.sticky { 
  position: sticky; 
  top: 0; 

  margin-bottom: auto;
}

.content-container { 
  display: flex; 
}

.sticky { 
  position: sticky; 
  top: 0; 
  margin-bottom: auto;
}

.main { 
  flex-grow: 1; 
}
<div class="content-container"> .

    <div class="sticky">
        <div> Section Header 1</div>
        <div> Section Header 2 </div>
        <div> Section Header 3 </div>
        <div> Section Header 4 </div>
    </div>

  <div class="main">
     <div> Test </div>
     <div> Test </div>
     <div> Test </div>
     <div> Test </div>
     <div> Test </div>
     <div> Test </div>
     <div> Test </div>
     <div> Test </div>
     <div> Test </div>
     <div> Test </div>
     <div> Test </div>
     <div> Test </div>
     <div> Test </div>
     <div> Test </div>
     <div> Test </div>
     <div> Test </div>
     <div> Test </div>
     <div> Test </div>
     <div> Test </div>
     <div> Test </div>
     <div> Test </div>
     <div> Test </div>
     <div> Test </div>
     <div> Test </div>
     <div> Test </div>
     <div> Test </div>
     <div> Test </div>
     <div> Test </div>
     <div> Test </div>
     <div> Test </div>
     <div> Test </div>
     <div> Test </div>
     <div> Test </div>
  </div>
</div>
s.kuznetsov
  • 14,870
  • 3
  • 10
  • 25
0

The problem, is your .sticky container has nothing to "stick" against, since it's the same height as your main div.

What you need to do is add another element inside of your sticky element. That element will then stick to it's parent (.sticky) on scroll.

.content-container {
  position: relative;
  display: flex
}

.sticky .inner {
  position: sticky;
  top: 0;
}

.main {
  flex-grow: 1;
}
<div class="content-container">

  <div class="sticky">
    <div class="inner">
      <div> Section Header 1</div>
      <div> Section Header 2 </div>
      <div> Section Header 3 </div>
      <div> Section Header 4 </div>
    </div>
  </div>

  <div class="main">
    <div> Test </div>
    <div> Test </div>
    <div> Test </div>
    <div> Test </div>
    <div> Test </div>
    <div> Test </div>
    <div> Test </div>
    <div> Test </div>
    <div> Test </div>
    <div> Test </div>
    <div> Test </div>
    <div> Test </div>
    <div> Test </div>
    <div> Test </div>
    <div> Test </div>
    <div> Test </div>
    <div> Test </div>
    <div> Test </div>
    <div> Test </div>
    <div> Test </div>
    <div> Test </div>
    <div> Test </div>
    <div> Test </div>
    <div> Test </div>
    <div> Test </div>
    <div> Test </div>
    <div> Test </div>
    <div> Test </div>
    <div> Test </div>
    <div> Test </div>
    <div> Test </div>
    <div> Test </div>
    <div> Test </div>
    <div> Test </div>
    <div> Test </div>
    <div> Test </div>
    <div> Test </div>
    <div> Test </div>
    <div> Test </div>
    <div> Test </div>
    <div> Test </div>
    <div> Test </div>
    <div> Test </div>
    <div> Test </div>
  </div>
</div>

You can also avoid the wrapping element, by using align-items: flex-start on the .content-container. This will make the flex elements the height of their content.

.content-container {
  position: relative;
  display: flex;
  align-items: flex-start;
}

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

.main {
  flex-grow: 1;
}
<div class="content-container">

  <div class="sticky">
      <div> Section Header 1</div>
      <div> Section Header 2 </div>
      <div> Section Header 3 </div>
      <div> Section Header 4 </div>
  </div>

  <div class="main">
    <div> Test </div>
    <div> Test </div>
    <div> Test </div>
    <div> Test </div>
    <div> Test </div>
    <div> Test </div>
    <div> Test </div>
    <div> Test </div>
    <div> Test </div>
    <div> Test </div>
    <div> Test </div>
    <div> Test </div>
    <div> Test </div>
    <div> Test </div>
    <div> Test </div>
    <div> Test </div>
    <div> Test </div>
    <div> Test </div>
    <div> Test </div>
    <div> Test </div>
    <div> Test </div>
    <div> Test </div>
    <div> Test </div>
    <div> Test </div>
    <div> Test </div>
    <div> Test </div>
    <div> Test </div>
    <div> Test </div>
    <div> Test </div>
    <div> Test </div>
    <div> Test </div>
    <div> Test </div>
    <div> Test </div>
    <div> Test </div>
    <div> Test </div>
    <div> Test </div>
    <div> Test </div>
    <div> Test </div>
    <div> Test </div>
    <div> Test </div>
    <div> Test </div>
    <div> Test </div>
    <div> Test </div>
    <div> Test </div>
  </div>
</div>
disinfor
  • 10,865
  • 2
  • 33
  • 44