Selektor CSS tr:nth-child(even) oznacza dokładnie: wybierz wszystkie elementy <tr>, które są parzystymi dziećmi swojego rodzica, licząc od 1 w górę. W CSS funkcja nth-child() przyjmuje słowo kluczowe even dla elementów parzystych (2, 4, 6, …) i odd dla elementów nieparzystych (1, 3, 5, …). To jest zdefiniowane w specyfikacji CSS Selectors Level 3. W Twoim przykładzie even powoduje, że przeglądarka nadaje styl background-color: #F2F2F2; wszystkim parzystym wierszom tabeli, czyli 2., 4., 6. itd. wierszowi <tr>. Dzięki temu powstaje tzw. zebra-striping, czyli naprzemienne kolorowanie wierszy tabeli, bardzo często stosowane w interfejsach webowych, bo poprawia czytelność danych i ułatwia śledzenie wiersza wzrokiem. W praktyce używa się tego zwykle razem z drugim stylem, np. tr:nth-child(odd) { background-color: white; }, żeby wyraźnie rozróżnić wiersze. Warto też pamiętać, że nth-child() liczy wszystkie dzieci danego rodzica, a nie tylko te z określoną klasą, więc jeżeli w tabeli pojawią się np. wiersze nagłówkowe <tr> w <thead>, to selektor tr:nth-child(even) zastosowany globalnie może dać trochę inne efekty niż się spodziewasz. Dobrą praktyką jest zawężanie selektora, np. tbody tr:nth-child(even), żeby kolorowanie dotyczyło tylko części z danymi, bez nagłówków. Z mojego doświadczenia warto też używać kolorów o niewielkim kontraście, tak jak #F2F2F2, żeby nie męczyć wzroku użytkownika przy długich tabelach.
W tym zadaniu kluczowe jest zrozumienie, jak dokładnie działa funkcja nth-child() w CSS oraz co oznaczają słowa kluczowe even i odd. Wiele osób intuicyjnie myli te pojęcia i zakłada, że selektor zadziała trochę „magicznie”, np. tylko na wybrane elementy, albo że numeracja zaczyna się od zera. Tymczasem przeglądarka liczy dzieci danego elementu rodzica od 1 w górę, w kolejności ich występowania w drzewie DOM. Słowo kluczowe even oznacza wszystkie elementy o indeksach parzystych: 2, 4, 6, 8 itd. Dlatego tr:nth-child(even) nie może oznaczać wypełnienia nieparzystych wierszy tabeli – do tego służyłby selektor tr:nth-child(odd). Pomylenie even z odd to bardzo typowy błąd, zwłaszcza na początku nauki CSS, bo nazwy są krótkie i łatwo je skojarzyć odwrotnie, niż trzeba. Kolejne nieporozumienie to przekonanie, że nth-child(even) obejmuje wszystkie wiersze tabeli. Gdyby chodziło o wszystkie wiersze <tr>, wystarczyłby prosty selektor tr bez nth-child. Funkcja nth-child() zawsze wybiera tylko pewien podzbiór dzieci, zgodnie z podanym wzorem, więc mówienie, że styl z taką funkcją dotyczy wszystkich elementów, jest po prostu sprzeczne z definicją tej konstrukcji w specyfikacji CSS. Pojawia się też czasem myśl, że taka reguła ma jakiś „separujący” charakter, czyli że wstawia wizualny wiersz oddzielający nieparzyste i parzyste rekordy. CSS nie dodaje nowych elementów do DOM, on tylko styluje te, które już istnieją. tr:nth-child(even) nie tworzy żadnego dodatkowego wiersza, nie wstawia separatorów, po prostu zmienia tło wybranych istniejących wierszy, zgodnie z parzystością ich indeksu. W praktyce, jeśli chcemy mieć efekt wyraźnego rozdzielenia wierszy, używa się obramowań (border), cieni lub właśnie naprzemiennego kolorowania, ale zawsze w ramach istniejących <tr>. Dobrym nawykiem jest też pamiętanie, że nth-child() liczy wszystkie dzieci danego rodzica, więc jeśli w tabeli mamy thead, tbody i tfoot, to często stosuje się selektor tbody tr:nth-child(even), żeby uniknąć nieoczekiwanych przesunięć numeracji przez nagłówki. Zrozumienie tej zasady bardzo ułatwia późniejsze korzystanie z bardziej złożonych wzorów nth-child, jak np. 2n+1 czy 3n.