嵌套HTML表的匹配表高度

时间:2018-09-25 13:00:04

标签: javascript jquery html css html-table

我正在尝试在一个表行中嵌套表,同时保持单个表的外观,如下面的示例所示(一个表,其中一行包含一个数据值,两个表嵌套,一个2x2,另一个嵌套3x3):

enter image description here

这只是一个例子;实际的表具有更多的行和列。我之所以要使用表格,是因为可以自然地重排列宽和行高以适合表格数据,而不必担心容器大小(即表格宽度= 100%)。

我遇到的问题是,最高的表设置了行高,但是其他表没有扩展以填充该高度,因此内部边框不会从顶部延伸到底部,如结果所示片段:

.display {
	border-collapse: collapse;
}
.display, .display td, .display th {
	border: 1px solid black;
}
.subtable {
	border-collapse: collapse;
}
.subtable td {
	border-top: 0;
	border-bottom: 1px solid black;
	border-left: 0;
	border-right: 1px solid black;
}
.subtable tr td:last-of-type {
	border-top: 0;
	border-bottom: 1px solid black;
	border-left: 0;
  border-right: 0;
}
.subtable tr:last-of-type td {
	border-top: 0;
	border-bottom: 0;
	border-left: 0;
	border-right: 1px solid black;
}
.subtable tr:last-of-type td:last-of-type {
	border: 0;
}
td {
	padding: 5px;
}
td.d-subtable {
	padding: 0;
}
<table class="display" cellpadding="0">
	<tr><th>Customer</th><th>Items</th><th>Payments</th></tr>
	<tr><td>Customer Name</td>
		<td class="d-subtable"><table class="subtable" cellpadding="0"><tr><td>Item1</td><td>5</td><td>$400.00</td></tr><tr><td>Item2</td><td>10</td><td>$200.00</td></tr><tr><td>Item3</td><td>2</td><td>$500.00</td></tr></table></td>
		<td class="d-subtable"><table class="subtable" cellpadding="0"><tr><td>12 Sep 2018</td><td>$3,000.00</td></tr><tr><td>18 Sep 2018</td><td>$2,000.00</td></tr></table></td>
	</tr>
</table>

enter image description here

现在我知道我可以使用rowspan解决此问题(这就是我当前正在解决的问题),但是这需要预先确定要排成一行的行,并且可能导致出现以下代码段所产生的问题,如果将rowspan="2"应用于具有两行的表格的第一行(而不是最后一行),显然会更好:

td {
  border: 1px solid black;
}

table {
  border-collapse: collapse;
  width: 500px;
}
<table cellpadding="5">
	<tr><td rowspan="3">x</td>
		<td>problem when you have some really long text in the first row</td><td>p</td><td>a</td><td>b</td><td>c</td></tr><tr><td rowspan="2">z</td><td rowspan="2">q</td><td>d</td><td>e</td><td>f</td></tr><tr><td>g</td><td>some other really long text</td><td>i</td>
  </tr>
</table>

enter image description here

我希望上面的表格看起来像这样:

enter image description here

是否有一种方法可以使用HTML / CSS来实现?表中有很多行,因此我更希望浏览器在渲染之前对其进行排序。但是,如果不可能,我可以使用Javascript / JQuery解决方案。

更新

尽管我当时确实找到了一个可行的解决方案(请参阅我发布的答案),但此后我遇到了一些情况,由于无法预期所有的变化,很难预先设置列的宽度(甚至是百分比)。可能显示的数据。因此,我希望找到一个不依赖于此的答案。

由于我没有像应该说的那样清晰明了,所以我有多个行要嵌套表格,同时保持高度和列宽的匹配。例如,对于两行,我希望能够创建这样的布局:

enter image description here

原始表格HTML的结果如下:

enter image description here

		.display {
			border-collapse: collapse;
		}
		.display, .display td, .display th {
			border: 1px solid black;
		}
		.subtable {
			border-collapse: collapse;
		}
		.subtable td {
			border-top: 0;
			border-bottom: 1px solid black;
			border-left: 0;
			border-right: 1px solid black;
		}
		.subtable tr td:last-of-type {
			border-top: 0;
			border-bottom: 1px solid black;
			border-left: 0;
			border-right: 0;
		}
		.subtable tr:last-of-type td {
			border-top: 0;
			border-bottom: 0;
			border-left: 0;
			border-right: 1px solid black;
		}
		.subtable tr:last-of-type td:last-of-type {
			border: 0;
		}
		td {
			padding: 5px;
		}
		td.d-subtable {
			padding: 0;
		}
