css 网格的粘性列问题

Sticky column issue with css grid

这是说明问题的代码笔:https://codepen.io/robertcooper_rc/pen/jOYbdbR

我正在使用 CSS 网格创建 table 布局。它运行良好,但我对网格中其中一列的 position: sticky 的行为有疑问。

我有一个水平滚动的 table,有 4 列,第一列是粘性的。

当我向右滚动时,第一列确实像预期的那样粘在左边。

但是,当滚动开始接近 table 水平 space 的末尾时,第一个不再保持其在 table 左边缘的粘性位置。

我注意到,如果我删除 <aside> 的 HTML 标记,粘滞列行为将按预期工作。但是,我需要 <aside> 存在。

关于如何在保持 DOM 结构的同时使用 CSS 解决此问题的任何想法?

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 class="container">
  <aside>
    My aside
  </aside>
  <div class="table">
    <div class="row">
      <div class="col sticky">Col 1</div>
      <div class="col">Col 2</div>
      <div class="col">Col 3</div>
      <div class="col">Col 4</div>
    </div>
    <div class="row">
      <div class="col sticky">Col 1</div>
      <div class="col">Col 2</div>
      <div class="col">Col 3</div>
      <div class="col">Col 4</div>
    </div>
    <div class="row">
      <div class="col sticky">Col 1</div>
      <div class="col">Col 2</div>
      <div class="col">Col 3</div>
      <div class="col">Col 4</div>
    </div>
    <div class="row">
      <div class="col sticky">Col 1</div>
      <div class="col">Col 2</div>
      <div class="col">Col 3</div>
      <div class="col">Col 4</div>
    </div>
    <div class="row">
      <div class="col sticky">Col 1</div>
      <div class="col">Col 2</div>
      <div class="col">Col 3</div>
      <div class="col">Col 4</div>
    </div>
    <div class="row">
      <div class="col sticky">Col 1</div>
      <div class="col">Col 2</div>
      <div class="col">Col 3</div>
      <div class="col">Col 4</div>
    </div>
    <div class="row">
      <div class="col sticky">Col 1</div>
      <div class="col">Col 2</div>
      <div class="col">Col 3</div>
      <div class="col">Col 4</div>
    </div>
    <div class="row">
      <div class="col sticky">Col 1</div>
      <div class="col">Col 2</div>
      <div class="col">Col 3</div>
      <div class="col">Col 4</div>
    </div>
    <div class="row">
      <div class="col sticky">Col 1</div>
      <div class="col">Col 2</div>
      <div class="col">Col 3</div>
      <div class="col">Col 4</div>
    </div>
    <div class="row">
      <div class="col sticky">Col 1</div>
      <div class="col">Col 2</div>
      <div class="col">Col 3</div>
      <div class="col">Col 4</div>
    </div>
  </div>
</div>

所以问题实际上出在.table 上的min-width 设置上。行末未定义宽度,这会影响 row-end.

处的粘性元素的行为

您会注意到,如果将 min-width: 0; 交换为 min-width: 100%;,它会按照您的意愿运行,但是 table 会溢出到 .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

也就是说,滚动的元素需要有一个定义的宽度,这样粘性元素就知道保持粘性。

一个简单的解决方案是将所有 .table 元素嵌套在另一个具有已定义宽度的包装器中。我根据内容和容器的渲染宽度选择了300px

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 class="container">
  <aside>
    My aside
  </aside>
  <div class="table">
    <div class="wrapper">
      <div class="row">
        <div class="col sticky">Col 1</div>
        <div class="col">Col 2</div>
        <div class="col">Col 3</div>
        <div class="col">Col 4</div>
      </div>
      <div class="row">
        <div class="col sticky">Col 1</div>
        <div class="col">Col 2</div>
        <div class="col">Col 3</div>
        <div class="col">Col 4</div>
      </div>
      <div class="row">
        <div class="col sticky">Col 1</div>
        <div class="col">Col 2</div>
        <div class="col">Col 3</div>
        <div class="col">Col 4</div>
      </div>
      <div class="row">
        <div class="col sticky">Col 1</div>
        <div class="col">Col 2</div>
        <div class="col">Col 3</div>
        <div class="col">Col 4</div>
      </div>
      <div class="row">
        <div class="col sticky">Col 1</div>
        <div class="col">Col 2</div>
        <div class="col">Col 3</div>
        <div class="col">Col 4</div>
      </div>
      <div class="row">
        <div class="col sticky">Col 1</div>
        <div class="col">Col 2</div>
        <div class="col">Col 3</div>
        <div class="col">Col 4</div>
      </div>
      <div class="row">
        <div class="col sticky">Col 1</div>
        <div class="col">Col 2</div>
        <div class="col">Col 3</div>
        <div class="col">Col 4</div>
      </div>
      <div class="row">
        <div class="col sticky">Col 1</div>
        <div class="col">Col 2</div>
        <div class="col">Col 3</div>
        <div class="col">Col 4</div>
      </div>
      <div class="row">
        <div class="col sticky">Col 1</div>
        <div class="col">Col 2</div>
        <div class="col">Col 3</div>
        <div class="col">Col 4</div>
      </div>
      <div class="row">
        <div class="col sticky">Col 1</div>
        <div class="col">Col 2</div>
        <div class="col">Col 3</div>
        <div class="col">Col 4</div>
      </div>
    </div>
  </div>
</div>