Tabellen/Gestaltung mit CSS

Aus SELFHTML-Wiki
Wechseln zu: Navigation, Suche

Beim Layout für Tabellen steht eine Sache im Vordergrund – nicht wie gut die Tabelle aussieht, sondern wie schnell und einfach der Benutzer Daten in den richtigen Spalten und Zeilen erfassen kann.

In diesem Kapitel soll gezeigt werden, wie du Tabellen mit CSS ansprechender und zugleich besser lesbar machen kannst.

CSS-Grundeinstellungen

Rahmen und Ränder

Normalerweise empfiehlt SELFHTML, die Standardeinstellungen der Browser nur vorsichtig zu ändern. Dabei bilden Tabellen eine Ausnahme, da in der Standardansicht jede Tabellenzelle und die Tabelle selbst eine Randlinie und einen Außenrand haben, was den Tabellen einen „technischen“ Look verleiht.

border-collapse

Mit border-collapse: collapse lässt sich das ändern, sodass die Tabelle in einem „normalen“ Raster dargestellt wird.

  • border-collapse: separate; Rahmen benachbarter Tabellenelemente sind getrennt
  • border-collapse: collapse;: Rahmen fallen zusammen
Zusammenfallen der Ränder mit border-collapse ansehen …
table, th, td { border: thin solid; }
#coll { border-collapse: collapse; }
#sepa { border-collapse: separate; margin-top: 2em; }
caption { text-align: left; }

border-spacing

Die Eigenschaft border-spacing legt den Abstand der Rahmen der Tabellenelemente fest. Dies funktioniert natürlich nur, wenn für die Tabelle border-collapse: separate; festgelegt ist.


Erlaubt ist die Angabe nichtnegativer Längenmaße. Prozentangaben sind nicht erlaubt.

Wird nur ein Wert angegeben, so bezieht sich dieser sowohl auf die horizontalen als auch auf die vertikalen Abstände. Bei der Angabe von zwei Werten beschreibt der erste die (horizontalen) Abstände zwischen den Spalten, der zweite die (vertikalen) Abstände zwischen den Zeilen.

Innenabstände mit border-spacing ansehen …
table, th, td {
  border: thin solid gainsboro;
}

#bsp1 {
  border-collapse: separate;
  border-spacing: 10px;
}

#bsp2 {
  border-collapse: separate;
  border-spacing: 50px 10px;
}

Überschriften

In einer Tabelle bilden die th-Zellen die Überschriften für einzelne Spalten oder Zeilen, das Element caption stellt eine Beschriftung der Tabelle dar. Normalerweise, (d. h im Default-Stylesheet) werden die Tabellenköpfe in fetter Schrift dargestellt, die Beschriftung wird abseits der Tabelle untergebracht. Dies kann mit CSS geändert werden:


Das wikitable-Layout ansehen …
<table>
  <caption>Kostenaufstellung</caption>
  <tr>
    <th>Posten</th>
    <th>Januar</th>
    <th>Februar</th>
    <th>März</th>
  </tr>
  <tr>
    <th>Miete</th>
    <td>1.000,-</td>
    <td>1.000,-</td>
    <td>1.000,-</td>
  </tr>
</table>

Die Tabellenköpfe (th) stehen sowohl für Spaltenköpfe (oben) als auch für Zeilenköpfe (links).

Als Überschrift wird ein caption-Element verwendet.

Beispiel
table, th, td, caption {
  border: thin solid #a0a0a0;
}

table {
  border-collapse: collapse;
  border-spacing: 0;
  border-width: thin 0 0 thin;
  margin: 0 0 1em;
  table-layout: auto;
  max-width: 100%;
}
th, td {
  font-weight: normal;
  text-align: left;
}
th, caption {
  background-color: #f1f3f4;
  font-weight: 700;
}

caption-side

Die Eigenschaft caption-side legt die Position der Tabellenbeschriftung fest.

Erlaubt sind dabei folgende Werte:

  • top (Standardwert), die Beschriftung befindet sich oberhalb der Tabelle und bildet mit dieser ein gemeinsames Blockelement
  • bottom die Beschriftung befindet sich unterhalb der Tabelle und bildet mit dieser ein gemeinsames Blockelement