<table class="display" cellpadding="0">
	<tr><th>Customer</th><th>Items</th><th>Payments</th></tr>
	<tr><td>Customer 1</td>
		<td class="d-subtable"><table class="subtable" cellpadding="0"><tr><td>Item1</td><td>5</td><td>$400.00</td></tr><tr><td>Item2</td><td>100</td><td>$20.00</td></tr><tr><td>Item3</td><td>2</td><td>$500.00</td></tr></table></td>
		<td class="d-subtable"><table class="subtable" cellpadding="0"><tr><td>12 Sep 2018</td><td>$3,000.00</td></tr><tr><td>18 Sep 2018</td><td>$2,000.00</td></tr></table></td>
	</tr>
	<tr><td>Customer 304</td>
		<td class="d-subtable"><table class="subtable" cellpadding="0"><tr><td>Item4</td><td>5</td><td>$6.00</td></tr></table></td>
		<td class="d-subtable"><table class="subtable" cellpadding="0"><tr><td>20 Sep 2018</td><td>$4.00</td></tr><tr><td>27 Sep 2018</td><td>$26.00</td></tr></table></td>
	</tr>
</table>

9 个答案:

答案 0 :(得分:10)

我最终可以通过编写一个onload函数来找到给定行中所有嵌套表的最大高度,然后将该行中每个嵌套表的高度设置为相同的值来解决此问题。

window.onload=function () {
    let rows = document.querySelectorAll('tr');
    for (let r = 0; r < rows.length; r++) {
        let subtables = rows[r].querySelectorAll('.subtable');
        let maxHeight = 0;
        for (let i = 0; i < subtables.length; i++) {
            maxHeight = Math.max(maxHeight, subtables[i].clientHeight);
        }
        for (let i = 0; i < subtables.length; i++) subtables[i].style.height='' + maxHeight + 'px';
    }
};

该解决方案的唯一缺点是,这意味着我必须为嵌套表中的<td>分配宽度。但是,由于我可以使用百分比宽度,所以这对我来说不是一个大问题:

<table class="display" cellpadding="0">
    <tr><th>Customer</th><th>Items</th><th>Payments</th></tr>
    <tr><td>Customer 1</td>
        <td class="d-subtable"><table class="subtable" cellpadding="0"><tr><td width="35%">Item1</td><td width="20%">5</td><td width="45%">$400.00</td></tr><tr><td>Item2</td><td>10</td><td>$200.00</td></tr><tr><td>Item3</td><td>2</td><td>$500.00</td></tr></table></td>
        <td class="d-subtable"><table class="subtable" cellpadding="0"><tr><td width="60%">12 Sep 2018</td><td width="40%">$3,000.00</td></tr><tr><td>18 Sep 2018</td><td>$2,000.00</td></tr></table></td>
    </tr>
    <tr><td>Customer 2</td>
        <td class="d-subtable"><table class="subtable" cellpadding="0"><tr><td width="35%">Item4</td><td width="20%">5</td><td width="45%">$600.00</td></tr></table></td>
        <td class="d-subtable"><table class="subtable" cellpadding="0"><tr><td width="60%">20 Sep 2018</td><td width="40%">$4,000.00</td></tr><tr><td>27 Sep 2018</td><td>$2,000.00</td></tr></table></td>
    </tr>
</table>

最终输出:

enter image description here

答案 1 :(得分:10)

我建议使用flex来满足您的需求。 Flex对于这种布局非常强大,因为我们可以轻松地让内容对其进行指导。请参阅附件。它完全由HTML和CSS制成。不需要固定大小,也不需要Javascript。

(旧代码段)

.outer {
  display: flex;
  flex-wrap: wrap;
  
  /* For demo purposes */
  max-width: 500px; 
  margin: 20px auto; 
  border-left: 1px solid black;
  border-top: 1px solid black;
}

.column {
  flex: 1 1 auto;
  display: flex;
  flex-direction: column;
  flex-wrap: wrap;
}

.row {
  display: flex;
  flex-direction: row;
  flex: 1 1 auto;
}

.inner {
  flex: 1 1 auto;
  display: flex;
  flex-direction: column;
}

