CSSで、表を1行おきに色分けする方法
表を1行おきに色分けするには、tbody tr:nth-child(even) に background-color を付けます。これで、本体の行のうち2行目、4行目、6行目…に色が付きます。絞り込みなどで行を隠すと縞がずれますが、:nth-child(even of :not([hidden])) と書くと、見えている行だけで数え直せます。
検証環境は Ubuntu 24.04、Node.js 22.23.4、Playwright 1.63.0、Chromium 153 です。検証用のページを Playwright で開き、行ごとの getComputedStyle() の背景色と、スクリーンショットの画素の色を読みました。Firefox と Safari、スマートフォンの実機は試していません。

偶数番目の行に背景色を付ける
HTML は、見出しの行を <thead> に、本体の行を <tbody> に入れた、ふつうの表です。
<table>
<thead>
<tr><th scope="col">商品</th><th scope="col">在庫</th><th scope="col">値段</th></tr>
</thead>
<tbody>
<tr><td>りんご</td><td>12</td><td>150円</td></tr>
<tr><td>みかん</td><td>0</td><td>80円</td></tr>
<tr><td>ぶどう</td><td>5</td><td>480円</td></tr>
<tr><td>もも</td><td>8</td><td>300円</td></tr>
<tr><td>なし</td><td>0</td><td>200円</td></tr>
<tr><td>かき</td><td>20</td><td>120円</td></tr>
</tbody>
</table>
CSS は次のとおりです。
table {
border-collapse: collapse;
}
th,
td {
padding: 8px 12px;
border-bottom: 1px solid #c8d3d8;
text-align: left;
}
thead th {
background-color: #067a98;
color: #fff;
}
/* 偶数番目の行に色を付ける */
tbody tr:nth-child(even) {
background-color: #e0f6fb;
}
/* マウスを乗せた行 */
tbody tr:hover {
background-color: #ffe3ea;
}
:nth-child() は、同じ親を持つ兄弟要素の中で、何番目にあるかで要素を選ぶ擬似クラスです。even は偶数番目、odd は奇数番目を表します。MDN の説明にあるとおり、tr:nth-child(even) は tr:nth-child(2n) と、tr:nth-child(odd) は tr:nth-child(2n+1) と同じ行を選びます。1行目から色を付けたいときは、even を odd にします。
この CSS で表を表示すると、本体の2行目(みかん)、4行目(もも)、6行目(かき)の背景が #e0f6fb になり、1・3・5行目は白のままでした。数えるのは <tbody> の中の <tr> だけなので、<thead> の見出しの行は数に入りません。
マウスを乗せた行の色は、縞のルールより後に書く
マウスを乗せた行に色を付ける tbody tr:hover は、縞のルールの後に書きます。上の CSS で2行目(みかん)にマウスを乗せると、その行は #ffe3ea のピンクになりました。
順番を入れかえて、tbody tr:hover を tbody tr:nth-child(even) より前に書くと、マウスを乗せた2行目は水色のままでした。奇数番目の3行目(ぶどう)に乗せたときは、ピンクになりました。
どちらのセレクターも、擬似クラスが1つと要素の名前が2つで、詳細度が同じです。詳細度が同じときは、後に書いたルールが使われます。偶数番目の行には両方のルールが当てはまるので、前に書いたホバーの色が、後の縞の色に負けます。
thead を書かないと、見出しの行も数に入る
<thead> と <tbody> を書かずに、見出しの行も本体の行も <table> の中にそのまま並べた表で、tr:nth-child(even) を試しました。見出しの行が1行目と数えられ、本体の1行目(りんご)、3行目(ぶどう)、5行目(なし)に色が付きました。縞が1行ずれます。
このとき、ページの中の <table> の子要素を調べると、<tbody> が1つありました。<tbody> の説明にあるとおり、<tr> が <table> の直接の子として書かれていると、ブラウザーが <tbody> で囲みます。見出しの行も同じ <tbody> に入るので、tbody tr:nth-child(even) と書いても、同じくりんご・ぶどう・なしに色が付きました。table > tr:nth-child(even) と書くと、どの行にも色が付きませんでした。
見出しの行は <thead> に入れておくと、縞を数える対象から外れます。thead th に付けた見出しの色も、<thead> がない表では付きませんでした。
行を隠すと縞がずれるときは、of 構文で数え直す
在庫が0の行を隠すような絞り込みをすると、:nth-child(even) の縞がずれます。hidden 属性で、2行目(みかん)と5行目(なし)を隠して試しました。
tbody tr:nth-child(even) では、画面に見えている4行のうち、1行目(りんご)と2行目(ぶどう)が続けて白になり、3行目(もも)と4行目(かき)が続けて水色になりました。隠した行も、兄弟要素として数に入っているためです。
:nth-child() には、数える対象をセレクターで絞る of 構文があります。
tbody tr:nth-child(even of :not([hidden])) {
background-color: #e0f6fb;
}
:not([hidden]) は、hidden 属性がない行です。この CSS では、見えている4行が白・水色・白・水色と交互になりました。MDN の :nth-child() の説明にある、of 構文で表の縞模様を直す例も、同じ書き方です。
![「在庫0の行を隠す」ボタンにマウスポインターを動かしてクリックする。押した瞬間に右の「クリック 1回目/2回」と、下の「表示している行」の「4行」がピンクの地になる。上の「tr:nth-child(even)」の表では、みかんとなしの行が消え、りんごとぶどうが続けて白、ももとかきが続けて水色になる。下の「tr:nth-child(even of :not([hidden]))」の表では、残った4行が白・水色・白・水色と交互になる。2回目のクリックで「在庫0の行も出す」に戻り、どちらの表も6行の縞に戻る](https://neko-note.org/wp-content/uploads/2026/11/css-striped-table-striped-filter.gif)
of のあとのセレクターは、行をどう隠しているかに合わせます。style 属性の display: none で隠した行には hidden 属性がないので、:not([hidden]) では数から外れません。style="display: none" で同じ2行を隠すと、of :not([hidden]) を付けていても、:nth-child(even) だけのときと同じように縞がずれました。
隠すための class を決めているなら、その class で数え直します。.is-hidden { display: none; } で隠し、tbody tr:nth-child(even of :not(.is-hidden)) と書くと、見えている4行が交互の色になりました。
MDN の互換性データ(@mdn/browser-compat-data 8.1.8)では、of 構文は Chrome 111、Edge 111、Firefox 113、Safari 9 から使えます。
of 構文にすると、偶数番目の行にホバーの色が付かなくなる
of 構文の縞のルールの後に tbody tr:hover を書き、偶数番目の2行目(みかん)にマウスを乗せました。後に書いたのに、その行は水色のままでした。奇数番目の3行目(ぶどう)に乗せたときは、ピンクになりました。
Selectors Level 4 の詳細度の決め方では、:nth-child() の詳細度は、擬似クラス1つ分に、of のあとのセレクターの詳細度を足したものです。:not() の詳細度は、かっこの中のセレクターの詳細度と同じなので、[hidden] の分だけ縞のルールのほうが詳細度が高くなります。縞が付く偶数番目の行では、順番に関係なく縞の色が勝ちます。
縞のルールを :where() で包むと、詳細度が上がらなくなります。:where() の詳細度は、中に何を書いても0です。
tbody tr:where(:nth-child(even of :not([hidden]))) {
background-color: #e0f6fb;
}
tbody tr:hover {
background-color: #ffe3ea;
}
この CSS では、2行目(みかん)に乗せても3行目(ぶどう)に乗せても、その行がピンクになりました。在庫0の2行を hidden 属性で隠したときも、見えている4行は交互の色のままでした。互換性データでは、:where() は Chrome 88、Edge 88、Firefox 78、Safari 14 から使えます。
セルに背景色があると、行の色が隠れる
縞の色は <tr> に付けています。ほかの CSS で、セル(<td>)にも td { background-color: #fff; } のように背景色が付いていると、縞は見えなくなります。
この CSS を足して試すと、偶数番目の行の <tr> の背景色は #e0f6fb のままでしたが、画面に塗られた色はすべての行で白でした。縞の色をセルに付けると、また見えるようになりました。
tbody tr:nth-child(even) td {
background-color: #e0f6fb;
}
tbody を分けると、数え方は tbody ごとに始まる
:nth-child() が数えるのは、同じ親の中での順番です。6行の本体を、3行ずつ2つの <tbody> に分けて tbody tr:nth-child(even) を試すと、色が付いたのは、それぞれの <tbody> の2行目でした。画面の上から数えると2行目と5行目で、3行目と4行目が続けて白になりました。
<tbody> で行をまとまりに分けているときは、まとまりごとに縞が1行目から始まります。表全体で交互にしたいときは、本体の行を1つの <tbody> にまとめます。





