【问题标题】:Table that occupies full width even when the columns don't即使列不占满宽度的表格
【发布时间】:2019-11-14 14:56:26
【问题描述】:

我有一张这样的 HTML 表格:

table { border-collapse: collapse; }

table thead th:nth-child(1) { width: 180px }
table thead th:nth-child(2) { width: 150px }
table thead th:nth-child(3) { width: 170px }

table thead tr { border-bottom:2px solid #222; }
table tbody tr { border-top:1px solid #ddd; }
table tbody tr:hover { background: #def; }

table tbody td { height: 40px; }
<div>
  <table>
    <thead>
      <tr>
        <th>Heading 1</th>
        <th>Heading 2</th>
        <th>Heading 3</th>
      </tr>
    </thead>
    <tbody>
      <tr>
        <td>Content 1 1</td>
        <td>Content 1 2</td>
        <td>Content 1 3</td>
      </tr>
      <tr>
        <td>Content 2 1</td>
        <td>Content 2 2<br>Line 2<br>Line 3<br>Line 4</td>
        <td>Content 2 3</td>
      </tr>
      <tr>
        <td>Content 3 1</td>
        <td>Content 3 2</td>
        <td>Content 3 3</td>
      </tr>
    </tbody>
  </table>
</div>

列将具有不同的固定宽度值,在 CSS 中指定,这将定义表格的大小。在上面的示例中,列分别为 180px、150px 和 170px,因此表格将是 500px 宽。

由于设计的原因,我们需要让表格占容器的 100%不调整列的大小。这意味着,例如,如果屏幕为 900 像素,列仍将占用它们的 500 像素,但表格应拉伸到容器的末尾以占用剩余的 400 像素。

将表格宽度设置为 100%,并添加一个自动占据剩余空间的新列将解决此问题。但是我们被要求避免添加这样的列,因为屏幕阅读器会遍历它并将其作为一个空单元格读取,这可能会让用户感到困惑。

一个hacky选项是添加一个占据整个页面宽度的伪元素(包装div有一个overflow: hidden,如下面的演示)。但是这个解决方案的问题是,如果表格的列占据的宽度超过了页面的宽度,我们希望包含的 div 滚动,但是我们会看到看起来像一个巨大的空行。

table { border-collapse: collapse; }

table thead th:nth-child(1),
table thead th:nth-child(1) { min-width: 180px }
table thead th:nth-child(2) { min-width: 150px }
table thead th:nth-child(3) { min-width: 170px }

table thead tr { border-bottom:2px solid #222; }
table tbody tr:not(:first-child) { border-top:1px solid #ddd; }
table tbody tr:hover { background: #def; }

table tbody td { height: 40px; }

div {
  overflow: hidden;
}
table tr::after {
  content: "";
  display: block;
  width: 100vw;
}
<div>
  <table>
    <thead>
      <tr>
        <th>Heading 1</th>
        <th>Heading 2</th>
        <th>Heading 3</th>
      </tr>
    </thead>
    <tbody>
      <tr>
        <td>Content 1 1</td>
        <td>Content 1 2</td>
        <td>Content 1 3</td>
      </tr>
      <tr>
        <td>Content 2 1</td>
        <td>Content 2 2<br>Line 2<br>Line 3<br>Line 4</td>
        <td>Content 2 3</td>
      </tr>
      <tr>
        <td>Content 3 1</td>
        <td>Content 3 2</td>
        <td>Content 3 3</td>
      </tr>
    </tbody>
  </table>
</div>

是否有一种可访问的方式让表格占据整个宽度,但列仅占据分配的宽度?

【问题讨论】:

  • 你真的需要表格来占据那个空间,还是仅仅需要出现来占据这个空间?
  • @steveax 无论哪种方式都可以,只要列保持在指定的宽度。

标签: html css html-table accessibility


【解决方案1】:

我建议将第三列的宽度更改为width: auto,以左对齐表格标题(th)的内容并将表格的width 设置为100%。这会将第三列拉伸到页面的右边框。

要强制第三列的内容不超过 170px,可以将padding-right: calc(100% - 500px); 添加到第三列的规则中:

table {
  border-collapse: collapse;
  width: 100%;
}

table thead th:nth-child(1) {
  width: 180px
}

table thead th:nth-child(2) {
  width: 150px
}

table thead th:nth-child(3),
table tbody td:nth-child(3){
  width: auto;
  padding-right: calc(100% - 500px);
}

table thead tr {
  border-bottom: 2px solid #222;
}

table tbody tr {
  border-top: 1px solid #ddd;
}

table tbody tr:hover {
  background: #def;
}

table tbody td {
  height: 40px;
}

th {
  text-align: left;
}
<div>
  <table>
    <thead>
      <tr>
        <th>Heading 1</th>
        <th>Heading 2</th>
        <th>Heading 3</th>
      </tr>
    </thead>
    <tbody>
      <tr>
        <td>Content 1 1</td>
        <td>Content 1 2</td>
        <td>Content 1 3</td>
      </tr>
      <tr>
        <td>Content 2 1</td>
        <td>Content 2 2<br>Line 2<br>Line 3<br>Line 4</td>
        <td>Content 2 3</td>
      </tr>
      <tr>
        <td>Content 3 1</td>
        <td>Content 3 2</td>
        <td>Content 3 3 lots of content lots of content lots of content </td>
      </tr>
    </tbody>
  </table>
</div>

【讨论】:

  • 这个解决方案的一个问题是,如果第三列有很多内容,它不会像设计所期望的那样在 170px 之后换行。
  • @AlvaroMontoro 啊,好吧,我不明白那个细节,对不起。但是我改变了我的答案,我认为它现在应该符合你的条件 - 请看一下。
【解决方案2】:

我会考虑让最后一列始终填充剩余空间并使用内部填充来强制内容具有固定宽度,因为它不会溢出填充。

如果你想要一个准确的结果,只需注意计算:

table {
  border-collapse: collapse;
}

table thead th:nth-child(1),
table thead th:nth-child(1) {
  min-width: 180px
}

table thead th:nth-child(2) {
  min-width: 150px
}

table thead th:nth-child(3),
table tr td:nth-child(3){
  width: 100%;
  min-width:170px;
  /*2x2px + 1px is for the default border-spacing*/
  padding-right:calc(100% - 150px - 180px - 170px - (2*2px + 1px)); 
}

table thead tr {
  border-bottom: 2px solid #222;
}

table tbody tr:not(:first-child) {
  border-top: 1px solid #ddd;
}

table tbody tr:hover {
  background: #def;
}

table tbody td {
  height: 40px;
}

div {
  overflow: hidden;
}
<div>
  <table>
    <thead>
      <tr>
        <th>Heading 1</th>
        <th>Heading 2</th>
        <th>Heading 3</th>
      </tr>
    </thead>
    <tbody>
      <tr>
        <td>Content 1 1</td>
        <td>Content 1 2</td>
        <td>Content 1 3</td>
      </tr>
      <tr>
        <td>Content 2 1</td>
        <td>Content 2 2<br>Line 2<br>Line 3<br>Line 4</td>
        <td>Content 2 3</td>
      </tr>
      <tr>
        <td>Content 3 1 with very long word here</td>
        <td>Content 3 2</td>
        <td>Content 3 3 with very long word here</td>
      </tr>
    </tbody>
  </table>
</div>

相同的想法不同的价值:

table {
  border-collapse: collapse;
}

table thead th:nth-child(1),
table thead th:nth-child(1) {
  width: 180px
}

table thead th:nth-child(2) {
  width: 150px
}

table thead th:nth-child(3),
table tr td:nth-child(3){
  width: calc(100% - 150px - 180px - 2*2px);
  min-width:170px;
  /*3x2px + 1px is for the default border-spacing*/
  padding-right:calc(100% - 150px - 180px - 170px - (2*2px + 1px)); 
}

table thead tr {
  border-bottom: 2px solid #222;
}

table tbody tr:not(:first-child) {
  border-top: 1px solid #ddd;
}

table tbody tr:hover {
  background: #def;
}

table tbody td {
  height: 40px;
}

div {
  overflow: hidden;
}
<div>
  <table>
    <thead>
      <tr>
        <th>Heading 1</th>
        <th>Heading 2</th>
        <th>Heading 3</th>
      </tr>
    </thead>
    <tbody>
      <tr>
        <td>Content 1 1</td>
        <td>Content 1 2</td>
        <td>Content 1 3</td>
      </tr>
      <tr>
        <td>Content 2 1</td>
        <td>Content 2 2<br>Line 2<br>Line 3<br>Line 4</td>
        <td>Content 2 3</td>
      </tr>
      <tr>
        <td>Content 3 1 with very long word here</td>
        <td>Content 3 2</td>
        <td>Content 3 3 with very long word here</td>
      </tr>
    </tbody>
  </table>
</div>

【讨论】:

    【解决方案3】:

    我们选择的解决方案可能是最简单的事情:添加额外的空列 - 因为它没有任何特定宽度,它会拉伸并扩展以填充剩余空间 -...和在该列的单元格中添加aria-ignore="true"

    还是有点hacky,但是在 Chrome(带有 VoiceOver 和 ChromeVox)、Firefox(带有 NVDA)和 Internet Explorer 11(带有 NVDA 和 JAWS)中测试后,所有屏幕阅读器都忽略了这一点单元格(用户无法使用键盘导航到该单元格),甚至不计入列数(读者将阅读“进入/退出包含四行三列的表格”)。

    代码如下:

    table { border-collapse: collapse; }
    
    table thead th:nth-child(1) { width: 180px }
    table thead th:nth-child(2) { width: 150px }
    table thead th:nth-child(3) { width: 170px }
    
    table thead tr { border-bottom:2px solid #222; }
    table tbody tr { border-top:1px solid #ddd; }
    table tbody tr:hover { background: #def; }
    
    table tbody td { height: 40px; }
    
    table {
      width: 100%;
      table-layout: fixed;
    }
    <div>
      <table>
        <thead>
          <tr>
            <th>Heading 1</th>
            <th>Heading 2</th>
            <th>Heading 3</th>
            <th aria-hidden="true"></th>
          </tr>
        </thead>
        <tbody>
          <tr>
            <td>Content 1 1</td>
            <td>Content 1 2</td>
            <td>Content 1 3</td>
            <td aria-hidden="true"></td>
          </tr>
          <tr>
            <td>Content 2 1</td>
            <td>Content 2 2<br>Line 2<br>Line 3<br>Line 4</td>
            <td>Content 2 3</td>
            <td aria-hidden="true"></td>
          </tr>
          <tr>
            <td>Content 3 1</td>
            <td>Content 3 2</td>
            <td>Content 3 3</td>
            <td aria-hidden="true"></td>
          </tr>
        </tbody>
      </table>
    </div>

    【讨论】:

      猜你喜欢
      • 2020-08-13
      • 2015-04-27
      • 1970-01-01
      • 2013-09-07
      • 2020-11-29
      • 1970-01-01
      • 2019-11-22
      • 1970-01-01
      • 2014-06-14
      相关资源
      最近更新 更多