.item {
  border-right: 1px solid black;
  border-bottom: 1px solid black;
  text-align: center;
  padding: 3px;
}

.item.heading {
  font-weight: bold;
}

.item:not(.heading) {
  flex: 1 1 auto;
  justify-content: center;
  align-items: center;
  display: flex;
}

.fixed .narrow {
  flex-basis: 20px;
}
<div class="outer">
  <div class="column">
    <div class="item heading">Customer</div>
    <div class="item">
      <span>Customer Name</span>
    </div>
  </div>
  <div class="column">
    <div class="item heading">Items</div>
      <div class="inner fixed">
        <div class="row">
          <div class="item">Item1</div>
          <div class="item narrow">5</div>
          <div class="item last">$400.00</div>
        </div>
        <div class="row">
          <div class="item">Item2</div>
          <div class="item narrow">10</div>
          <div class="item last">$200.00</div>
        </div>
        <div class="row">
          <div class="item">Item3</div>
          <div class="item narrow">2</div>
          <div class="item last">$500.00</div>
        </div>
    </div>
  </div>
  <div class="column">
    <div class="item heading">Payments</div>
    <div class="inner">
      <div class="row">
        <div class="item">12 sep 2018</div>
        <div class="item">$3,000.00</div>
      </div>
      <div class="row">
        <div class="item">
          18 sep 2018
        </div>
        <div class="item">
          $2,000.00
        </div>
      </div>
    </div>
  </div>
</div>

更新:已根据您的评论/答案进行了更改。它在某种程度上取决于您的HTML结构。我必须将标题移动到其自己的“ .row.row-item”,因此需要设置一个弹性基础以对齐列。可以使用多个“ .row.row-item”扩展。请参见下面的代码段。

.outer {
  display: flex;
  flex-wrap: wrap;
  
  /* For demo purposes */
  max-width: 600px; 
  margin: 20px auto; 
  border-left: 1px solid black;
  border-top: 1px solid black;
}

.column {
  flex: 1 1 33.33%;
  display: flex;
  flex-direction: column;
  flex-wrap: wrap;
}

.row {
  display: flex;
  flex-direction: row;
  flex: 1 1 auto;
}

.row-item {
  flex-basis: 100%;
}

.inner {
  flex: 1 1 auto;
  display: flex;
  flex-direction: column;
}

.item {
  border-right: 1px solid black;
  border-bottom: 1px solid black;
  text-align: center;
}

.item.heading {
  font-weight: bold;
  flex: 1 1 33.33%;
}

.item:not(.heading) {
  flex: 1 1 33.33%;
  justify-content: center;
  align-items: center;
  display: flex;
}

.fixed .narrow {
  flex: 1 1 20px;
}
<div class="outer">
  <div class="row row-item">
    <div class="item heading">Customer</div>
    <div class="item heading">Items</div>
    <div class="item heading">Payments</div>
  </div>
  <div class="row row-item">
    <div class="column">
      <div class="item">
        <span>Customer 1</span>
      </div>
    </div>
    <div class="column">
        <div class="inner fixed">
          <div class="row">
            <div class="item">Item1</div>
            <div class="item narrow">5</div>
            <div class="item last">$400.00</div>
          </div>
          <div class="row">
            <div class="item">Item2</div> 
            <div class="item narrow">10</div>
            <div class="item last">$200.00</div>
          </div>
          <div class="row">
            <div class="item">Item3</div>
            <div class="item narrow">2</div>
            <div class="item last">$500.00</div>
          </div>
      </div>
    </div>
    <div class="column">
      <div class="inner">
        <div class="row">
          <div class="item">12 sep 2018</div>
          <div class="item">$3,000.00</div>
        </div>
        <div class="row">
          <div class="item">
            18 sep 2018
          </div>
          <div class="item">
            $2,000.00
          </div>
        </div>
      </div>
    </div>
  </div>
  <div class="row row-item">
    <div class="column">
      <div class="item">
        <span>Customer 304</span>
      </div>
    </div>
    <div class="column">
        <div class="inner fixed">
          <div class="row">
            <div class="item">Item4</div>
            <div class="item narrow">5</div>
            <div class="item last">$6.00</div>
          </div>
      </div>
    </div>
    <div class="column">
      <div class="inner">
        <div class="row">
          <div class="item">20 sep 2018</div>
          <div class="item">$4.00</div>
        </div>
        <div class="row">
          <div class="item">
            27 sep 2018
          </div>
          <div class="item">
            $26.00
          </div>
        </div>
      </div>
    </div>
  </div>
  <div class="row row-item">
    <div class="column">
      <div class="item">
        <span>Customer 605</span>
      </div>
    </div>
    <div class="column">
        <div class="inner fixed">
          <div class="row">
            <div class="item">Item5</div>
            <div class="item narrow">50</div>
            <div class="item last">$60.00</div>
          </div>          
          <div class="row">
            <div class="item">Item6</div>
            <div class="item narrow">3</div>
            <div class="item last">$260.00</div>
          </div>
      </div>
    </div>
    <div class="column">
      <div class="inner">
        <div class="row">
          <div class="item">29 sep 2018</div>
          <div class="item">$40.00</div>
        </div>
        <div class="row">
          <div class="item">
            30 sep 2018
          </div>
          <div class="item">
            $206.00
          </div>
        </div>
      </div>
    </div>
  </div>