Beispiel ansehen …
table {
  caption-side: bottom;
}
caption {
    background-color: #fdfcf3; 
    border: thin solid #e7c157;    
	padding-top: 1em;
	margin-top: 1em;
}

Die Tabelle erhält mit caption-side eine CSS-Festlegung, dass die Tabellenunterschrift auch wirklich unterhalb der Tabelle platziert wird.

Zur besonderen Kennzeichnung wurde die caption selbst mit einem farbigen Rand und Hintergrund und ein bisschen Abstand formatiert.


Felder

Die meisten Tabellen beinhalten Zahlenreihen.

Hier ist es wichtig die Zahlen übersichtlich auszurichten und Summen entsprechend zu kennzeichnen.

Eine Kostenaufstellung ansehen …
table.finanz td { 
  text-align: right;
}

table.finanz tr.result > * {
  border-top-width: medium;
}

Hintergrund

Querschnitt durch Schichten einer Tabelle

Beim Gestalten des Hintergrunds für Tabellen ist zu beachten, dass das Tabellenlayout durch das Übereinanderlegen mehrerer Schichten entsteht.

Die Grafik illustriert den Aufbau einer Tabelle am konkreten Beispiel.

Schichtenmodell einer Tabelle ansehen …
  table, th, td  {border: thin solid black; border-spacing: 0.5em;}
  th, td         {padding: 1em;}
  #tabelle       {background-color: #8a9da8;}
  #spaltengruppe {background-color: #df6c20;}
  #spalte        {background-color: #5c82d9;}
  #zeilengruppe  {background-color: #8db243; color: #ffffff;}
  #zeile         {background-color: #e7c157;}
  #zelle         {background-color: #c32e04;}


Das Feld "Ü4" wird in grau dargestellt, weil die Hintergründe für die entsprechenden <th>, <tr>, <thead>, <col> und <colgroup> transparent sind. Es ist also der Hintergrund des table-Elements zu sehen. Wäre auch dieser transparent, so würde man den Hintergrund des unter der Tabelle liegenden Elementes (meist, wie auch in diesem Beispiel <body>) sehen. Aus ähnlichen Gründen ist "Zelle 5" grün.

Beispiel Browser-Support

Für unser Beispiel verwenden wir eine Tabelle, in der die Marktanteile der einzelnen Browser in Deutschland dargestellt sind.

In die Tabelle wurde ein tbody-, thead und tfoot-Element eingefügt (ein tbody-Element erzeugen die Browser ggf. selbst). Zeilen werden mit tr eingeleitet.

Der Tabellenkopf besteht aus th-, die einzelnen Zellen mit td-Elementen.

Da der Internet Explorer im Unterschied zu den anderen Browsern keine automatischen Updates erhält, ist es interessant zu wissen, auf welche Versionen sich der Marktanteil verteilt:

Beispiel ansehen …
<thead>
  <tr>
    <td rowspan="2"></td>
    <th scope="col" rowspan="2">Chrome</th>
    <th scope="col" rowspan="2">Firefox</th>
    <th scope="colgroup" colspan="3">Internet Explorer</th>
    <th scope="col" rowspan="2">Edge</th>
    <th scope="col" rowspan="2">Opera</th>
    <th scope="col" rowspan="2">Safari</th>
  </tr>
  <tr>
    <th scope="col">IE 8</th>
    <th scope="col">IE 9</th>            
    <th scope="col">IE 10-11</th>
  </tr>
</thead>

In der oberen Reihe erhalten alle Tabellenzellen mit rowspan="2" die doppelte Höhe. Die Zelle mit dem Inhalt Internet Explorer erstreckt sich mit colspan="3" über drei Zellen.

In der zweiten Reihe gibt es nur drei Zellen, die den Raum unter der dreifach breiten, aber nur einfach hohen Zelle einnehmen.

Tabellenüberschrift

Sie können einer Tabelle mit dem caption-Element eine kurze Erklärung oder Überschrift zuordnen. Die Deklaration muss unmittelbar nach dem einleitenden table-Tag erfolgen, kann durch CSS aber auch unterhalb der Tabelle positioniert werden.

Positionierung einer Tabellen-Unterschrift ansehen …
table {
  caption-side: bottom;
}
<table>
  <caption>Verzeichnis der Teilnehmer</caption>
  <thead>
    <tr>
  ...

