querySelector と querySelectorAll は、CSS セレクタを使って HTML 要素を取得する JavaScript のメソッドです。ID・クラス・属性・疑似クラスなど、CSS で書けるあらゆるセレクタで要素を検索できるため、DOM 操作の最も汎用的な方法として広く使われています。
・querySelector(1 要素)と querySelectorAll(全要素)の違い
・CSS セレクタの書き方一覧(ID / クラス / 属性 / 疑似クラス / 複合)
・NodeList の特性と forEach / for…of でのループ
・getElementById 等との比較と使い分け
・スコープ付き検索(親要素内から検索)
・closest() / matches() との組み合わせ
・パフォーマンスの注意点
querySelector と querySelectorAll の基本
| メソッド | 戻り値 | 該当なし |
|---|---|---|
| querySelector(selector) | 最初に一致した 1 要素(Element) | null |
| querySelectorAll(selector) | 一致した 全要素(NodeList) | 空の NodeList(length=0) |
// querySelector: 最初の 1 要素を取得
const header = document.querySelector("h1");
const firstCard = document.querySelector(".card");
const mainTitle = document.querySelector("#main-title");
// querySelectorAll: 一致する全要素を取得
const allCards = document.querySelectorAll(".card");
console.log(allCards.length); // 一致した要素数
// 見つからない場合
const notFound = document.querySelector(".nonexistent"); // null
const empty = document.querySelectorAll(".nonexistent"); // NodeList [] (length=0)
使える CSS セレクタの一覧
| セレクタ | 意味 | 例 |
|---|---|---|
| #id | ID | querySelector(“#main-title”) |
| .class | クラス | querySelectorAll(“.card”) |
| tag | タグ名 | querySelectorAll(“p”) |
| .class1.class2 | 複数クラス AND | querySelector(“.card.active”) |
| .class1, .class2 | 複数セレクタ OR | querySelectorAll(“.card, .item”) |
| parent child | 子孫 | querySelectorAll(“.sidebar a”) |
| parent > child | 直接の子 | querySelectorAll(“ul > li”) |
| el + el | 隣接兄弟 | querySelector(“h2 + p”) |
| el ~ el | 後続兄弟 | querySelectorAll(“h2 ~ p”) |
| [attr] | 属性あり | querySelectorAll(“[data-id]”) |
| [attr=”val”] | 属性値一致 | querySelector(‘[type=”email”]’) |
| [attr^=”val”] | 属性値が val で始まる | querySelectorAll(‘[href^=”https”]’) |
| [attr$=”val”] | 属性値が val で終わる | querySelectorAll(‘[src$=”.png”]’) |
| [attr*=”val”] | 属性値が val を含む | querySelectorAll(‘[class*=”btn”]’) |
| :first-child | 最初の子要素 | querySelector(“li:first-child”) |
| :last-child | 最後の子要素 | querySelector(“li:last-child”) |
| :nth-child(n) | N 番目の子要素 | querySelector(“tr:nth-child(2)”) |
| :not(selector) | 否定 | querySelectorAll(“input:not([type=hidden])”) |
| :checked | チェック済み | querySelectorAll(“input:checked”) |
| :disabled | 無効化 | querySelectorAll(“input:disabled”) |
querySelector / querySelectorAll は CSS のセレクタ仕様に準拠しています。CSS で要素を指定できるなら JavaScript でもそのまま使えます。疑似要素(::before / ::after)は DOM に存在しないため取得できません。
// data 属性で取得
const user = document.querySelector('[data-user-id="42"]');
// フォームの特定 input
const emailInput = document.querySelector('input[type="email"]');
// チェック済みのラジオボタン
const checked = document.querySelector('input[name="plan"]:checked');
// hidden 以外の全 input
const visibleInputs = document.querySelectorAll('input:not([type="hidden"])');
// テーブルの偶数行
const evenRows = document.querySelectorAll("tr:nth-child(even)");
NodeList の特性とループ
const cards = document.querySelectorAll(".card");
// forEach(最もシンプル)
cards.forEach(card => {
card.classList.add("active");
});
// for...of
for (const card of cards) {
card.classList.add("active");
}
// インデックス付きアクセス
console.log(cards[0]); // 最初の要素
console.log(cards.length); // 要素数
// 配列メソッド(filter / map 等)を使いたい場合
const activeCards = [...cards].filter(c => c.classList.contains("active"));
// または Array.from(cards).filter(...)
| NodeList の特性 | 内容 |
|---|---|
| 静的(スナップショット) | 取得時点の要素。DOM の変更は反映されない |
| forEach 対応 | IE 11 以外は直接使える |
| インデックスアクセス | cards[0] / cards[1] で個別アクセス可能 |
| length | 要素数を取得可能 |
| filter / map 等 | 直接は使えない。スプレッド構文 […cards] で配列に変換して使う |
querySelectorAll が返す NodeList は取得時点のスナップショットです。後から DOM に要素を追加・削除しても NodeList の中身は変わりません。これは getElementsByClassName(ライブ)とは異なる動作です。
スコープ付き検索(親要素内から検索)
// document 全体ではなく、特定の親要素内から検索
const sidebar = document.querySelector(".sidebar");
const sidebarLinks = sidebar.querySelectorAll("a");
// .sidebar 内の a 要素だけ取得
// CSS の子孫セレクタでも同じ結果
const sidebarLinks2 = document.querySelectorAll(".sidebar a");
// 注意: sidebar が null の場合 → エラー
// sidebar?.querySelectorAll("a") で安全に
document.querySelector はページ全体を検索しますが、element.querySelector はその要素の子孫だけを検索します。検索範囲を絞ることでパフォーマンスも向上します。getElementById 等との比較
| メソッド | セレクタ | 戻り値 | 速度 | 推奨 |
|---|---|---|---|---|
| querySelector | CSS セレクタ全般 | Element / null | 普通 | 推奨(汎用) |
| querySelectorAll | CSS セレクタ全般 | NodeList(静的) | 普通 | 推奨(汎用) |
| getElementById | ID のみ | Element / null | 最速 | ID のみなら可 |
| getElementsByClassName | クラスのみ | HTMLCollection(ライブ) | 速い | 非推奨(ライブの罠) |
| getElementsByTagName | タグのみ | HTMLCollection(ライブ) | 速い | 非推奨 |
getElementById は僅かに速いですが、実測で体感できる差はありません。querySelector 系は CSS セレクタの知識がそのまま使え、ID / クラス / 属性 / 複合条件をすべて 1 つの API で扱えます。チーム内で統一するなら querySelector 系に統一するのが合理的です。
closest() / matches() との組み合わせ
// クリックされた要素から最も近い .card を探す
document.addEventListener("click", (e) => {
const card = e.target.closest(".card");
if (card) {
console.log("カードがクリックされた");
}
});
// 要素が特定のセレクタに一致するか
const el = document.querySelector(".card");
console.log(el.matches(".card.active")); // true / false
// イベントデリゲーションで活用
document.addEventListener("click", (e) => {
if (e.target.matches(".delete-btn")) {
e.target.closest(".card").remove();
}
});
| メソッド | 方向 | 用途 |
|---|---|---|
| querySelector | 下方向(子孫を検索) | 子要素の中から条件に合う要素を取得 |
| closest | 上方向(祖先を検索) | クリックされた要素の親を辿って特定の要素を見つける |
| matches | 自分自身 | 要素がセレクタに一致するか判定(boolean) |
実務パターン集
パターン(1): フォームの全入力値を取得
const form = document.querySelector("#myForm");
const inputs = form.querySelectorAll("input, select, textarea");
const formData = {};
inputs.forEach(input => {
if (input.name) {
formData[input.name] = input.value;
}
});
console.log(formData);
パターン(2): 外部リンクに target=”_blank” を自動付与
document.querySelectorAll('a[href^="http"]').forEach(link => {
if (!link.hostname.includes(location.hostname)) {
link.setAttribute("target", "_blank");
link.setAttribute("rel", "noopener noreferrer");
}
});
パターン(3): テーブルの偶数行にクラスを付与
document.querySelectorAll("table.striped tr:nth-child(even)").forEach(row => {
row.classList.add("bg-gray");
});
パターン(4): チェック済みチェックボックスの値を取得
const checked = document.querySelectorAll('input[name="categories"]:checked');
const values = [...checked].map(cb => cb.value);
console.log(values); // ["food", "drink"]
パターン(5): イベントデリゲーション
// 親要素 1 つにイベントを登録し、子要素をセレクタで判定
document.querySelector(".todo-list").addEventListener("click", (e) => {
const deleteBtn = e.target.closest(".delete-btn");
if (deleteBtn) {
deleteBtn.closest(".todo-item").remove();
}
});
パフォーマンスの注意点
| 注意点 | 対策 |
|---|---|
| ループ内で毎回 querySelector を呼ぶ | 変数にキャッシュしてループ外で 1 回だけ取得 |
| document 全体を検索する | 親要素を起点に検索範囲を絞る |
| 複雑すぎるセレクタ | セレクタを分割して段階的に検索 |
// NG: ループ内で毎回検索
// for (...) { document.querySelector(".header").style.color = "red"; }
// OK: 変数にキャッシュ
const header = document.querySelector(".header");
if (header) header.style.color = "red";
よくある質問
querySelector は最初に一致した 1 要素を返します(見つからなければ null)。querySelectorAll は一致した全要素の NodeList を返します(見つからなければ空の NodeList)。const arr = [...document.querySelectorAll(".card")];
const active = arr.filter(c => c.classList.contains("active"));getComputedStyle(el, "::before") を使います。querySelector("#my\\:id")(JS の文字列でバックスラッシュ 2 つ)または
CSS.escape() を使います: querySelector("#" + CSS.escape("my:id"))el.shadowRoot.querySelector(".inner-element")まとめ
querySelector / querySelectorAll の要点をまとめます。
| やりたいこと | 方法 |
|---|---|
| 最初の 1 要素を取得 | document.querySelector(“selector”) |
| 全要素を取得 | document.querySelectorAll(“selector”) |
| ID で取得 | querySelector(“#myId”) |
| クラスで取得 | querySelectorAll(“.myClass”) |
| 属性で取得 | querySelector(‘[data-id=”42″]’) |
| 複合条件(AND) | querySelector(“.card.active”) |
| 複合条件(OR) | querySelectorAll(“.card, .item”) |
| 親要素内から検索 | parent.querySelectorAll(“selector”) |
| 祖先要素を検索 | element.closest(“selector”) |
| セレクタ一致判定 | element.matches(“selector”) |
| NodeList をループ | forEach / for…of / […nodeList].filter() |
ID での取得は「ID で要素を取得する方法」、クラスでの取得は「クラス名で要素を取得する方法」も併せて参照してください。

