wake-up-neo.com

Übereinstimmende Tabellenhöhe für verschachtelte HTML-Tabellen

Ich versuche, Tabellen in einer Tabellenzeile zu verschachteln, während das Erscheinungsbild einer einzelnen Tabelle beibehalten wird, wie im folgenden Beispiel gezeigt (eine Tabelle mit einer einzelnen Zeile mit einem Datenwert und zwei verschachtelten Tabellen (2x2 und 3x3).

 enter image description here

Dies ist nur ein Beispiel. Die eigentliche Tabelle enthält wesentlich mehr Zeilen und Spalten. Ich möchte Tabellen verwenden, da die Spaltenbreiten und Zeilenhöhen natürlich auf die Tabellendaten passen, ohne sich um die Containergröße kümmern zu müssen (d. H. Tabellenbreite = 100%).

Das Problem, das ich habe, ist, dass die höchste Tabelle die Zeilenhöhe festlegt, aber die anderen Tabellen werden nicht erweitert, um diese Höhe auszufüllen. Daher erstrecken sich die internen Ränder nicht von oben nach unten, wie im Ergebnis dieses Ausschnitts gezeigt:

.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

Jetzt weiß ich, dass ich dieses Problem mithilfe von rowspan lösen kann (und damit löse ich derzeit das Problem). Dies erfordert jedoch im Voraus zu entscheiden, welche Zeilen aneinandergereiht werden müssen. Dies kann zu Problemen führen, die beispielsweise durch das folgende Snippet generiert werden Es wäre eindeutig besser, wenn ich rowspan="2" auf die erste Zeile (anstelle der letzten Zeile) der Tabelle mit 2 Zeilen angewendet hätte:

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

Ich würde es vorziehen, wenn die obige Tabelle so aussieht:

 enter image description here

Gibt es eine Möglichkeit, mit HTML/CSS das zu erreichen, was ich möchte? Die Tabelle enthält viele Zeilen, daher würde ich es vorziehen, wenn der Browser das vor dem Rendern aussortiert. Falls dies nicht möglich ist, bin ich offen für eine Javascript/JQuery-Lösung.

Update

Ich habe zwar zu dem Zeitpunkt eine praktikable Lösung gefunden (siehe meine Antwort). Ich habe seitdem einige Situationen erlebt, in denen das Einstellen der Spaltenbreiten (selbst in Prozent) schwierig war, da ich nicht alle möglichen Daten vorhersehen konnte angezeigt werden. Ich hoffe also, eine Antwort zu finden, die nicht darauf angewiesen ist.

Da ich es nicht so klar gemacht habe, wie ich sollte, habe ich mehrere Zeilen, in denen ich Tabellen verschachteln möchte, wobei die Höhen sowie die Spaltenbreiten übereinstimmen. Zum Beispiel möchte ich für zwei Zeilen ein Layout wie folgt erstellen:

 enter image description here

Wo mit roher Tabellen-HTML das Ergebnis so aussieht:

 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>

16
Nick

Ich würde die Verwendung von Flex vorschlagen, um Ihre Bedürfnisse zu erreichen. Flex ist für diese Art von Layout sehr leistungsfähig, da wir uns leicht vom Inhalt leiten lassen können. Bitte sehen Sie den beigefügten Ausschnitt. Es ist rein aus HTML und CSS. Keine festen Größen und kein Javascript erforderlich.

(alter Ausschnitt)

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

Update : Entsprechend Ihrem Kommentar/Ihrer Antwort geändert. Es hängt etwas von Ihrer HTML-Struktur ab. Ich musste die Überschriften zu ihrem eigenen ".row.row-item" verschieben und musste daher eine Flex-Basis setzen, um die Spalten auszurichten. Dies kann mit mehreren ".row.row-item" erweitert werden. Siehe untenstehendes Snippet.

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

10
guitarzero

Ich konnte dies schließlich lösen, indem ich eine onload-Funktion schrieb, um die maximale Höhe aller geschachtelten Tabellen in einer bestimmten Zeile zu ermitteln und dann die Höhe jeder geschachtelten Tabelle in dieser Zeile auf denselben Wert festzulegen.

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

Der einzige Nachteil dieser Lösung war, dass ich den <td>s in den verschachtelten Tabellen Breiten zuweisen musste. Da ich jedoch prozentuale Breiten verwenden konnte, war dies kein zu großes Problem für mich:

<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>

Endgültige Ausgabe:

 enter image description here

9
Nick

Bei diesem Beispiel handelt es sich um ein responsives Design, das nur HTML- und verschachtelte CSS-Grids in einer Flexbox verwendet.

Ich habe mir erlaubt, Ihrem Szenario Kopfzeilen und einen Platzierungsplatzhalter hinzuzufügen. Diese können entfernt werden, ohne den Rest des Layouts zu beeinflussen.

Ich habe ein GitHub-Repo nested-CSS-Grid-and-Flexbox-Playground erstellt, das eine Angular-Anwendung enthält, die dieses Layout mit dynamischen Daten verwendet, sowie Referenzen, die ich bei der Recherche dieses Projekts gesammelt habe.

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

4
RandyDaddis

Es wurden keine rowspans oder colspans beschädigt, wenn diese Tabelle erstellt wurde

Das Folgende ist ein Diagramm der Tabelle, auf die zugegriffen werden kann:

 ![enter image description here

Der Begriff "Spalte" wird als lose bezeichnet. Beispiel: Die Spalte td.items bezieht sich auf alle td.items als Gruppe.

  1. Es gibt den Haupttisch ...

  2. ... und dann für jede Kundenreihe ein Body. Mehrere Körper haben gilt.

  3. Als nächstes ist ein tr und dann ...

  4. ... ein td. Dieses td ist die Spalten: .customer, .items und .payments.

  5. In jedem Td gibt es eine Untertabelle und einen Unterkörper.

  6. Die erste Spalte td.customer ist auf eine Unterzeile beschränkt, da der Inhalt jeder tbody.row nur eine .__ ist. Kundenname. Die Zellen für diese Spalte haben die Eigenschaften , Die tbody.row Höhe Steuern (siehe Kommentare in der Demo).

  7. Die zweite Spalte td.items kann mehrere Unterzeilen enthalten, die Demo-Funktionen von 1 bis 3 Unterzeilen.
  8. Die letzte Spalte td.payments kann auch mehrere Unterzeilen haben, die Demofunktionen Jeweils 2 Unterzeilen.

Demo

Details sind in der Demo kommentiert

  • Die Demo ist ansprechend (möglicherweise benötigen Sie MQ für Edge-Cases und mobile Geräte).

  • Gültiges HTML/CSS und semantisch solide.

  • Kein JavaScript/jQuery.

  • Nur mit <table>-, <thead>-, <tbody>-, <tr>-, <th>- und <td>-Tags erstellt (nicht einmal ein Div oder 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>


Verweise

table-layout

vh und vw

Word-wrap: break-Word; Word-break:break-Word;

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

::before/after

3
zer00ne

Hier ist eine JavaScript-Lösung, die sowohl die Zeilenhöhe als auch die Spaltenbreite automatisch festlegt (keine Angabe der Spaltenbreite erforderlich) und die Größenänderung unterstützt.

Die vollständige Lösung/Demo ist hier: http://jsfiddle.net/ez0jqc1L/

Die einzige Einschränkung besteht darin, dass Sie den Inhalt aller <td>-Zellen mit <div class="content"></div> umschließen (ein Beispiel finden Sie im Abschnitt jsfiddle).

Zuerst legen wir die Untertischhöhen fest:

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

Dann durchlaufen wir alle Untertabellenspalten, um die maximale Breite für jeden Satz vertikal benachbarter Zellen zu berechnen (wir speichern dies im maxColWidths-Array, wobei jeder Index des Arrays dem Satz vertikal benachbarter Zellen entspricht):

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]);
    }
});

