English-only | Jenom česky | Bilingual/Dvojjazyčně

CSS Technique: Striped Tables

Řešení CSS: Pruhované tabulky

Often, especially for longer tables, we'd like to use a style displaying alternate background color of even and odd rows. The most obvious way to do this is to assign a different class name to adjacent table rows and set their color in CSS. In fact, only one class is enough.

Pro tabulky, zvláště pro ty delší, je často vhodné použít styl zobrazující sudé a liché řádky střídavě jinou barvou. Nejběžnější způsob, jak toho dosáhnout, je použít pro sousední řádky tabulky různé třídy a jim pak nastavit různou barvu pozadí. Ve skutečnosti stačí dokonce použít třídu jen jednu.

td {
   background: white
   }
.even td {
   background: #f0f0ff
   }

...

<table>
   <tr>
      <td>1</td><td>Jan Kovář</td><td>Brno</td>
   </tr>
   <tr class="even">
      <td>2</td><td>John Smith</td><td>New York</td>
   </tr>
   ...
</table>
1Jan KovářBrno
2John SmithNew York
3Hans SchmiedHamburg
4Kovács JánosBudapest
5Janusz KowalskiKrakow
6Jano KováčBratislava
7Jean ForgeronLyon
8Juan HerradorValladolid

Note: Intentionally, table cells (td) background is used, instead of table rows (tr) background, because some (older) browsers don't display background of the tr element.

Anyway, what can we do if the table is already given, we are not able to change the code and add the class names to the table rows? CSS3 is ready for this, there is new pseudo-class :nth-child (see an W3C example). Unfortunately, today's browsers are not supporting it, therefore it's not a usable solution yet. After the CSS3 support is wider, we can do a style for a "striped" table very simply — i.e. this way:

Pozn.: Úmyslně je zde použito pozadí pro buňky tabulky (td) a ne pro řádky (tr), protože některé (starší) prohlížeče pozadí prvků tr nezobrazí.

Co ovšem udělat v případě, že je tabulka již vygenerovaná, nebo podobu kódu nemůžeme ovlivnit a řádkům tabulky potřebné třídy nastavit? CCS3 na to už pamatuje a pro podobné účely jsou zde nové pseudo-třídy :nth-child (viz např. ukázka na W3C). Bohužel je v této chvíli prohlížeče nepodporují, takže jako řešení je to ještě nepoužitelné. Až bude podpora CSS3 širší, styl pro takovou "pruhovanou" tabulku se udělá velmi jednoduše, například takto:

tr:nth-child(even) td { background: white }
tr:nth-child(odd)  td { background: #f0f0ff }

Staying resticted to the CSS2, we have not many tools for styling like this. As a kind of solution, we could use the + selectors, which can tell information about the local context of selected element. Though it knows only which element is preceding, the full context is not accessible. Still we can use it, at least with short tables (we must know the maximal row count). A selector tr describes (any) table row, a selector tr+tr describes "a table row preceded by a table row", which is suitable to all table rows but the first one. A selector tr+tr+tr is "a table row preceded by a table row preceded by a table row" — this means all rows from the third one, etc. The style could be defined like this:

S omezením na podporu CSS2 ale mnoho nástrojů na takovéto stylování nezbývá. Jistou obezličkou může být použití selektoru +, který dokáže vypovědět o lokálním kontextu daného prvku. Pozná ale pouze jaký prvek prvku ve stránce předchází, širší kontext dostupný není. Přesto ho můžeme aspoň u krátkých tabulek použít (musíme ovšem znát maximální počet jejích řádků). Označuje-li selektor tr (kterýkoli) řádek tabulky, selektor tr+tr je pak "řádek tabulky, kterému předchází řádek tabulky", čemuž vyhovují všechny řádky tabulky kromě prvního. Selektor tr+tr+tr je "řádek tabulky, kterému předchází řádek tabulky, kterému předchází řádek tabulky" — tj. řádky od třetího dále, atd. Styl pak může být definován takto:

tr td { background: white }
tr+tr td { background: #f0f0ff }
tr+tr+tr td { background: white }
tr+tr+tr+tr td { background: #f0f0ff }
tr+tr+tr+tr+tr td { background: white }
tr+tr+tr+tr+tr+tr td { background: #f0f0ff }

Attention, these selectors are beeing gradually tightened up, their order is important. I.e., if we group all selectors with same background color, it will stop working. This idea was sent to me by Libor Tvrdík and I thank him for it. Anyway, this is very limited solution. First, we have to know the maximum number of table rows (the example above is working till the sixth row — from seventh row, each row fits the last selector and the same color will be used).

There is moreover a problem with limited browser support. Especially IE5 and IE6 don't understand these selectors — but in Firefox, Opera, or Safari it works fine. Try the Example 1, if your browsers supports such construction.

Pozor, takto zapsané selektory se postupně zpřísňují, jejich pořadí je proto důležité. Kdybychom třeba seskupili všechny selektory se stejným pozadím k sobě, fungovat by to přestalo. Tento nápad na řešení mi poslal Libor Tvrdík a já mu za něj děkuji. Nicméně je to řešení pouze pro úzce vymezené potřeby — především musíme předem znát maximální počet řádků tabulky (výše uvedený příklad funguje do šestého řádku — počínaje sedmým už všechny vyhoví poslednímu selektoru a budou mít stejnou barvu.

Navíc je zde ještě problém s omezenou podporou tohoto selektoru v prohlížečích. Především jej neumí IE5 ani IE6, ale ve Firefoxu, Opeře či Safari to fungovat bude. Sami si můžete vyzkoušet na Příkladu 1, jestli váš prohlížeč takovouto konstrukci podporuje.

After all, Javascript seems to be the most usable solution. We can call (automatically onload, or after any action) a simple function, which adds missing class names to the table rows.

Jako nejpoužitelnější řešení se v tomto případě ukazuje Javascript. Automaticky po načtení stránky (nebo po zvolené akci) můžeme zavolat jednoduchou funkci, která chybějící třídy řádkům tabulky doplní.

function stripeTable(t) {
   var i, odd = true;
   for (i=0; i<t.rows.length; i++) {
      t.rows[i].className += odd ? ' odd' : ' even';
      odd = !odd;
      }
   }

This function, as its parameter, accepts an object representing the table to be colored. It traverses its rows and inserts to their class alternatively values odd and even, defined in CSS. Notice that the className is not overwritten, we append a space and a new class — if the row has already a class, the existing style isn't harmed. If needed, additional functions can be used, i.e. stripeAllTables(), which colors all tables within current document, or stripeTableById() coloring table by given ID. You can see it in Example 2.

This solution is fully functional and tested in IE5, IE5.5, IE6, FF, Opera and Safari.

Této funkci se jako parametr předává objekt představující tabulku, která se má obarvit. Postupně projde všechny řádky a nastaví jim do class střídavě hodnoty odd a even, které jsou použity v CSS. Všimněte si, že className nepřepisujeme, ale připojujeme za něj za mezerou další třídu — v případě, že řádky už nějakou třídu mají, tak neublížíme stávajícímu stylu. Podle potřeby můžeme přidat další funkce, např. stripeAllTables(), která obarví všechny tabulky ve stránce, nebo např. stripeTableById(), která obarví tabulku daného ID. Uvedené možnosti použití najdete v Příkladu 2.

Toto řešení je plně funkční a otestováno v IE5, IE5.5, IE6, FF, Opeře i Safari.