Tabellen/Gestaltung mit CSS
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.
Inhaltsverzeichnis
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
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.
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:
<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.
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;
}
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
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.
table.finanz td {
text-align: right;
}
table.finanz tr.result > * {
border-top-width: medium;
}
Hintergrund
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.
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:
<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.
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
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.
- 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.
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.
→ Farbe/Farben und Kontraste
Zebrastreifen
Gerade bei größeren Tabellen ist es übersichtlicher jede zweite Zeile einzufärben.
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?
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:
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.
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:
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:
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.
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.
// 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.
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.
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
- ↑ css-tricks: Simple CSS-Only Row and Column Highlighting von Chris Coyier, 13.04.2015
- ↑ Selfhtml Forum: CSS Lösung von Gunnar Bittersmann
- ↑ SELF-Forum: Tabellenspalte bei :hover markieren von Matthias Apsel vom 03.11.2019
- tympanus.net: Pimp your tables with css3
- read-team-designers: css3-tables-with-rounded-corners