リストの特定アイテムだけスキップして残りを操作する、テーブルのヘッダー行を除いてデータ行だけ処理する、タブの選択中パネル以外を非表示にするなど、n 番目以外の子要素を取得する操作は DOM 操作でよく使います。この記事では JavaScript と CSS セレクタの両方のアプローチを解説します。
この記事でわかること
・Array.from + filter でインデックスを除外する方法
・CSS の
・children プロパティと for ループによる方法
・複数のインデックスをまとめて除外する方法
・先頭・末尾・特定クラス以外の要素を取得する方法
・nth-child と nth-of-type の違い
・テーブル行フィルタリング・タブ切り替えの実務パターン
・Array.from + filter でインデックスを除外する方法
・CSS の
:not(:nth-child(n)) で除外する方法・children プロパティと for ループによる方法
・複数のインデックスをまとめて除外する方法
・先頭・末尾・特定クラス以外の要素を取得する方法
・nth-child と nth-of-type の違い
・テーブル行フィルタリング・タブ切り替えの実務パターン
方法の比較
| 方法 | 特徴 | 推奨場面 |
|---|---|---|
| Array.from + filter | 柔軟・複雑な条件に対応 | 動的なインデックス指定・複数除外 |
| :not(:nth-child(n)) | CSS セレクタのみで完結 | 固定のインデックス除外 |
| children + for ループ | ライブコレクション・高速 | シンプルなループ処理 |
Array.from + filter で除外する(推奨)
最も柔軟な方法です。children を配列に変換し、filter でインデックスを条件にして除外します。
HTML
<ul id="list"> <li>アイテム 1</li> <li>アイテム 2</li> <li>アイテム 3</li> <li>アイテム 4</li> <li>アイテム 5</li> </ul>
JavaScript
const list = document.getElementById("list");
const n = 2; // 除外したいインデックス(0始まり → 3番目の要素)
// children を配列に変換してフィルタリング
const filtered = Array.from(list.children).filter((_, index) => index !== n);
console.log(filtered.length); // 4(5要素中1つ除外)
filtered.forEach(el => console.log(el.textContent));
// "アイテム 1", "アイテム 2", "アイテム 4", "アイテム 5"
スプレッド構文でも同様に配列変換できます。
スプレッド構文版
const filtered = [...list.children].filter((_, i) => i !== n);
Array.from(list.children) と [...list.children] は同じ結果です。好みで使い分けてください。CSS セレクタ :not(:nth-child(n)) で除外する
CSS の :not(:nth-child(n)) を querySelectorAll に渡すことで、特定の位置の要素を除外して取得できます。
JavaScript
const list = document.getElementById("list");
// 3番目(:nth-childは1始まり)以外の子要素を取得
const filtered = list.querySelectorAll(":scope > li:not(:nth-child(3))");
filtered.forEach(el => console.log(el.textContent));
// "アイテム 1", "アイテム 2", "アイテム 4", "アイテム 5"
:nth-child は 1 始まりです。JavaScript のインデックス(0 始まり)とは 1 ずれるため、0 始まりのインデックス n を使う場合は :nth-child(${n + 1}) で変換してください。先頭・末尾を除外する CSS セレクタ
| セレクタ | 除外される要素 |
|---|---|
:not(:first-child) |
先頭の要素 |
:not(:last-child) |
末尾の要素 |
:not(:nth-child(3)) |
3 番目の要素 |
:not(:nth-child(odd)) |
奇数番目の要素 |
:not(:nth-child(even)) |
偶数番目の要素 |
先頭以外を取得
// 先頭の li 以外を取得
const withoutFirst = list.querySelectorAll(":scope > li:not(:first-child)");
// 末尾の li 以外を取得
const withoutLast = list.querySelectorAll(":scope > li:not(:last-child)");
:scope を付けることで、list の直接の子要素のみが対象になります。省略すると孫要素以降も含まれてしまいます。children プロパティと for ループで除外する
JavaScript
const list = document.getElementById("list");
const n = 2;
for (let i = 0; i < list.children.length; i++) {
if (i === n) continue; // n番目をスキップ
console.log(list.children[i].textContent);
}
children はライブコレクション(DOM の変更がリアルタイムに反映される)です。ループ中に要素を追加・削除すると挙動が変わるため注意してください。
複数のインデックスをまとめて除外する
JavaScript
const list = document.getElementById("list");
// 除外したいインデックスのセット
const excludeIndexes = new Set([0, 2, 4]);
const filtered = [...list.children].filter((_, i) => !excludeIndexes.has(i));
filtered.forEach(el => console.log(el.textContent));
// "アイテム 2", "アイテム 4"
特定のクラスを持つ要素以外を取得
JavaScript
// .active クラスを持つ要素以外を取得
const inactive = [...list.children].filter(el => !el.classList.contains("active"));
// CSS セレクタでも可能
const inactive2 = list.querySelectorAll(":scope > li:not(.active)");
特定の要素ノード以外を取得
JavaScript
const targetEl = list.children[2]; // 除外したい要素の参照 const others = [...list.children].filter(el => el !== targetEl);
:nth-child と :nth-of-type の違い
| セレクタ | 基準 | 注意点 |
|---|---|---|
:nth-child(n) |
親要素の中で n 番目の子要素 | 要素の種類に関係なくカウント |
:nth-of-type(n) |
同じタグ種類の中で n 番目 | タグ種類ごとにカウント |
HTML
<div id="mixed"> <h2>見出し</h2> <p>段落1</p> <p>段落2</p> <p>段落3</p> </div>
JavaScript
// :nth-child(2) → 2番目の子要素 = <p>段落1</p>
document.querySelector("#mixed :nth-child(2)");
// :nth-of-type(2) → 2番目の <p> = <p>段落2</p>
document.querySelector("#mixed p:nth-of-type(2)");
子要素が同じタグ種類だけなら
:nth-child と :nth-of-type の結果は同じです。異なるタグが混在する場合に結果が変わります。実務でよく使うパターン
テーブルのヘッダー行以外(データ行のみ)を取得する
JavaScript
const table = document.getElementById("myTable");
// tbody の全行を取得(ヘッダーは thead にあるため自然に除外)
const dataRows = table.querySelectorAll("tbody tr");
// thead がなく tr が直接並んでいる場合: 先頭以外を取得
const rows = [...table.querySelectorAll("tr")].filter((_, i) => i !== 0);
// CSS セレクタ版
const rows2 = table.querySelectorAll("tr:not(:first-child)");
タブ切り替え: 選択されたパネル以外を非表示にする
JavaScript
function switchTab(selectedIndex) {
const panels = document.querySelectorAll(".tab-panel");
panels.forEach((panel, i) => {
if (i === selectedIndex) {
panel.style.display = "block";
} else {
panel.style.display = "none";
}
});
}
switchTab(0); // 最初のパネルだけ表示
リストから選択中の要素以外のスタイルをリセットする
JavaScript
const items = document.querySelectorAll(".nav-item");
items.forEach(item => {
item.addEventListener("click", () => {
// 全アイテムから active を削除
items.forEach(el => el.classList.remove("active"));
// クリックされたアイテムだけ active を付与
item.classList.add("active");
});
});
ドラッグ&ドロップ: 移動中の要素以外にドロップ先を表示する
JavaScript
let draggedItem = null;
document.querySelectorAll(".sortable-item").forEach(item => {
item.addEventListener("dragstart", () => { draggedItem = item; });
item.addEventListener("dragover", (e) => {
e.preventDefault();
// 自分以外のアイテムにドロップ先スタイルを適用
if (item !== draggedItem) {
item.classList.add("drop-target");
}
});
item.addEventListener("dragleave", () => {
item.classList.remove("drop-target");
});
});
関連記事
- 子要素を取得・操作する方法 — children・firstElementChild
- 兄弟要素を取得する方法 — nextElementSibling
- querySelector / querySelectorAll の使い方
- classList の使い方完全ガイド
- 配列から偶数・奇数番目の要素を取得する方法
よくある質問
Q:nth-child のインデックスは 0 始まりですか?
Aいいえ、
:nth-child は 1 始まりです。JavaScript のインデックス(0 始まり)とは 1 ずれます。JavaScript のインデックス n を CSS セレクタに変換するには :nth-child(${n + 1}) としてください。Qchildren と childNodes の違いは?
A
children は要素ノード(HTML タグ)のみを返します。childNodes はテキストノードやコメントノードも含むすべてのノードを返します。通常は children を使います。Q複数のインデックスをまとめて除外するには?
A除外するインデックスを
Set に入れ、filter((_, i) => !set.has(i)) で一括除外できます。CSS セレクタでは :not(:nth-child(2)):not(:nth-child(4)) のように複数の :not を連結します。Q:not(:nth-child(n)) のブラウザ対応は?
Aモダンブラウザ(Chrome・Firefox・Safari・Edge)すべてで対応しています。IE は
:not のセレクタリスト(:not(:nth-child(2), :nth-child(4)))に非対応ですが、個別に :not(:nth-child(2)):not(:nth-child(4)) と連結すれば IE11 でも動作します。QquerySelectorAll の :scope は何ですか?
A
:scope は querySelectorAll の基準要素自体を指します。el.querySelectorAll(":scope > li") で el の直接の子要素の liだけを取得できます。:scope がないと孫要素以降の li も含まれます。まとめ
n 番目以外の子要素を取得する方法を整理しました。
- Array.from + filter: 最も柔軟。複雑な条件・複数除外・動的インデックスに対応
- :not(:nth-child(n)): CSS セレクタで完結。固定インデックスの除外に最適
- children + for ループ: ライブコレクション。continue でスキップ
テーブルのヘッダー除外、タブ切り替え、ナビゲーションのアクティブ管理など、「特定の要素以外を操作する」パターンは実務で頻出します。filter と :not の両方を使いこなして、効率的な DOM 操作を実現しましょう。