Search code examples
htmlcssflexboxsticky

Why isn't position:sticky with left:0 working inside a scrollable container?


I have this problem - I have a container that contains some rows and in each row there is a sticky left column and then multiple other columns. Now in the example below this works for a little while but as you scroll the parent container the position sticky no longer works and it gets pushed along as you scroll.

.container {
  overflow-x: scroll;
}

.row {
  display: flex;
  width: 100%;
  
}

.item {
  min-width: 173px;
}

.sticky {
  min-width: 250px;
  position: sticky;
  left: 0;
  background: red;
}
<div class="container">
  <div class="row">
    <div class="item sticky">STICKY ROW 1</div>
    <div class="item">1</div>
    <div class="item">2</div>
    <div class="item">3</div>
    <div class="item">4</div>
    <div class="item">5</div>
    <div class="item">6</div>
    <div class="item">7</div>
    <div class="item">8</div>
    <div class="item">9</div>
    <div class="item">10</div>
  </div>
  <div class="row">
    <div class="item sticky">STICKY ROW 2</div>
    <div class="item">1</div>
    <div class="item">2</div>
    <div class="item">3</div>
    <div class="item">4</div>
    <div class="item">5</div>
    <div class="item">6</div>
    <div class="item">7</div>
    <div class="item">8</div>
    <div class="item">9</div>
    <div class="item">10</div>
  </div>
  <div class="row">
    <div class="item sticky">STICKY ROW 3</div>
    <div class="item">1</div>
    <div class="item">2</div>
    <div class="item">3</div>
    <div class="item">4</div>
    <div class="item">5</div>
    <div class="item">6</div>
    <div class="item">7</div>
    <div class="item">8</div>
    <div class="item">9</div>
    <div class="item">10</div>
  </div>
</div>

Is there any way to solve this.. or is there another way to accomplish this??

My desired result is to be able to have the sticky div stuck on that left side a 0 and have the other columns scroll underneath..

Now I do know that if the overflow-x: scroll is on the actual .row element it works as expected.. but I may have 100+ rows so the scroll needs to be on the parent container


Solution

  • Add border to better see the issue which is related to the use a block level element and the restriction of width:100% (not the one your are setting which is useless but the default behavior of block elements)

    .container {
      overflow-x: scroll;
    }
    
    .row {
      display: flex;
      border:1px solid;
    }
    
    .item {
      min-width: 173px;
    }
    
    .sticky {
      min-width: 250px;
      position: sticky;
      left: 0;
      background: red;
    }
    <div class="container">
      <div class="row">
        <div class="item sticky">STICKY ROW 1</div>
        <div class="item">1</div>
        <div class="item">2</div>
        <div class="item">3</div>
        <div class="item">4</div>
        <div class="item">5</div>
        <div class="item">6</div>
        <div class="item">7</div>
        <div class="item">8</div>
        <div class="item">9</div>
        <div class="item">10</div>
      </div>
      <div class="row">
        <div class="item sticky">STICKY ROW 2</div>
        <div class="item">1</div>
        <div class="item">2</div>
        <div class="item">3</div>
        <div class="item">4</div>
        <div class="item">5</div>
        <div class="item">6</div>
        <div class="item">7</div>
        <div class="item">8</div>
        <div class="item">9</div>
        <div class="item">10</div>
      </div>
      <div class="row">
        <div class="item sticky">STICKY ROW 3</div>
        <div class="item">1</div>
        <div class="item">2</div>
        <div class="item">3</div>
        <div class="item">4</div>
        <div class="item">5</div>
        <div class="item">6</div>
        <div class="item">7</div>
        <div class="item">8</div>
        <div class="item">9</div>
        <div class="item">10</div>
      </div>
    </div>

    Consider an inline level element using inline-flex to solve the issue. Add min-width:100% to make sure you cover at least 100% of width if the content is small.

    .container {
      overflow-x: scroll;
    }
    
    .row {
      display: inline-flex;
      min-width: 100%;
      border:1px solid;
    }
    
    .item {
      min-width: 173px;
    }
    
    .sticky {
      min-width: 250px;
      position: sticky;
      left: 0;
      background: red;
    }
    <div class="container">
      <div class="row">
        <div class="item sticky">STICKY ROW 1</div>
        <div class="item">1</div>
        <div class="item">2</div>
        <div class="item">3</div>
        <div class="item">4</div>
        <div class="item">5</div>
        <div class="item">6</div>
        <div class="item">7</div>
        <div class="item">8</div>
        <div class="item">9</div>
        <div class="item">10</div>
      </div>
      <div class="row">
        <div class="item sticky">STICKY ROW 2</div>
        <div class="item">1</div>
        <div class="item">2</div>
        <div class="item">3</div>
        <div class="item">4</div>
        <div class="item">5</div>
        <div class="item">6</div>
        <div class="item">7</div>
        <div class="item">8</div>
        <div class="item">9</div>
        <div class="item">10</div>
      </div>
      <div class="row">
        <div class="item sticky">STICKY ROW 3</div>
        <div class="item">1</div>
        <div class="item">2</div>
        <div class="item">3</div>
        <div class="item">4</div>
        <div class="item">5</div>
        <div class="item">6</div>
        <div class="item">7</div>
        <div class="item">8</div>
        <div class="item">9</div>
        <div class="item">10</div>
      </div>
    </div>


    Some related questions:

    Nested sticky element with zero left does not sticky

    Why is my element not sticking to the left when using position sticky in css?