In diesem Beispiel erhält die Tabelle eine caption, diese wird mit caption-side an den unteren Rand positioniert.

Jede Spalte hat eine Kopfzelle (th) im Tabellenkopf (thead), die mit scope="col" der Spalte zugeordnet wird.

Analog dazu dient die linke Spalte mit scope="row" als Tabellenkopf für die einzelnen Reihen.

Grundlegende CSS-Angaben

Beispiel ansehen …
table, th, td {
  border: thin solid black;
  border-collapse: separate;
}

Die browsereigenen Einstellungen stellen Tabellen ohne Linien dar. Hier wurde nur zur Deutlichmachung ein dünner Rahmen festgelegt.

Mit der Eigenschaft border-collapse können Sie festlegen, ob Rahmen benachbarter Tabellenelemente getrennt (border-collapse: separate;) oder zusammenfallend (border-collapse: collapse;) dargestellt werden.

Schrift in Kopf- und Datenzellen wird in der Standardschriftgröße, Schrift in Kopfzellen wird fett dargestellt.

Empfehlung:
  • Verwenden Sie Linien in Tabellen nur sparsam.
    Verwenden Sie entweder horizontale oder vertikale Linien.
  • Gliedern Sie evtl. durch die Verwendung von Hintergrundfarben.
  • Verkleinern Sie die Schriftgröße, bzw. erhöhen Sie die Werte für Abstände und Ränder.

Gestaltung von Kopf und Datenzellen

In den browsereigenen Standardeinstellungen sieht man nur einen gleichförmigen Zahlensalat. Mit CSS können Sie Kopf- und Datenzellen so gestalten, dass die Zahlen besser lesbar sind.


Beispiel ansehen …
table {
  border-collapse: separate;
  border-spacing: 0.2em;
}
  
th, td {
  padding: .2em .5em;
  border-radius: .1em;  
}  

thead th {
  background-color: #ffebe6;
  color: #c32e04;
}

td {
  font-style: italic;
  text-align: right;
  box-shadow: inset 1px 3px 5px -3px rgb(0 0 0 / .5);
}   

td:empty{
  box-shadow: none;
}

Mit border-spacing wird der Abstand der Rahmen der Tabellenelemente vergrößert. Dies funktioniert natürlich nur, wenn für die Tabelle border-collapse: separate; festgelegt ist.

Die Tabellenköpfe erhalten eine Hintergrund- und Textfarbe.

Die Schrift in den Datenzellen soll kursiv und rechtsbündig sein, damit große Werte gleich herausstechen.

Damit die leere Datenzelle oben links keinen Schatten erhält, werden leere Zellen mit der Pseudoklasse empty angesprochen und der Schatten wieder entfernt.


Empfehlung: Wählen Sie Farben und Kontraste so, dass der Text sehr gut lesbar ist.
Farbe/Farben und Kontraste

Zebrastreifen

Gerade bei größeren Tabellen ist es übersichtlicher jede zweite Zeile einzufärben.

Beispiel ansehen …
tbody tr:nth-child(even) { 
  background-color: #e4ebf2; 
  color: #000; 
}

Mit der strukturellen Pseudoklasse nth-child erhält jede zweite, hier jede gerade (even = gerade) Zeile eine andere Hintergrundfarbe.


Zeilenüberschriften

Erinnern Sie sich noch an die Kopfzellen in jeder Zeile?

Beispiel ansehen …
tbody tr:nth-child(even) td { 
  background-color: #e4ebf2; 
  color: #000; 
}

th[scope=row] { 
  color: #c32e04;
  text-align: right; 
}

Mit th[scope=row] werden alle th-Elemente angesprochen, deren Attributwert für das scope-Attribut row beträgt.

Um weitere Festlegungen für den Hintergrundfarbe zu vermeiden, wird der Zebralook gegenüber dem obigen Beispiel für die Datenzellen der geraden Zeilen festgelegt.


Überschrift gestalten

Die im caption-Element enthaltene Überschrift wird nun mit einem ribbon gestaltet:


Beispiel ansehen …
table {
  border-collapse: separate;
  border-spacing: .2em;
  margin-left: 2em;
  box-shadow: 0 0 .1em #666;
  position: relative;
  z-index: 1;
}
  
