表头位置:sticky和边框问题

47
我有一张表格,想要将表头固定在页面顶部,参考这篇文章进行操作。但是我的表格样式中表头有上下边框。我不明白的是,应用在元素上的上下边框会随着表格的滚动消失而不是跟随"固定"的表头单元格一起停留在页面顶部。有没有什么办法可以解决这个问题呢?可在此处找到样例。

let string = ''
console.log("oj")
for(let i=0; i<100; i++) {
  string += `
        <tr>
          <td>Malcolm Reynolds</td>
          <td>Captain</td>
          <td>9035749867</td>
          <td>mreynolds</td>
        </tr>
  `
}
document.getElementsByTagName('tbody')[0].innerHTML += string
.table-sticky-container {
  height: 200px;
  overflow-y: scroll;
  border-top: 1px solid green;
  border-bottom: 1px solid green;
}

.table-sticky {

  th {
    position: sticky;
    top: 0;
    z-index: 2;
    border-top: 1px solid red !important;
    border-bottom: 2px solid red !important;
  }
}
<div class="table-sticky-container">
  <table class="table table-sticky">
    <thead class="thead-light">
      <tr>
        <th scope="col">Name</th>
        <th scope="col">Title</th>
        <th scope="col">ID</th>
        <th scope="col">Username</th>
      </tr>
    </thead>
    <tbody>
      <tr>
          <td>Malcolm Reynolds</td>
          <td>Captain</td>
          <td>9035749867</td>
          <td>mreynolds</td>
        </tr>
    </tbody>
  </table>
</div>

这个回答解决了你的问题吗?边框样式在sticky定位元素中不起作用 - DisgruntledGoat
4个回答

59
你可以添加。
.table {
  border-collapse: separate;
}

但不幸的是,这看起来很糟糕,更好的解决方案是使用伪元素添加一个解决方法。

th:after,
th:before {
  content: '';
  position: absolute;
  left: 0;
  width: 100%;
}

th:before {
  top: -1px;
  border-top: 1px solid red;
}

th:after {
  bottom: -1px;
  border-bottom: 2px solid red;
}

.table-sticky-container {
  height: 200px;
  overflow-y: scroll;
  border-top: 1px solid green;
  border-bottom: 1px solid green;
}

.table-sticky th {
  position: -webkit-sticky;
  position: sticky;
  top: 0;
  z-index: 2;
}

th:after,
th:before {
  content: '';
  position: absolute;
  left: 0;
  width: 100%;
}

th:before {
  top: -1px;
  border-top: 1px solid red;
}

th:after {
  bottom: -1px;
  border-bottom: 2px solid red;
}
<link rel='stylesheet' href='https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.1.3/css/bootstrap.min.css'>

<div class="table-sticky-container">
    <table class="table table-sticky">
      <thead class="thead-light">
        <tr>
          <th scope="col">Name</th>
          <th scope="col">Title</th>
          <th scope="col">ID</th>
          <th scope="col">Username</th>
        </tr>
      </thead>
      <tbody>
        <tr>
          <td>Malcolm Reynolds</td>
          <td>Captain</td>
          <td>9035749867</td>
          <td>mreynolds</td>
        </tr>
        <tr>
          <td>Zoe Washburne</td>
          <td>First Officer</td>
          <td>8908980980</td>
          <td>zwashburne</td>
        </tr>
        <tr>
          <td>Kaylee Frye</td>
          <td>Engineer</td>
          <td>6678687678</td>
          <td>kfrye</td>
        </tr>
        <tr>
          <td>Malcolm Reynolds</td>
          <td>Captain</td>
          <td>9035749867</td>
          <td>mreynolds</td>
        </tr>
        <tr>
          <td>Zoe Washburne</td>
          <td>First Officer</td>
          <td>8908980980</td>
          <td>zwashburne</td>
        </tr>
        <tr>
          <td>Kaylee Frye</td>
          <td>Engineer</td>
          <td>6678687678</td>
          <td>kfrye</td>
        </tr>
      </tbody>
    </table>
  </div>

第二种解决方案

.table {
  border-collapse: collapse;
}

