CSS 2.1 ::Tutorials
Tabellen-Layout mit CSS
Einführung
Seit den Zeiten der Diskussion um 'tabellenbasierte Layouts versus CSS-basierte Layouts' hat sich scheinbar in vielen Köpfen die Idee festgesetzt, dass Tabellen und CSS zwei gegensätzliche Pole des Webdesigns bilden. Das muss nicht so sein. Tatsächlich bietet CSS einige speziell auf Tabellen abgestellte Eigenschaften und ein paar interessante Möglichkeiten der Tabellenformatierung.
Dabei geht es aber nicht um Layouttabellen, sondern um Datentabellen. Dieser Artikel soll aufzeigen, wie Tabellen mit Hilfe von Stylesheets gestaltet werden können. Die theoretischen Grundlagen sind ausführlicher im Artikel Tabellenformatierung mit CSS erklärt.
Ein geeignetes Beispiel dafür ist die Auswertung der flexiblen Arbeitszeit eines Mitarbeiters. Die Rohdaten werden per Programm aus einer Datenbank ausgelesen und als HTML-Tabelle zusammengestellt. Wenn wir uns diese Tabelle so ansehen, bringt der Browser einzig die den HTML-Elementen innewohnenden semantischen Formatierungen an (mit Hilfe seines internen Stylesheets): Beispiel 00.
Das sieht noch nicht besonders ansprechend aus und gewisse stilistische Ergänzungen können nur von Vorteil sein.
Vorbereitung
Damit wir die Gestaltung unserer Tabelle flexibel und problemlos realisieren können, müssen wir den Code entsprechend vorbereiten.
Eine Tabelle besteht aus vielen gleichartigen Elementen, die nicht ohne weiteres unterscheidbar sind. So sind z. B. in vielen Tabellen alle Datenzellen durch ein simples <td>...</td>
markiert. Damit würde eine Deklaration für das Element td
auf alle Zellen der Tabelle zutreffen. Individuell werden die Zellen erst dadurch, dass wir sie durch unterschiedliche Attribute kennzeichnen. Dann können wir einzelne Zellen durch CSS-Deklarationen ansprechen. Das gilt ebenso für die einzelnen Reihen und Spalten.
Eine weitere Frage ist, wie die Tabelle zukünftig geändert werden wird. Wir wissen es nicht. Wir können aber jetzt bereits Vorbereitungen treffen, die den künftigen Wartungsaufwand deutlich verringern. Das Ziel ist hier, den Code so flexibel zu halten, dass spätere Änderungen an der Tabellengestaltung ohne Ergänzungen am Code, nur durch Änderungen des CSS, machbar sind.
Zugegeben, wenn die Inhalte einer Website aus einer Datenbank gezogen werden, würden sich die notwendigen Änderungen auf wenige Templates beschränken. Anders sieht es aber aus, wenn eine Website aus einigen hundert Seiten besteht, die manuell geändert werden müssen.
Fangen wir also oben an und notieren zunächst Spalten (col
) und Spaltengruppen (colgroup
) vor dem Kopf der Tabelle. Dabei dürfen wir nicht vergessen, dass col
und colgroup
kein Teil des Dokumentstammbaums sind und ihre CSS-Formatierung noch nicht von allen Browsern so unterstützt wird, wie wir es gern hätten. Deshalb haben wir bereits alle untereinanderliegenden Zellen jeweils mit denselben Klassen wie die Spalten versehen und sind daher nicht mehr auf die Spalten angewiesen.
Die CSS-Formatierung von Tabellenspalten wird in diesem Tutorial nur zur Demonstrationszwecken gezeigt. Es ist empfehlenswert, sich in dieser Beziehung in der Praxis nicht auf die Fähigkeiten der Browser zu verlassen.
Zusätzlich ergänzen wir noch weitere Klassenattribute im Code. Es sollten sämtliche Klassen eingefügt werden, die wir möglicherweise benötigen werden. Wir bringen diese Klassen zunächst alle nur im Quelltext an und deklarieren sie im Stylesheet später je nach Bedarf. Ob Class
-Attribute im Text stehen, die nicht im Stylesheet deklariert werden, macht keinen Unterschied.
Was fehlt uns noch? Richtig: Klassen für das erste bzw. letzte Kindelement sind gerade in Tabellen sehr hilfreich. Die erste Reihe der Tabelle oder die erste Zelle in einer Reihe könnten wir bequem mit der Pseudoklasse :first-child
ansprechen, wenn nicht IE/Win bis zur Version 6 damit Probleme hätte. Auch bietet CSS 2.1 noch keine Pseudoklasse für das letzte Kindelement. Daher definieren wir für beide Fälle eine spezielle Klasse, die wir first-child
und last-child
nennen.
Eine andere Möglichkeit wäre, auf diese beiden Klassen ganz zu verzichten und später einfach die Klassen tag
und bemkg
, ganz links und ganz rechts in der Tabelle, mit den notwendigen Deklarationen zu ergänzen. Das widerspricht aber der Forderung nach Trennung von Struktur und Inhalt, denn die Klassen tag
und bemkg
dienen der Formatierung der Spalten für Datum und Bemerkungen, nicht der Formatierung der ersten und der letzten Spalte (nach dem Zweck, nicht nach dem Ort). Entsprechende künftige Änderungen der Tabellenstruktur müssten dann auch im Stylesheet nachvollzogen werden: Beispiel 00a.
Tabellenformatierung ist umständlich und nicht einfach. Eine Tabelle, die elegant oder doch zumindest gelungen aussehen soll, erfordert eine Menge an HTML- und CSS-Input. Alle diese Ergänzungen manuell einzutragen, ist relativ aufwendig. Die meisten Tabellen mit derartig strukturierten Daten werden aber heute programmgesteuert erzeugt, deshalb zahlt es sich später aus, wenn wir anfangs einmal ein wenig mehr Zeit in den durchdachten Aufbau der Tabelle investieren.
Wir haben bereits gesehen, dass unsere Tabelle die Sektionen thead
, tfoot
und tbody
enthält. Im nächsten Codebeispiel sind diese Sektionen durch unterschiedliche Hintergrundfarben hervorgehoben. Ebenso sind die Elemente th
durch einen schwarzen Rahmen und die Elemente td
durch einen roten Rahmen gekennzeichnet. Diese Deklarationen sind temporär und dienen nur dazu, die Struktur der Tabelle noch einmal visuell zu verdeutlichen. Wir sehen aber auch, dass IE/Win bis Version 7 die Rahmen der leeren Zellen nicht darstellt, trotz der Deklaration empty-cells: show
im Stylesheet. Das liegt daran, dass der MS-Browser das CSS-Tabellenmodell noch nicht unterstützt. Um die Darstellung einheitlich zu machen, füllen wir alle leeren Zellen (vorläufig) mit einem
: Beispiel 00b.
TOP
Rahmen
Zur Darstellung unserer Beispieltabelle wählen wir das Modell der getrennten Rahmen. Das gibt uns größere Flexibilität, denn mit diesem Modell ist ebenfalls die Darstellung einfacher Rahmen zwischen den Zellen möglich. Dagegen erlaubt das Modell der zusammenfallenden Rahmen nicht die Darstellung getrennter Rahmen.
Klingt kompliziert? Gut, dann können Sie im Artikel Tabellenformatierung mit CSS nachlesen, was es mit den getrennten und zusammen fallenden Rahmen auf sich hat.
Um aus den getrennten Rahmen der Zellen einzelne Rahmen zu machen, schließen wir zunächst die Spalten zwischen den Zellen. Für IE/Win erreichen wir dies durch cellspacing="0"
im Starttag <table>
. Als nächstes entfernen wir von allen Zellen der Tabelle per CSS die Rahmen oben und links, so dass überall nur noch die Rahmen unten und rechts stehen bleiben. Da wir die einzelnen Zellen vorher schon zusammengerückt hatten, erscheint es jetzt so, dass nur noch die Rahmen ganz links außen und ganz oben an der Tabelle fehlen. Diese können wir durch unsere Klasse first-child
schnell wieder anbringen.
Siehe Beispiel 02a.
Damit arbeiten wir zwar jetzt mit dem Modell der getrennten Rahmen, haben aber praktisch das Modell der zusammenfallenden Rahmen simuliert. Der Vorteil davon ist: wir können leicht zwischen der Darstellung getrennter oder einfacher Rahmen wechseln, ohne das Tabellenmodell zu wechseln. Es ist auch möglich, unterschiedliche Rahmen für benachbarte Zellen nebeneinander oder untereinander zu zeichnen — in einer Tabelle, deren Rahmen sonst wie zusammenfallende Rahmen aussehen.
In den folgenden Beispielen werden einige Möglichkeiten aufgezeigt, die das verdeutlichen sollen. Es sind die Rahmen bestimmter Reihen und/oder Spalten markiert, nur mit Hilfe von CSS ohne Änderung des Codes.
Rahmen um eine Reihe: Beispiel 03a;
Rahmen um eine Gruppe von Reihen: Beispiel 03b;
Rahmen um eine Spalte: Beispiel 03c;
Rahmen um eine Gruppe von Spalten: Beispiel 03d;
Mehrere Rahmen um Spalten und Spaltengruppen nebeneinander: Beispiel 03e (dies ist mit dem Modell der zusammen fallenden Rahmen nicht möglich);
Mehrere Rahmen um Reihen und Spalten/Spaltengruppen nebeneinander: Beispiel 03f.
Rahmen um einen beliebigen Bereich innerhalb der Tabelle: Beispiel 03g
Wer die Beschreibung des CSS-Tabellenmodells aufmerksam gelesen hat, wird sich jetzt vielleicht fragen, warum für diese Beispiele der Aufwand mit dem Modell der getrennten Rahmen getrieben wurde. Man kann doch Rahmen an Reihen, an Spalten, Gruppen von Reihen oder Gruppen von Spalten in einer Tabelle viel einfacher im Modell der zusammenfallenden Rahmen anbringen.
Ganz so einfach ist es aber nicht. Zunächst sind die Prioritäten bei der Darstellung der Rahmen auch von den deklarierten Werten für border-style
und border-width
abhängig. Wenn in einer Tabelle schon Rahmen an den Zellen vorhanden und die genannten Werte gleich sind, haben diese höhere Priorität als Rahmen an anderen Elementen, z. B. tbody
. Das bedeutet: wo Rahmen an anderen Elementen als td
oder th
erscheinen sollen, muss man entweder diese Abhängigkeiten bei der Auswahl von Strichstärke und Muster beachten oder die Rahmen an den Zellen wegdeklarieren.
Weiter verweigert IE/Win die Darstellung des Rahmens am Element tr
ganz, an den Spalten ist die Zeichnung des Rahmens nicht browsereinheitlich. Beispiel 02b zeigt das — wer möchte, kann es sich einmal in verschiedenen Browsern ansehen. Rahmen an einzelnen Zellen bereiten dagegen keinem Browser Probleme. Deshalb bleibt uns nichts anderes übrig, als den Rahmen an den einzelnen Zellen zu deklarieren.
Letztendlich wird dieser Aufwand aber nur getrieben, um eine komfortable Zeichnung von Rahmen zu ermöglichen. Wer nur einfache Rahmen oder nur Hintergründe an seiner Tabelle anbringen möchte, kann ohne Probleme auf das Modell der zusammenfallenden Rahmen zurückgreifen.
TOP
Hintergründe
Hintergründe in Tabellen lassen sich wesentlich einfacher anbringen als Rahmen, da hier nur die Prioritäten der Elemente eine Rolle spielen. Wir brauchen uns um border-style
und border-width
nicht zu kümmern, und ob wir getrennte oder zusammenfallende oder gar keine Rahmen verwenden, ändert nichts an der Darstellung der Hintergründe. Dennoch gibt es auch hier eine Ausnahme von der Regel, auf die wir weiter unten noch kommen.
Zunächst kommen wir aber wieder zurück auf unser Beispiel der Arbeitszeitauswertung. Versuchen wir einmal, die Tabellenstruktur ohne Rahmenlinien, nur durch Hintergründe, kenntlich zu machen. Als erstes kennzeichnen wir die Reihen der Tabelle, rot für die Wochenenden, hellgrau die Wochentage (nichts aufregendes also), grün für Kopf- und Fußteil. Und so sieht es aus:
Beispiel 04a
Nun wollen wir zusätzlich einige Spalten besonders hervorheben und versehen sie mit verschiedenen Farben: z. B. gelb für die Rohdaten und blau für die Spalten mit den Ergebnissen. Im Beispiel 04b sehen wir nur, dass wir nichts sehen. Diese Spalten sind nur dort sichtbar, wo keine Hintergründe für Zellen oder Reihen vorhanden sind, d. h. in unserem Falle überhaupt nicht. Das ändert sich auch nicht durch die mit html body
künstlich gesteigerte Spezifizität. Der Grund dafür liegt hier auch wieder in den Prioritäten des CSS-Tabellenmodells. Als Abhilfe kann man die Opazität der Tabellenreihen herabsetzen, sodass die Spalteneinfärbung durchscheint. Aber das lässt sich im Moment nur mit proprietären Eigenschaften machen und ist nicht in allen Browsern darstellbar (Beispiel 04c für die Gecko-Engine).
Eine andere Möglichkeit, die Tabellenreihen halb durchsichtig zu gestalten, ist, anstelle einer Farbangabe ein halbdurchsichtiges GIF als Hintergrund zu verwenden. So ein Image, wie es rechts im Bild vergrößert gezeigt ist, besteht aus abwechselnden farbigen und transparenten Streifen, die jeweils 1 Pixel breit sind. Durch die transparenten Streifen wird die Farbe des darunterliegenden Elements sichtbar.
Theoretisch reicht es aus, so einer Grafik die Größe von 1 × 2 Pixeln zu geben. Das würde aber eine starke Belastung für die Browser beim Aufbau des Hintergrundes bedeuten. Deshalb hat die Grafik im Beispiel eine Größe von 20 × 10.
Ein kleines Problem müssen wir noch lösen: in den vorangegangenen Beispielen hatten wir den Hintergrund für die Spalten am Element colgroup
deklariert. Damit dieses Beispiel aber auch im Opera funktioniert, müssen wir hier die Hintergründe nicht an colgroup
, sondern an den Elementen col
anbringen.
Beispiel 04d
Jetzt gehen wir noch einen Schritt weiter und bringen probehalber halbdurchsichtige Grafiken als Hintergrund an den Spalten an. Das Streifenmuster ist diesmal waagerecht. Die Wirkung ist, ähnlich wie im vorangegangenen Beispiel, der Effekt einer flächenhaften Einfärbung. Tatsächlich haben wir es aber mit halbdurchsichtigen Hintergrundgrafiken zu tun. Deshalb besteht praktisch selbst in den Feldern, in denen zwei background-image
sich gegenseitig überdecken, noch eine Transparenz von 25%. Das lässt sich leicht erkennen, indem wir dem table
eine auffällige Hintergrundfarbe geben. Diese Farbe müsste dann in allen Feldern der Tabelle durchscheinen. Leider sind Mozilla, Firefox und Co. die einzigen, die dies richtig hinbekommen.
Beispiel 04e
Alternativ könnten wir die Hintergrundgrafik für die Spalten auch an den einzelnen Zellen der Tabelle anbringen, aber hier hat wiederum Opera 7 Probleme mit dem transparenten Teil. Die praktische Schlussfolgerung ist deshalb, dass für die farbige Hinterlegung von Tabellenspalten einfache Farbdeklarationen, angebracht an den Zellen, am besten sind.
TOP
Abstände
Ausgehend vom Beispiel 4c wollen wir uns nun noch kurz den Abständen innerhalb von Tabellen zuwenden. Abstände zwischen den Zellen werden automatisch gezeichnet, wenn wir das Modell der getrennten Rahmen anwenden. Diese Abstände sind immer transparent und lassen den Hintergrund des Elements table
durchscheinen. Falls außerdem Hintergründe für Reihen oder Spalten deklariert sind, werden diese nur auf die Zellen selbst angewandt. Zwischen den Zellen scheint immer der Hintergrund der Tabelle durch. Durch Kombination mit Rahmen lassen sich ebenfalls Spalten besonders hervorheben und mit fixem background-image
einige hübsche Effekte erzielen.
Beispiele: 05a, 05b, 05c.
Auch innerhalb der einzelnen Zellen lassen sich Abstände deklarieren: zwischen dem Inhalt und dem Rahmen der Zelle. Tabelleninhalte bilden in der Regel anonyme Boxen, an denen sich keine Deklarationen für Rahmen oder Abstände anbringen lassen. Früher wurden Abstände deshalb durch das Attribut cellpadding
am Element table
definiert, heute verwenden wir dafür padding
an den Elementen th
und td
. Wenn wir also vermeiden wollen, dass unsere Inhalte direkt am Rand 'kleben', dann definieren wir ein paar kleine Abstände und geben unserer Tabelle damit ein etwas gefälligeres Aussehen: Beispiel 05d.
Tabellenüberschrift und -unterschrift
Nun sieht nur noch unsere Tabellenüberschrift ein wenig mickerig aus. Bisher stand dafür immer das Element caption
ganz am Anfang der Tabelle. Bei der Formatierung dieses Elements müssen wir allerdings beachten, dass die Abstände padding
und margin
durch die führenden Browser jeweils anders dargestellt werden. Ebenso wird die Eigenschaft caption-side
bisher nur schlecht durch die Browser unterstützt. Das Verhalten der gängigen Browser ist im Grundlagenartikel Tabellenformatierung mit CSS erläutert. Aufgrund der unzureichenden Browserunterstützung und der unterschiedlichen Darstellung in den Browsern kann nur empfohlen werden, sich bei der Formatierung des Elements caption
auf die text
- und font
-Eigenschaften zu beschränken.
Wir wollen uns aber nicht derart begrenzen lassen und greifen deshalb zu einem kleinen Trick: wir verzichten ganz auf das Element caption
und ersetzen es stattdessen durch eine zusätzliche Reihe im Header oder Footer der Tabelle, die natürlich das Klassenattribut caption
erhält. Wir gehen hier sogar noch einen Schritt weiter und notieren jeweils eine Reihe im Kopfteil und im Fußteil der Tabelle. Eine der beiden deklarieren wir mit den üblichen Eigenschaften der visuellen Formatierung, die andere verstecken wir durch die Deklaration display: none;
.
Beispiel 06a
Wenn dann künftig die Tabellenbeschreibung nicht mehr oberhalb, sondern unterhalb der Tabelle stehen soll, braucht man auch hier wieder einfach nur das Stylesheet zu ändern.
Beispiel 06b
Horizontale (seitliche) Ausrichtung
Unsere Tabelle steht bereits am linken Rand der Seite, denn alle Tabellen werden automatisch am Zeilenbeginn ausgerichtet. In unserem Fall ist der Zeilenbeginn links, weil wir im Kopf unseres Webdokuments eine Zeile notiert haben, die wahrscheinlich so oder ähnlich aussieht:
Der rechts stehende, rot hervorgehobene Teil ist in diesem Falle wichtig. Er weist den Browser an, einen westlichen, lateinischen Zeichensatz mit Schreibrichtung links-nach-rechts zu verwenden. Warum das so ist? Es ist im ISO-Dokument '8859-1' so definiert. Andere Zeichensätze sind in weiteren Dokumenten der Reihe 8859 definiert. So enthält z. B. ISO-8859-8 die Zeichen der hebräischen Schrift, mit Schreibrichtung von rechts nach links. Eine vollständige Auflistung aller ISO-8859-Zeichensätze findet sich bei SelfHTML.
Wir haben mehrere Möglichkeiten, um die automatische Ausrichtung der Tabelle zu ändern: links, mittig, rechts oder über die ganze Breite der Seite. Dazu benötigen wir nur die Eigenschaften width
, margin-right
und margin-left
, die wir für das Element table
deklarieren. Die folgende Tabelle entstammt dem Grundlagenartikel über die Tabellenformatierung und fasst die möglichen Kombinationen zusammen. In den Beispielen ist gut zu erkennen, dass sich mit umgekehrter Schreibrichtung auch die Reihenfolge der Tabellenspalten und der Text in der Tabelle umkehrt. Dies lässt sich aber durch eine entsprechende Deklaration am Element table
wieder rückgängig machen.
Deklarationen | Ergebnis | ||||
---|---|---|---|---|---|
margin-left |
width |
margin-right |
Ausrichtung der Tabelle | Breite der Tabelle | Beispiel |
0 |
xx Pixel | 0 |
Zeilenanfang | xx Pixel | 07a, 07b |
0 |
xx Pixel | auto |
links | xx Pixel | 07c |
auto |
xx Pixel | 0 |
rechts | xx Pixel | 07d |
auto |
xx Pixel | auto |
mittig | xx Pixels | 07e |
auto |
auto |
auto |
mittig | Abhängig vom Inhalt | 07f |
0 |
0 |
0 |
Zeilenanfang | Abhängig vom Inhalt | 07g, 07h |
0 |
100% |
0 |
Breite entspricht der Breite des umschließenden Blocks bzw. des Bildschirms. | 07i |
Mit dem nächsten Thema kommen wir zu einem Punkt, der erst durch die Verbreitung standardstreuer Browser möglich geworden ist.
Tabellen und float
In der Vergangenheit erschien manchmal neben einer Tabelle eine freie Fläche, die so nicht immer gewollt war. Der Grund dafür war, dass Tabellen als Block- Level- Elemente im normalen Elementfluss nicht neben anderen Elementen abgebildet werden konnten. Webautoren entwickelten Tricks, um das Problem zu umgehen oder zumindest zu kaschieren, aber zu Zeiten des tabellenbasierten Layouts gab es keine Lösung, die für alle Bildschirmgrößen gleich gut war.
Heute ist so etwas nicht mehr nötig. Mit Hilfe der Eigenschaft float
lassen sich derartige Leerflächen einfach vermeiden. Float
kann direkt für das Element table
deklariert werden und wird in allen modernen Browsern korrekt dargestellt. Kleinere Tabellen lassen sich damit schnell und einfach links oder rechts ausrichten und der Fließtext läuft ungeachtet der Bildschirmbreite außen herum.
Beispiel 08a, 08b.
Nun richten wir noch die Zahlenwerte in den Zellen am rechten bzw. linken Rand aus, um die ganze Tabelle leichter lesbar zu machen: Beispiel 08c.
Dieser Artikel sollte einen Einblick in die CSS-Formatierung von Tabellen geben. Dabei ist auch hier ein Ende der Entwicklung noch nicht abzusehen. Insbesondere im Bereich der CSS-Rollovers hat die Tabelle mit ihren mehrfach verschachtelten Elementen ein großes Potential. Dieser Schritt wird wahrscheinlich stattfinden, sobald IE/Win :hover
nicht mehr nur an Ankerelementen darstellen kann.
Zum Schluss werden noch zwei Beispiele für eine relativ unkonventionelle Art der Tabellenformatierung gezeigt, wie sie mit reinem CSS und standardstreuen Browsern heute schon möglich sind. Das HTML wurde nicht geändert. Eine Tabelle muss letztlich nicht immer wie eine Tabelle aussehen, insbesondere, wenn man nur Teile der Tabelle ausgeben möchte. Dazu muss das CSS allerdings so weit ausgereizt werden, dass nur noch Gecko-basierte Browser und Opera 7.x mit Abstrichen folgen können: Beispiel 09a, 09b.
TOP