</div>

答案 2 :(得分:4)

此示例是一个响应式设计,仅在Flexbox中利用HTML和嵌套的CSS网格。

我可以自由地在您的方案中添加标题和分页占位符。在不影响其余布局的情况下,可以将其删除。

我创建了一个GitHub repo nested-CSS-Grid-and-Flexbox-Playground,其中包含一个Angular应用程序,该应用程序使用此布局以及动态数据以及在研究此项目时积累的参考。

HTML

<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8" />
  <title></title>
</head>
<body>
  <div class="container">
    <div class="header">
      <h1>Customers List</h1>
    </div>
    <div class="list">
      <div class="customer-column-header">Customers</div>
      <div class="invoice-column-header">Invoices</div>
      <div class="payments-column-header">Payments</div>
      <div class="customer-row">
        <div class="customer-column">
          <div>Acme Widget Manufacturing, Inc.</div>
        </div>
        <ul class="invoice-column">
          <li class="invoice-row-header">
            <div>Description</div>
            <div>Quantity</div>
            <div>Price</div>
          </li>
          <li class="invoice-row">
            <div>Item 1</div>
            <div>5</div>
            <div>$400.00</div>
          </li>
          <li class="invoice-row">
            <div>Item 2</div>
            <div>10</div>
            <div>$200.00</div>
          </li>
          <li class="invoice-row">
            <div>Item 3</div>
            <div>2</div>
            <div>$500.00</div>
          </li>
        </ul>
        <ul class="payment-column">
          <li class="payment-row-header">
            <div>Date</div>
            <div>Amount</div>
          </li>
          <li class="payment-row">
            <div>12 Sep 2018</div>
            <div>$3,000.00</div>
          </li>
          <li class="payment-row">
            <div>18 Sep 2018</div>
            <div>$2,000.00</div>
          </li>
          <li class="payment-row">
            <div>12 Sep 2018</div>
            <div>$3,000.00</div>
          </li>
          <li class="payment-row">
            <div>18 Sep 2018</div>
            <div>$2,000.00</div>
          </li>
        </ul>
      </div>
      <div class="customer-row">
        <div class="customer-column">
          <div>Beta Company</div>
        </div>
        <ul class="invoice-column">
          <li class="invoice-row-header">
            <div>Description</div>
            <div>Quantity</div>
            <div>Price</div>
          </li>
          <li class="invoice-row">
            <div>Item 1</div>
            <div>5</div>
            <div>$400.00</div>
          </li>
          <li class="invoice-row">
            <div>Item 2</div>
            <div>10</div>
            <div>$200.00</div>
          </li>
          <li class="invoice-row">
            <div>Item 3</div>
            <div>2</div>
            <div>$500.00</div>
          </li>
        </ul>
        <ul class="payment-column">
          <li class="payment-row-header">
            <div>Date</div>
            <div>Amount</div>
          </li>
          <li class="payment-row">
            <div>12 Sep 2018</div>
            <div>$3,000.00</div>
          </li>
          <li class="payment-row">
            <div>18 Sep 2018</div>
            <div>$2,000.00</div>
          </li>
        </ul>
      </div>
    </div>
    <div class="pagination">
      <p>Pagination Placeholder</p>
    </div>
  </div>
</body>
</html>

CSS

