我该如何在边框相交的地方放置+ 号,就像终端应用中那样?

前端开发 2026-07-11

我想以在终端程序中显示表格的方式来展示它:

body {
  width: 100%;
  font-family: "Fira Code", "Consolas", "Courier New", monospace;
}

table {
  border-right: 1px dashed;
  border-collapse: collapse;
}

td,th {
  border: 1px dashed;
}
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8">
    <link rel="stylesheet" href="./style.css">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Pen</title>
  </head>
  <body>
    <table>
      <thead>
        <tr>
          <th>Col1</th>
          <th>Col2</th>
        </tr>
      </thead>
      <tbody>
        <tr>
          <td>Col1</td>
          <td>Col2</td>
        </tr>
      </tbody>
      <tfoot>
        <tr>
          <td>Col1</td>
          <td>Col2</td>
        </tr>
      </tfoot>
    </table>

  </body>
</html>

通常在命令行/终端程序中的表格就是这样显示的:

+----------+---------+-----------+
| col1     | col2    | col3      |
+----------+---------+-----------+
| v1       | 3.0.0   |         1 |
| v2       | 1.0.2   |         1 |
| v3       | 1.0     |         1 |
| v4       | 3.3.1   |         1 |
+----------+---------+-----------+

如何将 + 字符放在边界相遇的位置?如果可能的话,我想用CSS的方式来实现,而不是用JS。

正如你所见,我目前只能勉强实现一个虚线边框,你知道怎么做到吗?

解决方案

如果你真的想要达到与终端字符轮廓表格相同的效果,你必须同时使用用于点状线、竖线以及+ 字符的字符。

这个代码片段实现了这个功能,但它只是额外增加了一列来放置最后的竖边框——换言之,HTML的语义被略微改变。否则它使用 ::before和 ::after伪元素来承载形成边框的字符。

另请注意,如果表格主体只有一行,你需要插入一个“备用”的tr,并放入相应的td,以便绘制底部边框。

<style>
  * {
    box-sizing: border-box;
  }

  table {
    font-family: monospace;
    border-collapse: collapse;
  }

  tr>*:nth-child(1) {
    --w: 11;
  }

  tr>*:nth-child(2) {
    --w: 9;
  }

  tr>*:nth-child(3) {
    --w: 12;
  }

  /* the following sets the column text right aligned without moving the before element */
  tbody>tr>td:nth-child(3) {
    text-align: right;
  }

  tbody>tr>*:nth-child(3)::before {
    text-align: left !important;
    position: absolute !important;
  }

  tr>*:nth-child(4) {
    --w: 0;
  }

  th,
  td {
    width: calc(var(--w) * 1ch);
    position: relative;
    padding: 0;
    text-align: left;
    overflow: hidden;
  }

  tr:first-child th,
  tr:first-child td {
    height: 2lh;
    padding-top: 1lh;
  }

  th::before,
  td::before {
    content: '| ';
    position: absolute;
    position: relative;
    left: 0;
  }

  th::after,
  td::after {
    position: absolute;
    position: relative;
  }

  tr:first-child th::after,
  tr:first-child td::after,
  tbody tr:last-child td::after {
    content: '+-----------------------------------------';
    position: absolute;
    left: 0;
    width: 100%;
    height: 1lh;
    overflow: hidden;
    display: block;
    padding: 0 !important;
  }

  tr:first-child>*::after {
    top: 0;
  }

  tbody tr:last-child {
    height: 2lh;
    vertical-align: top;
  }

  tbody tr:last-child td::after {
    bottom: 0;
  }
</style>
<table>
  <thead>
    <tr>
      <th>Col1</th>
      <th>Col2</th>
      <th>Col3</th>
      <th></th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>v1</td>
      <td>3.0.0</td>
      <td>1</td>
      <td></td>
    </tr>
    <tr>
      <td>v2</td>
      <td>1.0.2</td>
      <td>1</td>
      <td></td>
    </tr>
    <tr>
      <td>v3</td>
      <td>1.0.1</td>
      <td>1</td>
      <td></td>
    </tr>
  </tbody>
</table>
站内所有文章版权归属LeftHeroAI导航站,无授权禁止任何主体转载、抄袭、复制内容,亦不得私自架设镜像站点。一经侵权,本站将通过法律途径追责。

相关文章