caption {
  color: white;
  background: hsl(13 96% 39%);
  font-size: 1.5em;
  box-shadow: .1em .1em .1em 0 hsl(0 0 50%);
  padding: .2em .2em .2em 2em;
  width: 10em;
  margin-left: -.6em;
  position: relative;
}

caption::before {
  content: "";
  position: absolute;
  display: block;
  height: 0;
  width: 0;
  top: 1em;
  left: -.6em;
  border-style: solid;
  border-width: .6em;
  border-color: transparent hsl(13 96% 35%) transparent transparent;
  z-index: -1;
}

Die caption erhält eine andere Hintergrund- und Textfarbe. Gegenüber der für eine Unterschrift passenden Normalschriftgröße wird hier eine anderthalbfache Schriftgröße gewählt.
Das Band erhält durch ein links vorgelagertes Pseudoelement ein räumliches Aussehen.
Auch die Tabelle erhält nun einen Schatten.


Beachten Sie: Um das Pseudoelement mit z-index: -1; hinter das Band ordnen zu können, müssen Sie der Tabelle ebenfalls einen Wert für position und z-index zuordnen.

Markierung von Zeilen bei :hover

Wenn Benutzer mit der Maus über die Tabelle fahren, wird die jeweilige Datenzelle und dazugehörende Tabellenzeile farbig markiert:

Beispiel ansehen …
tbody tr:hover, tfoot tr:hover { 
  background-color:#fffbf0;
}

tbody td:hover, tfoot td:hover { 
  background-color: #fce4a2; 
}

Es werden alle Datenzellen im Tabellenkörper und Tabellenfuß bei :hover mit einer anderen Hintergrundfarbe versehen.


Markierung von Spalten bei :hover

Im Gegensatz zur Zeilenmarkierung ist eine Markierung von Tabellenspalten nicht so einfach. Das liegt daran, dass es zwischen Zellen und Spalten im DOM keine Eltern-Kind Beziehung gibt. Chris Coyier veröffentlichte auf CSS-Tricks eine Lösung[1], die mit absolut positionierten Pseudoelementen von 10000px Höhe arbeitet, die durch ein overflow:hidden auf dem <table>-Element visuell begrenzt werden. Das funktioniert, insbesondere auch bei Verwendung von verbundenen Zellen, kann aber nur als Umgehungslösung bezeichnet werden.

Mit der Verfügbarkeit der :has()-Pseudoklasse lassen sich CSS Selektoren konstruieren, die auf Pseudoelemente und JavaScript-Unterstützung verzichten können[2]. Dafür müssen zwei Voraussetzungen erfüllt sein:

  • Im HTML muss es genau ein <col>-Element für jede Spalte geben. Es ist möglich, diese auf mehrere <colgroup>-Elemente zu verteilen, das CSS wird dann aber umständlicher.
  • Die Tabelle verwendet keine über Spalten hinweg verbundenen Zellen

Mit :has() kann man einen CSS Selektor formulieren, der für das <table>-Element zutrifft, wenn sich die Maus über einer der Tabellenzellen befindet. Für ein td-Element in der vierten Spalte sähe das beispielsweise so aus:

 table:has(td:nth-child(4):hover)

Diesen Selektor muss nun mit einem Selektor für das <col>-Element zur Spalte als Nachfahre kombiniert werden, und das Ganze muss für jede Spalte der Tabelle wiederholt werden. Für einen Wochenkalender mit sieben Spalten sähe das so aus:

Spalten-Hover mit CSS ansehen …
table:has(td:nth-child(1):hover) col:nth-child(1),
table:has(td:nth-child(2):hover) col:nth-child(2),
table:has(td:nth-child(3):hover) col:nth-child(3),
table:has(td:nth-child(4):hover) col:nth-child(4),
table:has(td:nth-child(5):hover) col:nth-child(5),
table:has(td:nth-child(6):hover) col:nth-child(6),
table:has(td:nth-child(7):hover) col:nth-child(7) {
	background: hsl(20deg 100% 80% / 0.5);
}