*, *::before, *::after {
  margin: 0;
  padding: 0;
  box-sizing: inherit;
}

ul {
  list-style-type: none;
}

.container {
  width: 62.5rem;
  max-width: 80rem;
  margin: 0 auto;
  background-color: lightgray;
  display: flex;
  flex-direction: column;
  justify-content: center;
}

.header {
  padding: .5rem;
  background-color: darkgrey;
  align-self: center;
}

.list {
  background-color: darkcyan;
  display: grid;
  grid-template-columns: 1fr repeat(2, minmax(min-content, 1fr));
}

.customer-column-header {
  grid-column: 1 / 2;
}

.invoice-column-header {
  grid-column: 2 / 3;
}

.payments-column-header {
  grid-column: 3 / 4;
}

.customer-column-header,
.invoice-column-header,
.payments-column-header {
  padding: .5rem;
  text-align: center;
}

.customer-row {
  border-left: 1px solid;
  border-top: 1px solid;
  background-color: orangered;
  grid-column: 1 / -1;
  display: grid;
  grid-template-columns: 1fr repeat(2, minmax(min-content, 1fr));
}

.customer-column {
  grid-column: 1 / 2;
}

.invoice-column {
  grid-column: 2 / 3;
}

.payment-column {
  grid-column: 3 / 4;
}

.customer-column {
  align-self: center;
  justify-self: right;
}

  .customer-column > div {
    padding: 1rem;
  }

.invoice-column {
  border-left: 1px solid;
}

.invoice-row-header {
  background-color: darkcyan;
  border-bottom: 1px solid;
  display: grid;
  grid-template-columns: repeat(3, minmax(6rem, 1fr));
  justify-self: stretch;
}

  .invoice-row-header > div {
    text-align: right;
    padding: .5rem;
    justify-self: stretch;
    align-self: stretch;
  }

    .invoice-row-header > div:nth-child(2) {
      border-left: 1px solid;
      border-right: 1px solid;
    }

.invoice-row {
  border-bottom: 1px solid;
  display: grid;
  grid-template-columns: repeat(3, minmax(6rem, 1fr));
  justify-items: stretch;
  align-items: stretch;
}

  .invoice-row > div {
    text-align: right;
    padding: .5rem;
    justify-self: stretch;
    align-self: stretch;
  }

  .invoice-row div:nth-child(2) {
    border-left: 1px solid;
    border-right: 1px solid;
  }

.payment-column {
  border-left: 1px solid;
}

.payment-row-header {
  background-color: darkcyan;
  border-bottom: 1px solid;
  display: grid;
  grid-template-columns: repeat(2, minmax(6rem, 1fr));
  justify-self: stretch;
}

  .payment-row-header > div {
    text-align: right;
    padding: .5rem;
    justify-self: stretch;
    align-self: stretch;
  }

    .payment-row-header > div:nth-child(1) {
      border-right: 1px solid;
    }

.payment-row {
  border-bottom: 1px solid;
  display: grid;
  grid-template-columns: repeat(2, minmax(6rem, 1fr));
  justify-items: stretch;
  align-items: stretch;
}

  .payment-row > div {
    text-align: right;
    padding: .5rem;
    justify-self: stretch;
    align-self: stretch;
  }

    .payment-row > div:nth-child(1) {
      border-right: 1px solid;
    }

.pagination {
  padding: .5rem;
  background-color: darkgrey;
  align-self: center;
}

@media only screen and (min-width: 120rem) {

  .container {
    max-width: 80rem;
    margin: 0;
  }
}

@media only screen and (max-width: 80rem) {

  .container {
    max-width: 62.5rem;
    margin: 0 auto;
  }
}

@media only screen and (max-width: 62.5rem) {

  .container {
    max-width: 45rem;
    margin: 0 auto;
  }

  .list {
    grid-template-columns: repeat(autofit, 100%);
  }

  .customer-column-header,
  .invoice-column-header,
  .payments-column-header {
    grid-column: 1 / -1;
  }

  .customer-row {
    grid-template-columns: repeat(autofit, 100%);
    justify-content: center;
  }

    .customer-row .customer-column,
    .customer-row .invoice-column,
    .customer-row .payments-column {
      grid-column: 1 / -1;
    }

  .customer-column {
    justify-self: center;
  }
}

