jQuery / Selector / :even - 偶数インデックスの要素を選択するセレクター

jQueryの:evenは選択結果のインデックス0・2・4、つまり1番目・3番目・5番目を選びます。jQuery 3.4から非推奨なので、新しいコードでは同じ選択を行う.even()が適しています。CSSの:nth-child(even)とは数える範囲と開始番号が違います。

:evenと.even()のバージョンと基準

:evenの仕様は0始まりの偶数インデックスと3.4での非推奨化を説明しています。代替の.even()メソッドはjQuery 3.5で追加されました。古い1.xファイルを読み込んだまま構文だけ変えても利用できないため、実際の読み込みバージョンを確認します。

この記事の例はWindowsのブラウザーでjQuery 3.7.1と4.0.0を使って実行しました。:evenは確認した両バージョンで動作しました。非推奨と削除済みを区別し、今後の作成・更新では推奨される方法へ移します。

偶数インデックスと偶数番目の子は別

式 数える範囲と開始 選択位置
:evenまたは.even() 現在の選択結果、0から 0・2・4:1番目・3番目・5番目
:nth-child(even) 親ごとの兄弟要素、1から 2番目・4番目・6番目
:nth-child(odd) 親ごとの兄弟要素、1から 1番目・3番目・5番目

liだけが並ぶ1つのリストなら.even()と:nth-child(odd)の結果が一致する場合があります。しかし複数リストのliを一括選択すると、.even()は結合された選択結果で数えます。:nth-child()は親ごとに数え直し、指定タグだけでなくすべての兄弟要素の位置を使います。

2つのリストを比較する完全な例

コード全体をUTF-8のeven-demo.htmlに保存してブラウザーで開きます。公式jQuery配布ファイルを読むためネット接続が必要です。4.0.0に固定しており、パッケージのインストールは不要です。AとBにはそれぞれliが3個あります。

<!doctype html>
<html lang="en">
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <title>Even indexes and sibling positions</title>
  <style>
    body { font: 16px/1.6 sans-serif; margin: 24px; }
    .items { padding: 0; list-style: none; }
    .items li { padding: 8px 14px; border: 1px solid #ddd; }
    .marked { background: #fff0b3; }
    button { margin: 4px; padding: 8px; }
  </style>
  <script src="https://code.jquery.com/jquery-4.0.0.min.js"></script>
</head>
<body>
  <h1>Even indexes and sibling positions</h1>
  <div id="groups">
    <ul class="items"><li id="a1">A1</li><li id="a2" class="keep">A2</li><li id="a3" class="keep">A3</li></ul>
    <ul class="items"><li id="b1" class="keep">B1</li><li id="b2">B2</li><li id="b3" class="keep">B3</li></ul>
  </div>
  <button type="button" id="combined">Combined .even()</button>
  <button type="button" id="per-parent">Each list .even()</button>
  <button type="button" id="css-even">CSS :nth-child(even)</button>
  <button type="button" id="reset">Reset</button>
  <p id="result" aria-live="polite"></p>
  <script>
    $(function () {
      function show($chosen) {
        $("#groups li").removeClass("marked");
        $chosen.addClass("marked");
        const ids = $chosen.map((_, item) => item.id).get().join(", ");
        $("#result").text(`${ids || "none"} | ${$chosen.length}`);
      }
      $("#combined").on("click", () => show($("#groups li").even()));
      $("#per-parent").on("click", function () {
        let $chosen = $();
        $(".items").each(function () {
          $chosen = $chosen.add($(this).children("li").even());
        });
        show($chosen);
      });
      $("#css-even").on("click", () => show($("#groups li:nth-child(even)")));
      $("#reset").on("click", () => show($()));
      show($("#groups li").even());
    });
  </script>
</body>
</html>

初期状態では全6要素のインデックス0・2・4に当たるA1・A3・B2が強調され、結果は次のとおりです。

a1, a3, b2 | 3

ボタン別の結果と初期化

  1. Combined .even()は2リストを一括して数え、a1, a3, b2 | 3になります。
  2. Each list .even()は各リストのliを別々に選択します。親ごとに開始するためa1, a3, b1, b3 | 4です。
  3. CSS :nth-child(even)は各リストの2番目の子を選び、a2, b2 | 2になります。
  4. Resetは強調を外しnone | 0を表示します。項目自体は削除しません。Combinedで最初の結果に戻せます。

showは古い強調クラスを全体から外して新しい結果にだけ付けます。リスト別の処理はaddで結果を合成します。全体を数えるか親ごとかを、コードと表示の両方で確認してください。

既存の:evenを.even()へ置き換える

セレクターから:evenを外し、残ったセレクターのjQueryオブジェクトに.even()を呼びます。例を開いた直後かCombined後に開発者ツールのConsoleで次を実行します。最初の2結果は一致し、3番目は兄弟の偶数番目になります。

const ids = $set => $set.map((_, item) => item.id).get().join(", ");
console.log(ids($("#groups li:even")));
console.log(ids($("#groups li").even()));
console.log(ids($("#groups li:nth-child(even)")));
a1, a3, b2
a1, a3, b2
a2, b2

.even()を:nth-child(even)に置き換えると、構文だけでなく選択の意味が変わります。縞模様を親ごとに始めるのか、検索・絞り込み結果全体で交互にするのかを先に決めます。:evenはjQuery拡張であり、そのままCSSスタイルシートへ書くセレクターではありません。

絞り込みの順番と文書変更

keepクラスはA2・A3・B1・B3にあります。$("#groups li.keep").even()は先に範囲を絞るのでA2・B1を選びます。逆に$("#groups li").even().filter(".keep")は全体の偶数インデックスからkeepを残し、A3だけになります。処理順で数える対象が変わります。

選択結果は自動更新されません。項目の追加・削除や条件変更後に現在の順で強調するには、選択と.even()を再実行します。反応しない場合はNetworkの読み込み、Consoleのエラー、jQuery.fn.jqueryの値を確認します。複数バージョンを重複して読んでいないかも調べます。