【问题标题】:Table headers position:sticky and border issue表头位置:粘性和边框问题
【发布时间】:2019-12-01 14:50:34
【问题描述】:

我有一个表格,我正在尝试获取粘性标题,遵循this article。除了我的表格样式在顶部和底部都有带边框的标题。

我不明白的部分是应用于th 的顶部/底部边框与表格的其余部分一起滚动,而不是与“卡住”的标题单元格一起滚动。对此有什么可以做的吗?

工作示例可以在这里找到:https://codepen.io/smlombardi/pen/MNKqQY?editors=1100#0

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>

【问题讨论】:

    标签: html css twitter-bootstrap


    【解决方案1】:

    你可以添加

    .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;
     }
    

    【讨论】:

    • 行得通。我注意到我可以在边框“应该”的间隙中看到标题“后面”的内容。所以我将“top”和“bottom”设置为-1px。
    • 我添加了第二个解决方案宽度 box-shadow。
    • 我了解图形纯粹主义者 ;)
    • 正如@sarthakc 建议的那样,将第一个解决方案与border-spacing: 0; 结合起来,看起来不错!
    • 第一个解决方案有什么问题,在我的项目中,我的一切都一样,但是当我滚动网站时,广告很粘,但广告的背景颜色消失了
    【解决方案2】:

    你可以添加

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

    【讨论】:

    • 这是最优解。
    • 这样更好,你看到标题后面内容的效果非常小。
    • 我唯一的问题是,如果您的边框 > 1px,那么您的边框宽度最终会出现非常轻微的不一致。
    • 您如何处理现在边框最小为 2px 的事实?我一辈子都做不到让边框变薄。
    【解决方案3】:

    不要使用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;
    }
    

    【讨论】:

      【解决方案4】:

      Another working solution(在 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;
      }
      

      【讨论】:

        【解决方案5】:

        这里是用于 mui 材质表的 CSB,在 Chrome、FF、Edge 和 Safari 中测试

        https://codesandbox.io/s/mui-material-table-sticky-header-with-borders-fsmnd?file=/src/App.tsx

        在这种情况下,关键是在桌子上取消边框折叠:

        const TableSticky = (props: TableProps) => {
          const { sx, ...other } = props;
          return (
            <Table
              sx={{
                borderCollapse: "unset",
                borderLeft: border,
                ...sx,
              }}
              size="small"
              {...other}
            />
          );
        };
        

        在标题列而不是表格上使用 postion:sticky 也很聪明:

        const HeadCell = (props: TableCellProps) => {
          const { sx, ...other } = props;
          const theme = useTheme();
        
          return (
            <TableCell
              sx={{
                borderBottom: border,
                borderRight: border,
                borderTop: border,
                position: "sticky",
                top: 0,
                backgroundColor: theme.palette.background.default,
                ...sx
              }}
              {...other}
            />
          );
        };
        

        【讨论】:

          猜你喜欢
          • 2018-04-30
          • 1970-01-01
          • 2021-09-08
          • 1970-01-01
          • 2018-10-25
          • 2021-09-03
          • 1970-01-01
          • 2020-08-04
          • 2020-09-08
          相关资源
          最近更新 更多