@media only screen and (max-width: 45rem) {

  .container {
    width: 100%;
    margin: 0 auto;
  }
}
  

cref:https://codepen.io/randydaddis/pen/LqEjEg

答案 3 :(得分:3)

没有rowspancolspan s被害制作这张桌子

以下是sansthead表的图:

![enter image description here

“列” 一词的含义宽松。例如:td.items列是指全部 td.items分组。

  1. 有主表...

  2. ...,然后是每个客户行的提示。有多个组织是有效的。

  3. 下一个是tr,然后...

  4. ... td。此td是列:.customer.items.payments

  5. 在每个td中都有一个子表和一个子正文。

  6. 第一列td.customer限于一个子行,因为每个子行的内容 tbody.row只是一个  客户的名字。此列的单元格具有属性 控制tbody.row高度 (请参见演示中的评论)。

  7. 第二列td.items可以具有多个子行,演示功能从1到3 子行。
  8. 最后一列td.payments也可以具有多个子行,演示功能 每个2个子行。

演示

详细信息在演示中被评论

  • 该演示具有响应能力(对于边缘情况和移动设备可能需要MQ)。

  • 有效的HTML / CSS和语义上合理的声音。

  • 没有JavaScript / jQuery。

  • 仅使用<table><thead><tbody><tr><th><td>标签构建(甚至不包含div或span)。

* { border: 0px none transparent; padding: 0px; margin: 0px; }

/* 
|- table-layout: fixed; 
|| Gives you more control over table behavior such as setting column widths and 
|| table adhering to them.
===
|- height: 100%; width: 100%; 
|| Applied to table.main as well as the nested tables. It facilitates all of 
|| the nested tables to stretch evenly within tbody.row.
*/
table { border-collapse: collapse; border: 2px solid #000; 
table-layout: fixed; height: 100%; width: 100%; }

table table { border: 1px solid #000; }

.main { min-height: 40vh; }

th { border-bottom: 2px solid #000; outline: 1px solid #000; }

/*
|| This rule set determines content wrapping behavior within each cell.
*/
td td { border: 1px solid #000; padding: 0px 5px; word-wrap: break-word; 
word-break:break-word; overflow: hidden}

.items td:first-of-type { width: 30%; }

.items td:nth-of-type(2) { width: 25%; text-align: right; }

.items td:last-of-type { width: 45%; text-align: right; }

.payments td:last-of-type { text-align: right; }

.customer,
.items,
.payments { border: 0px none transparent; padding: 0px; }

th:first-of-type { border-left: 3px solid #000; width: 20%; }

th:nth-of-type(2) { width: 40%; }

th:last-of-type { border-right: 3px solid #000; width: 40%; }

/*
|| This allows the tr.row to always be equal in height as well as being
|| responsive. This column was the best choice as the one to stabilize height 
|| since the content probably changes the least and it has the most space to use
|| hidden spacers (see next comment). 
*/
.customer table { min-height: 20vh; } 

/*
|| This sets a &nbsp; within the cells in the first column. Although vh units
|| are very responsive, they will start collapsing if the viewport height is 
|| reduced disproportionately vs. viewport width. Thus, this pseudo-element
|| ensures a minimum height of 60px for both tr.row.
*/
.customer td::after { content: '\a0'; display: inline-block; width:0.5px; 
min-height: 60px; line-height: 60px; vertical-align: middle; }
<!DOCTYPE html>
<html>
<head>
<meta charset='utf-8'>
</head>
<body>

<table class='main'>
  <thead>
    <tr>
      <th>Customer</th><th>Items</th><th>Payments</th>
    </tr>
  </thead>
  <tbody class='row'>
   <tr>
    <td class='customer'>
      <table><tr><td>
      Customer 1
      </td></tr></table>
    </td>
    <td class='items'>
      <table>
        <tr><td>Item1</td><td>5</td><td>$400.00</td></tr>
        <tr><td>Item2</td><td>100</td><td>$20.00</td></tr>
        <tr><td>Item3</td><td>2</td><td>$500.00</td></tr>
     </table>
   </td>
   <td class='payments'>
     <table>
       <tr><td>12 Sep 2018</td><td>$3,000.00</td></tr>
       <tr><td>18 Sep 2018</td><td>$2,000.00</td></tr>
     </table>
   </td>
  </tr>
 </tbody>
 
 <tbody class='row'>
  <tr>
   <td class='customer'>
    <table><tr><td>
      Customer 304
      </td></tr></table>
   </td>
   <td class='items'>
   <table>
     <tr><td>Item4</td><td>5</td><td>$6.00</td></tr>
   </table>
  </td>
  <td class='payments'>
   <table>
     <tr><td>20 Sep 2018</td><td>$4.00</td></tr>
     <tr><td>27 Sep 2018</td><td>$26.00</td></tr>
   </table>
  </td>
 </tr>
</tbody>

 <tbody class='row'>
   <tr>
    <td class='customer'>      
     <table><tr><td>
      Customer 888
      </td></tr></table>
    </td>
    <td class='items'>
     <table>
        <tr><td>Item5</td><td>50</td><td>$100.00</td></tr>
        <tr><td>Item6</td><td>10</td><td>$500.00</td></tr>
     </table>
   </td>
   <td class='payments'>
     <table>
       <tr><td>10 Nov 2018</td><td>$3,000.00</td></tr>
       <tr><td>17 Nov 2018</td><td>$7,000.00</td></tr>
     </table>
   </td>
  </tr>
 </tbody>
</table>

</body>
</html>


参考文献

table-layout

vh and vw

word-wrap: break-word; word-break:break-word;

:first-/:nth-/:last-of-type

::before/after

答案 4 :(得分:2)

这是一个JavaScript解决方案,可以自动设置行高和列宽(不需要指定列宽),并支持调整大小。

完整的解决方案/演示在这里:http://jsfiddle.net/ez0jqc1L/

一个警告是,这要求您用<td>包装所有<div class="content"></div>单元格的内容(有关示例,请参见jsfiddle)。

首先,我们确定子表的高度:

let tbody = /* the tbody of the <table> containing subtables we are fixing */;
for(let r = 0; r < tbody.children.length; r++) {
    let row = tbody.children[r];
    let subtables = row.querySelectorAll('.subtable');
    let maxHeight = 0;
    for(let i = 0; i < subtables.length; i++) {
        maxHeight = Math.max(maxHeight, subtables[i].clientHeight);
    }
    for(let i = 0; i < subtables.length; i++) {
        subtables[i].style.height = maxHeight + 'px';
    }
}

然后,我们遍历所有子表列以计算每个垂直相邻单元格的最大宽度(我们将其存储在maxColWidths数组中,该数组的每个索引对应于垂直相邻单元格的集合) :

let forEachSubtableColumn = function(f) {
    for(let r = 0; r < tbody.children.length; r++) {
        let row = tbody.children[r];
        let subtables = row.querySelectorAll('.subtable');
        let c = 0;
        for(let i = 0; i < subtables.length; i++) {
            let subtable = subtables[i];
            if(subtable.children.length === 0 || subtable.children[0].children.length === 0) {
                continue;
            }
            let stbody = subtable.children[0];
            for(let j = 0; j < stbody.children.length; j++) {
                let srow = stbody.children[j];
                for(let k = 0; k < srow.children.length; k++) {
                    let td = srow.children[k];
                    f(c + k, td);
                }
            }
            c += stbody.children[0].children.length;
        }
    }
};
let maxColWidths = []; 
forEachSubtableColumn(function(c, td) {
    if(c >= maxColWidths.length) {
        maxColWidths.push(td.children[0].clientWidth);
    } else {
        maxColWidths[c] = Math.max(td.children[0].clientWidth, maxColWidths[c]);
    }
});

最后,我们设置列宽。这是需要<div class="content">换行的地方,因为设置<td>的宽度并不能保证浏览器将其设置为确切的宽度,但是我可以使用具有{{1} }。

display: inline-block

为调整支持大小,我们清除了所有强制的宽度和高度,以便以后可以重新计算它们:

forEachSubtableColumn(function(c, td) {
    td.children[0].style.width = maxColWidths[c] + 'px';
});

编辑:更正了onresize = function() { let tables = document.querySelectorAll('.subtable'); for(let i = 0; i < tables.length; i++) { let table = tables[i]; table.style.removeProperty('height'); } let tds = document.querySelectorAll('.subtable td'); for(let i = 0; i < tds.length; i++) { let td = tds[i]; td.children[0].style.removeProperty('width'); } updateTables(); }; 代码。

答案 5 :(得分:1)

通过嵌套CSS grid布局,实际上可以解决相当简单的问题。

(如果存在colspanrowspan,则需要使用其对应的grid-columngrid-row。)

我简化了HTML,因此可以使解决方案更清晰地理解-尽管它失去了表的语义。

如果希望保持表格标记,则中间标签(例如<tr>)的样式应为display:contents,以确保它们不会破坏布局(例如{{3} }。

/* defining the grid */
.grid{display:grid;grid-gap:0 0;}
.grid-2col{grid-template-columns:auto auto;}
.grid-3col{grid-template-columns:auto auto auto;}

/* making it look like a table. */
.th{font-weight:bold;}
.grid>*{
   border:1px solid black;
   padding:5px;}

/* avoiding double borders. */

/* no double top border - first row can be recognized by class .th */
.grid>*{border-top:none;}
.th{border-top:1px solid black;}

/* no double side border - first column can be recognized modulo number of columns of grid. */
.grid>*{border-left:none;}
.grid-2col>*:nth-child(2n+1){border-left:1px solid black;}
.grid-3col>*:nth-child(3n+1){border-left:1px solid black;}
   
/* no padding in nested tables. */
.grid>.grid{border:none;padding:0px;}
.grid>.grid>*{border-left:none;border-top:none;}
<div class="grid grid-3col">
   <span class="th">Customer</span>
   <span class="th">Items</span>
   <span class="th">Payments</span>
   <span>Customer Name</span>
   <div class="grid grid-3col">
      <span>Item1</span>
      <span>5</span>
      <span>$400.00</span>
      <span>Item2</span>
      <span>10</span>
      <span>$200.00</span>
      <span>Item3</span>
      <span>2</span>
      <span>$500.00</span>
   </div>
   <div class="grid grid-2col">
     <span>12 Sep 2018</span>
     <span>$3,000.00</span>
     <span>18 Sep 2018</span>
     <span>$2,000.00</span>
   </div>
</div>

答案 6 :(得分:0)

<table>标记的含义在当前HTML和较旧的HTML之间已更改。尽管<table>用于提供更多格式化功能,但在HTML5中,它仅应用于文字表。正如其他人提到的那样,从字面上看,您的设置实际上并不像一张桌子。因此,尽管使用一堆嵌套的<table>元素可以完成您想要的操作,但这可能不是最有效的方法。

您可以通过仅嵌套一堆<div>元素和一些基本CSS来实现此目的。这是一个示例:

<div style="width: 1000px; height: 600px; border: 1px solid #000;">
  <div style="width: 100px; height: 600px; display: inline-block; border: 1px solid #000; margin: 0; padding: 0;">X</div>
  <div style="width: 100px; height: 300px; display: inline-block; border: 1px solid #000; margin: 0; padding: 0;">Y</div>
  <div style="width: 100px; height: 300px; display: inline-block; border: 1px solid #000; position: relative; top: 300px; margin: 0; padding: 0; left: -105px;">Z</div>
</div>

这将产生您在上面描述的显示的X,Y和Z部分。可以扩展相同的技术来构建其余的显示器。

一些注意事项:

  • 此示例使用PX来确定宽度,从CSS角度来看,这是非常不好的做法。在移动设备上太大,在大型桌面上太小。但是,您可以调整此技术以使用更自适应的格式。但是,这将增加解决方案的复杂性,因此为什么我选择使用PX作为示例。
  • 此示例使用嵌入式CSS,因为这是显示解决方案的最简单方法。但是,这确实是不好的做法,请不要这样做

希望这会有所帮助。

答案 7 :(得分:0)

像Google表格这样的在线电子表格程序使它看起来非常简单,但是当我第一次涉猎时,它要复杂得多。我给每行一个特殊的属性,如row =“ r_1”,每个子行的特定属性,如row =“ r_1” subrow =“ sr_1_a”。 onkeyup事件或onload触发的数学运算使用querySelectorAll查找所有父行,然后确保其高度等于所有相加的子行高度。

答案 8 :(得分:-1)

我认为我很难实现您想要的。

原因:td嵌套在tr中,因此任何高度变化都会影响相关行的高度。

建议:您可以有五个单独的标签或div,并以内联块显示它们,然后将数据放入其中。

如果您使用此建议,请首先设置一个包裹5列的div,并将其字体大小设置为0px,然后记住将字体大小更改为对孩子有用的字体。