JavaScriptでHTMLの要素を取得するときによく使うのが、document.querySelector() です。引数にはCSSと同じ書き方(セレクター)を使えるので、CSSを少し書いたことがあれば、その知識をそのまま活かせます。
この記事では、querySelector と querySelectorAll に渡すセレクターの書き方を種類ごとにまとめ、使うときにつまずきやすい点も紹介します。
querySelector と querySelectorAll の違い
| メソッド | 戻り値 | 見つからないとき |
|---|---|---|
querySelector() | 条件に合う最初の1つの要素 | null |
querySelectorAll() | 条件に合うすべての要素(NodeList) | 空の NodeList(件数0) |
1つだけ欲しいときは querySelector、まとめて処理したいときは querySelectorAll を使います。セレクターの書き方はどちらも同じです。
基本のセレクター
| 種類 | 記号 | 書き方の例 | 取得できる要素 |
|---|---|---|---|
| 要素(タグ) | なし | 'div' | <div> 要素 |
| ID | # | '#app' | id="app" の要素 |
| クラス | . | '.btn' | class に btn を含む要素(class="btn primary" も対象) |
| 組み合わせ | つなげて書く | 'button.btn.primary' | class に btn と primary の両方を含む <button> |
const header = document.querySelector('header');
const title = document.querySelector('#title');
const submitButton = document.querySelector('.submit-btn');属性で指定する(属性セレクター)
type や href、自分で付けられる data-* 属性などで絞り込めます。フォームの部品を取得するときによく使います。
| 条件 | 書き方の例 | 取得できる要素 |
|---|---|---|
| 属性がある | '[disabled]' | disabled 属性が付いている要素 |
| 値が一致 | '[type="text"]' | type が text の要素 |
| 値が〜で始まる | '[href^="https"]' | href が https で始まる要素 |
| 値が〜で終わる | '[src$=".png"]' | src が .png で終わる要素 |
| 値に〜を含む | '[class*="icon-"]' | class の文字列に icon- を含む要素 |
// チェックボックスを取得
const checkbox = document.querySelector('input[type="checkbox"]');
// data-status="active" が付いた要素を取得
const activeTab = document.querySelector('[data-status="active"]');セレクターの中で " を使うので、外側を ' で囲むとエスケープがいりません。クォートの使い分けは「文字列の ‘ と ” と ` の違い」で紹介しています。
親子や兄弟の関係で指定する(結合子)
HTMLの入れ子の関係を使って、目的の要素を絞り込みます。
| 種類 | 記号 | 書き方の例 | 取得できる要素 |
|---|---|---|---|
| 子孫(中にあるものすべて) | 半角スペース | 'ul li' | <ul> の中にある <li>(入れ子の奥も含む) |
| 子(すぐ下だけ) | > | 'ul > li' | <ul> のすぐ下にある <li> |
| すぐ後ろの兄弟 | + | 'h2 + p' | <h2> のすぐ後ろにある <p> |
| 後ろにある兄弟 | ~ | 'h2 ~ p' | <h2> より後ろにある、同じ親の <p> |
// .nav-menu のすぐ下の li の、すぐ下の a を取得
const navLink = document.querySelector('.nav-menu > li > a');状態や順番で指定する(疑似クラス)
| 種類 | 書き方の例 | 取得できる要素 |
|---|---|---|
| 最初の子 | 'li:first-child' | 親の中で最初の子である <li> |
| 最後の子 | 'li:last-child' | 親の中で最後の子である <li> |
| n番目の子 | 'li:nth-child(3)' | 親の中で3番目の子である <li> |
| 〜以外 | 'div:not(.hidden)' | class に hidden を含まない <div> |
| チェック済み | 'input:checked' | チェックが入っているチェックボックスやラジオボタン |
// チェックが入っているラジオボタン(name="plan")を取得
const selected = document.querySelector('input[name="plan"]:checked');
// .is-hidden が付いていないエラーメッセージを取得
const visibleError = document.querySelector('.error-msg:not(.is-hidden)');nth-child の勘違いに注意
.list-item:nth-child(2) は「2番目の .list-item」ではなく、「親の中で2番目の子で、かつ .list-item である要素」を指します。たとえば次のHTMLでは、結果が変わります。
<ul>
<li class="note">お知らせ</li>
<li class="list-item">項目1</li>
<li class="list-item">項目2</li>
</ul>// 親の中で2番目の子(かつ .list-item)→「項目1」
console.log(document.querySelector('.list-item:nth-child(2)').textContent);
// 2番目の .list-item →「項目2」
console.log(document.querySelectorAll('.list-item')[1].textContent);「○番目の .list-item」が欲しいときは、querySelectorAll でまとめて取得してから番号(0から数える)で選ぶと確実です。
複数のセレクターをまとめて指定する
カンマ , で区切ると、「A または B」に当てはまる要素をまとめて取得できます。取得される順番は、書いた順ではなく、HTMLの中で並んでいる順です。
// h1、h2、h3 をまとめて取得(HTMLの中の順)
const headings = document.querySelectorAll('h1, h2, h3');
// .btn-primary または .btn-secondary をまとめて取得
const buttons = document.querySelectorAll('.btn-primary, .btn-secondary');使うときにつまずきやすいこと
見つからないと null になる
querySelector は、要素が見つからないと null を返します。そのまま使うと「Cannot read properties of null」のエラーになるので、ないかもしれない要素は確かめてから使います。
const button = document.querySelector('.submit-btn');
if (button) {
button.addEventListener('click', () => {
console.log('送信');
});
}<script> を <head> に書いていると、HTMLの要素がまだ読み込まれていなくて null になることもあります。<script defer src="..."> のように defer を付けるか、</body> の直前に書くと防げます。
querySelectorAll の戻り値は配列ではない
querySelectorAll が返すのは NodeList で、配列とは少し違います。forEach や length、[0] のような番号での取り出しは使えますが、map や filter はそのままでは使えません。使いたいときは Array.from() で配列に変えます。
const items = document.querySelectorAll('li');
items.forEach(item => console.log(item.textContent)); // OK
// items.map(...) はエラーになるので、配列に変えてから使う
const texts = Array.from(items).map(item => item.textContent);filter の書き方は「filterメソッドの書き方」で紹介しています。
要素の中だけを探す
querySelector は document だけでなく、取得した要素からも呼べます。その要素の中だけを探すので、同じクラスがページのあちこちにあるときに便利です。
const nav = document.querySelector('.nav-menu');
const navLinks = nav.querySelectorAll('a'); // .nav-menu の中の a だけ書き間違いや特殊な文字はエラーになる
セレクターの書き方が間違っていると、null ではなく SyntaxError になります。数字で始まる id も、そのまま # を付けるとエラーになるので注意が必要です。
// document.querySelector('#1st'); // SyntaxError(数字で始まる id)
const el1 = document.querySelector('#' + CSS.escape('1st')); // CSS.escape で変換する
const el2 = document.getElementById('1st'); // id だけならこちらでもよいid だけで取得するなら getElementById も使えます。# を付けずに id をそのまま渡すので、このような変換もいりません。
疑似要素は取得できない
CSSの ::before や ::after のような疑似要素は、HTMLの要素ではないので querySelector では取得できません。CSSと同じ書き方といっても、取得できるのはHTMLの要素だけです。
まとめ
querySelectorは最初の1つ(なければnull)、querySelectorAllはすべて(NodeList)を返す- セレクターは、タグ・id・クラス、属性、親子・兄弟の関係、状態や順番で組み合わせられる
:nth-child(n)は「親の中でn番目の子」。「n番目の○○」ならquerySelectorAll()[n - 1]nullの確認、NodeList と配列の違い、数字で始まる id に気をつける
この記事のコードは、CodePenなどでHTMLと一緒に試すと、どの要素が取得されるかがよく分かります。取得した要素の値がないときのデフォルト値の入れ方は、「??(Null合体演算子)と三項演算子の違い」で紹介しています。



コメント