Mögliche Anpassungen:

  • Um auch einen Hover auf Tabellenüberschriften zu berücksichtigen, kann man td durch :is(th,td) ersetzen.
  • Wird mehr als eine colgroup verwendet, müssen die Selektoren so erweitert werden, dass sie auch die richtige colgroup ansprechen, zum Beispiel so:
    Beispiel
      table:has(td:nth-child(5):hover) colgroup:nth-child(1) col:nth-child(5),
      table:has(td:nth-child(6):hover) colgroup:nth-child(2) col:nth-child(1),
    

Alternative mit JavaScript

Früher war es mit CSS nicht möglich, eine Tabellenspalte bei :hover markieren.[3].

Eine Alternative besteht in der Verwendung von JavaScript. Voraussetzung ist hier, dass im Markup der Tabelle ein col-Element für jede Tabellenspalte vorgesehen wird.


Tabellenspalte bei :hover markieren ansehen …
  const tableElement = document.querySelector('table');
  const colElements = tableElement.querySelectorAll('col');

  function findColumnFor(element) {
    const cell = event.target.closest('td,th');
    return cell ? colElements[cell.cellIndex] : null;
  }

  tableElement.addEventListener('mouseover', event => {
    const col = findColumnFor(event.target);
    if (col)
      col.classList.add('hover');
  });
  tableElement.addEventListener('mouseout', (event) => {
    const col = findColumnFor(event.target);
    if (col)
      col.classList.remove('hover');
  });

Mit Einsatz des Optional Chaining Operators ?. kann man die Eventhandler noch kompakter formulieren, aber diese Syntax wird von SelfHTML Frickl nicht unterstützt.

Beispiel
  // Optional Chaining statt Temp-Variable und if
  tableElement.addEventListener('mouseover', event => {
    findColumnFor(event.target)?.classList.add('hover');
  });

Beispiel Bundesländer grau in grau

Im Folgenden sollen nun in einem zweiten Beispiel die Bundesländer der Bundesrepublik vorgestellt werden.

Beispiel ansehen …
table, th, td { 
  border-collapse: collapse;
  padding: .3em .5em; 
}

table {
 margin-left: 1em;}

th, caption { 
  background-color: #666; 
  color: #fff; 
  border: thin solid #666;
}

td {
 background-image: linear-gradient(#f9f9f9, #e3e3e3);
 border-left: thin solid #666;
 border-right: thin solid #666;
}

tfoot {
  border-bottom: thin solid #666;
}

caption {
  font-size: 1.5em;
  border-radius: .5em .5em 0 0;
  padding: .5em 0 0 0
}

/* 3. und 4. Spalte rechtsbündig */
td:nth-of-type(3), td:nth-of-type(4) {
  text-align: right;
}

Diese Tabelle verzichtet auf viele Farben. Überschrift und Tabellenkopf werden hell auf dunkel dargestellt.

Die Tabelle erhält nur vertikale Linien; der Datenzellen-Hintergrund wird als Verlauf ausgeführt und sorgt für eine horizontale Gliederung.

Fester Tabellenkopf mit position:sticky

In längeren Tabellen soll der Tabellenkopf beim Scrollen stets sichtbar bleiben. Dies können Sie einfach und ohne JavaScript mit position: sticky erreichen:

Elemente mit der Eigenschaft position: sticky behalten ihre Position im Elementfluss, bis sie das obere oder untere Seitenende erreichen und dort „kleben“ bleiben. Erforderlich ist dafür auch die Angabe von top oder bottom – der zugewiesene Wert ist der Abstand vom Seitenende, bei dem das Element „kleben“ bleiben soll.


Tabelle mit festem Kopf ansehen …
thead {
	position: sticky;
	top: 0;
	color: black;
	background: white;
}

Mit diesem CSS wird dafür gesorgt, dass die Tabelle beim Scrollen ihren Tabellenkopf stets sichtbar anzeigt. Wenn zum weiter unterliegenden Absatz weitergescrollt wird, verschwindet der Tabellenkopf aber wieder.


Weblinks

  1. css-tricks: Simple CSS-Only Row and Column Highlighting von Chris Coyier, 13.04.2015
  2. Selfhtml Forum: CSS Lösung von Gunnar Bittersmann
  3. SELF-Forum: Tabellenspalte bei :hover markieren von Matthias Apsel vom 03.11.2019