Home > OS >  Sticky column issue with css grid
Sticky column issue with css grid

Time:03-17

Here's a codepen illustrating the issue: No scroll

When I scroll to the right, the first column does stick to the left as is expected.

A bit of scroll to the right

However, when scrolling starts nearing the end of the table's horizontal space, the first no longer maintains its sticky position to the left edge of the table.

Scrolling all the way to the right

I've noticed that if I remove the HTML markup for the <aside>, the sticky column behavior works as expected. However, I need the <aside> to be present.

Any ideas on how to fix this with CSS while maintaining the DOM structure?

body {
  display: flex;
  align-items: center;
  justify-content: center;
  height: 100vh;
}

.container {
  display: flex;
  width: 300px;
  padding: 0.5rem;
  border: 1px solid red;
}

aside {
  padding-right: 1rem;
  width: 100px;
}

.table {
  min-width: 0;
  overflow: scroll;
}

.row {
  display: grid;
  grid-template-columns: repeat(4, 100px);
}

.col {
  border: 1px solid black;
  background: #eee;
}

.sticky {
  position: sticky;
  left: 0;
  z-index: 1;
  background: lightblue;
}
<div >
  <aside>
    My aside
  </aside>
  <div >
    <div >
      <div >Col 1</div>
      <div >Col 2</div>
      <div >Col 3</div>
      <div >Col 4</div>
    </div>
    <div >
      <div >Col 1</div>
      <div >Col 2</div>
      <div >Col 3</div>
      <div >Col 4</div>
    </div>
    <div >
      <div >Col 1</div>
      <div >Col 2</div>
      <div >Col 3</div>
      <div >Col 4</div>
    </div>
    <div >
      <div >Col 1</div>
      <div >Col 2</div>
      <div >Col 3</div>
      <div >Col 4</div>
    </div>
    <div >
      <div >Col 1</div>
      <div >Col 2</div>
      <div >Col 3</div>
      <div >Col 4</div>
    </div>
    <div >
      <div >Col 1</div>
      <div >Col 2</div>
      <div >Col 3</div>
      <div >Col 4</div>
    </div>
    <div >
      <div >Col 1</div>
      <div >Col 2</div>
      <div >Col 3</div>
      <div >Col 4</div>
    </div>
    <div >
      <div >Col 1</div>
      <div >Col 2</div>
      <div >Col 3</div>
      <div >Col 4</div>
    </div>
    <div >
      <div >Col 1</div>
      <div >Col 2</div>
      <div >Col 3</div>
      <div >Col 4</div>
    </div>
    <div >
      <div >Col 1</div>
      <div >Col 2</div>
      <div >Col 3</div>
      <div >Col 4</div>
    </div>
  </div>
</div>

CodePudding user response:

So the problem actually falls with the min-width set on .table. The width is not defined to the end of the row which is affecting the behavior of the sticky elements at row-end.

You'll notice if you exchange min-width: 0; to min-width: 100%; it functions as you would like, but then the table overflows outside of .container.

A stickily positioned element is treated as relatively positioned until its containing block crosses a specified threshold (such as setting top to value other than auto) within its flow root.

MDN CSS/Position

So with that said, the elements with the scroll need to have a defined width so the sticky element knows to stay sticky.

A simple solution would be to nest all of the .table elements in another wrapper that has a defined width. I chose 300px based on the rendered width of the content and the container.

body {
  display: flex;
  align-items: center;
  justify-content: center;
  height: 100vh;
}

.container {
  display: flex;
  width: 300px;
  padding: 0.5rem;
  border: 1px solid red;
}

aside {
  padding-right: 1rem;
  width: 100px;
}

.table {
  min-width: 0;
  overflow: scroll;
}

.row {
  display: grid;
  grid-template-columns: repeat(4, 100px);
}

.col {
  border: 1px solid black;
  background: #eee;
}

.sticky {
  position: sticky;
  left: 0;
  z-index: 1;
  background: lightblue;
}

.wrapper {
  width: 300px;
}
<div >
  <aside>
    My aside
  </aside>
  <div >
    <div >
      <div >
        <div >Col 1</div>
        <div >Col 2</div>
        <div >Col 3</div>
        <div >Col 4</div>
      </div>
      <div >
        <div >Col 1</div>
        <div >Col 2</div>
        <div >Col 3</div>
        <div >Col 4</div>
      </div>
      <div >
        <div >Col 1</div>
        <div >Col 2</div>
        <div >Col 3</div>
        <div >Col 4</div>
      </div>
      <div >
        <div >Col 1</div>
        <div >Col 2</div>
        <div >Col 3</div>
        <div >Col 4</div>
      </div>
      <div >
        <div >Col 1</div>
        <div >Col 2</div>
        <div >Col 3</div>
        <div >Col 4</div>
      </div>
      <div >
        <div >Col 1</div>
        <div >Col 2</div>
        <div >Col 3</div>
        <div >Col 4</div>
      </div>
      <div >
        <div >Col 1</div>
        <div >Col 2</div>
        <div >Col 3</div>
        <div >Col 4</div>
      </div>
      <div >
        <div >Col 1</div>
        <div >Col 2</div>
        <div >Col 3</div>
        <div >Col 4</div>
      </div>
      <div >
        <div >Col 1</div>
        <div >Col 2</div>
        <div >Col 3</div>
        <div >Col 4</div>
      </div>
      <div >
        <div >Col 1</div>
        <div >Col 2</div>
        <div >Col 3</div>
        <div >Col 4</div>
      </div>
    </div>
  </div>
</div>

  • Related