.table-sticky thead th {
  position: -webkit-sticky;
  position: sticky;
  top: 0;
  z-index: 2;
  box-shadow: inset 0 1px 0 red, inset 0 -2px 0 red;
}

2
那很有效。我注意到在边框“应该”存在的间隙中,我可以看到我的标题“后面”的内容。因此我将“top”和“bottom”设为-1px。 - Steve
2
我添加了第二个解决方案,使用了box-shadow。 - Grzegorz T.
1
我理解追求图形完美主义者的想法; - Grzegorz T.
2
正如@sarthakc所建议的那样,将第一个解决方案与border-spacing: 0;相结合,看起来很不错! - Sebastien
第一种解决方案有什么问题,在我的项目中,我所有的东西都是一样的,但当我滚动网站时,thead是粘性的,但thead的背景颜色消失了。 - Robert Głowacki
感谢您提供出色的解决方案。在众多我找到的代码中,这是唯一一个能够正确处理thead内部的rowspan和colspan(尽管需要将“th {position: relative}”添加到代码中)。 - tomasz86

36

您可以添加

.table {
  border-collapse: separate;
  border-spacing: 0;
}

2
这是最优解。 - cage rattler
1
这样做要好得多,您可以看到标题后面的内容影响非常小。 - mslugx
1
我唯一的问题是,如果您的边框> 1px,则会导致边框宽度略微不一致。 - nullromo
1
你如何处理现在边框最小为2像素的事实?我无论如何都无法使边框变得更薄。 - Melendowski
太棒了,谢谢你。我在这个问题上苦苦思索。 - mr.pribesh
终于!所有的解决方案都显得过于复杂。我知道只要我继续搜索,就能找到简单的解决办法。谢谢! - undefined

5

不要使用 border-collapse,可以按照以下方式绘制线条:

td, th {
    border-bottom: 1px solid grey;
    border-right: 1px solid grey;
}

table {
    border-spacing: 0px;
    border-left: 1px solid grey
}

th {
    background-color:#c5e8ec;
    position: sticky;
    position: -webkit-sticky;
    border-top: 1px solid grey;
    top:0;
}

0

另一个可行的解决方案(在最新的Chrome和FF上测试通过)- 用div包装th/td内容,使用这些div的边框而不是单元格的边框。

<div class="wrapper">
  <table>
  <thead>
    <tr>
      <th>
        <div class="cell">head1</div>
      </th>
      <th>
        <div class="cell">head2</div>
      </th>
      <th>
        <div class="cell">head3</div>
      </th>
      <th>
        <div class="cell">head4</div>
      </th>
      <th>
        <div class="cell">head5</div>
      </th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>
        <div class="cell">1</div>
      </td>
      <td>
        <div class="cell">1</div>
      </td>
      <td>
        <div class="cell">1</div>
      </td>
      <td>
        <div class="cell">1</div>
      </td>
      <td>
        <div class="cell">1</div>
      </td>
    </tr>
    <tr>
      <td>
        <div class="cell">1</div>
      </td>
      <td>
        <div class="cell">1</div>
      </td>
      <td>
        <div class="cell">1</div>
      </td>
      <td>
        <div class="cell">1</div>
      </td>
      <td>
        <div class="cell">1</div>
      </td>
    </tr>
    <tr>
      <td>
        <div class="cell">1</div>
      </td>
      <td>
        <div class="cell">1</div>
      </td>
      <td>
        <div class="cell">1</div>
      </td>
      <td>
        <div class="cell">1</div>
      </td>
      <td>
        <div class="cell">1</div>
      </td>
    </tr>
  </tbody>
</table>
</div>

table {
  border-collapse: collapse;
  table-layout: fixed;
  width: 500px;
}

.wrapper {
  height: 150px;
  overflow: auto;
}

td, th {
  width: 150px;
  height: 50px;
  text-align: center;
  font-size: 32px;
  padding: 0;
}

th {
  position: sticky;
  top: 0;
  left: 0;
  background-color: #fff;
}

.cell {
  border: 1px solid black;
  height: 100%;
}

td .cell {
  border-top: none;
  border-left: none;
}

th .cell {
  border-left: none;
}

td:first-child .cell,
th:first-child .cell {
  border-left: 1px solid black;
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接