Zum Schluss legen wir die Spaltenbreiten fest. Hier ist der <div class="content">-Wrapping erforderlich, da das Festlegen der Breite eines <td> keine Garantie dafür darstellt, dass der Browser genau diese Breite macht. Ich kann diese Garantie jedoch mit einem Element mit display: inline-block erhalten.

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

Um die Größenänderung zu unterstützen, löschen wir alle erzwungenen Breiten und Höhen, um sie anschließend neu berechnen zu können:

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();
};

EDIT: Der onresize-Code wurde korrigiert.

2
sashavol

Online-Tabellenkalkulationsprogramme wie Google Sheets machen es so einfach, aber als ich zum ersten Mal hineingeschoben wurde, war es viel komplizierter. Ich gab jeder Zeile ein spezielles Attribut wie row = "r_1" und jedes unterstrangspezifische Attribut wie row = "r_1" subrow = "sr_1_a". onkeyup -Ereignisse oder ein onload-Befehl lösten die Mathematik aus, um alle übergeordneten Zeilen mithilfe von querySelectorAll zu finden, und stellten dann sicher, dass ihre Höhe allen zusammengezogenen Unterzeilen entspricht.

0
Gagich

Die Bedeutung des <table>-Tags hat sich zwischen dem aktuellen HTML-Code und dem älteren HTML-Code geändert. Während <table> verwendet wurde, um mehr Formatierungsfunktionen zu verwenden, sollte dies in HTML5 nur für eine Literal-Tabelle verwendet werden. Wie bereits erwähnt, sieht Ihr Setup im wörtlichen Sinne nicht wirklich wie eine Tabelle aus. Obwohl eine Reihe verschachtelter <table>-Elemente das erreichen kann, was Sie möchten, ist dies wahrscheinlich nicht der effektivste Weg.

Sie können dies erreichen, indem Sie einfach ein paar <div>-Elemente zusammen mit ein paar einfachen CSS-Elementen verschachteln. Hier ist ein Beispiel:

<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>

Dadurch werden die X-, Y- und Z-Teile der oben beschriebenen Anzeige erzeugt. Die gleiche Technik kann erweitert werden, um den Rest Ihrer Anzeige zu erstellen.

Ein paar Dinge zu beachten:

  • In diesem Beispiel werden PXs verwendet, um die Breite zu bestimmen, was wirklich schlechte Praxis eine CSS-Perspektive bildet. Es wäre auf dem Handy zu groß und auf dem großen Desktop zu klein. Sie können diese Technik jedoch anpassen, um ein adaptiveres Format zu verwenden. Dies macht die Lösung jedoch komplexer, weshalb ich mich für die Verwendung von PXs für das Beispiel entschieden habe.
  • In diesem Beispiel wird Inline-CSS verwendet, da dies die einfachste Möglichkeit ist, die Lösung anzuzeigen. das ist wirklich eine schlechte Praxis, TUN SIE NICHT DIESES !

Hoffe das hilft.

0
nmg49