本文へスキップ
JavaScript 基礎 JavaScript querySelectorAll forEach

複数のHTML要素をまとめて操作しよう

更新日:2026-08-02

同じ役割のボタンが複数ある場合は、要素ごとに処理を繰り返し書かず、まとめて取得して処理します。

今回は、記事一覧をカテゴリで絞り込むボタンを作ります。この記事を終えると、querySelectorAll()の戻り値、forEach()の役割、クリックされた要素の見分け方を説明できるようになります。

今回使用するファイル構成

javascript-practice/
├── index.html
└── js/
    └── script.js

複数要素を扱う流れ

querySelectorAllで取得する

<button class="filter-button" type="button">HTML</button>
<button class="filter-button" type="button">CSS</button>
<button class="filter-button" type="button">JavaScript</button>
const buttons = document.querySelectorAll('.filter-button');
console.log(buttons.length);

querySelectorAll()は条件に一致する要素をNodeListとして返します。

forEachでイベントを登録する

buttons.forEach((button) => {
  button.addEventListener('click', () => {
    buttons.forEach((item) => item.classList.remove('is-active'));
    button.classList.add('is-active');
  });
});

クリックされたbuttonだけへ.is-activeを追加する前に、すべてのボタンから同じクラスを削除しています。

コールバックの要素を確認する

buttons.forEach((button, index) => {
  console.log(index, button.textContent);
});

要素と番号をConsoleへ出すと、繰り返しの対象を確認できます。

要素が0件でもエラーにならない

querySelector()は見つからない場合にnullを返しますが、querySelectorAll()は要素数0のNodeListを返します。forEach()の処理は実行されません。

記事の絞り込み機能を完成させる

絞り込み対象をHTMLへ追加する

先ほどのボタンにdata-category属性を付け、記事側にも対応する値を持たせます。

<div aria-label="記事の絞り込み">
  <button class="filter-button is-active" type="button" data-category="all">すべて</button>
  <button class="filter-button" type="button" data-category="html">HTML</button>
  <button class="filter-button" type="button" data-category="css">CSS</button>
  <button class="filter-button" type="button" data-category="javascript">JavaScript</button>
</div>

<p id="filter-result" aria-live="polite"></p>

<ul>
  <li class="article-item" data-category="html">HTMLの基本</li>
  <li class="article-item" data-category="css">Flexbox入門</li>
  <li class="article-item" data-category="javascript">DOM操作</li>
</ul>

data-categoryは、画面に表示しない補助データです。詳しい仕組みは第16回で扱います。

クリックしたカテゴリだけを表示する

js/script.jsを次の内容にします。

const buttons = document.querySelectorAll('.filter-button');
const articles = document.querySelectorAll('.article-item');
const result = document.querySelector('#filter-result');

buttons.forEach((button) => {
  button.addEventListener('click', () => {
    const selectedCategory = button.dataset.category;
    let visibleCount = 0;

    buttons.forEach((item) => {
      item.classList.remove('is-active');
    });
    button.classList.add('is-active');

    articles.forEach((article) => {
      const shouldShow =
        selectedCategory === 'all' ||
        article.dataset.category === selectedCategory;

      article.hidden = !shouldShow;

      if (shouldShow) {
        visibleCount += 1;
      }
    });

    result.textContent = `${visibleCount}件の記事を表示しています。`;
  });
});

hiddentrueを設定すると要素が非表示になります。!shouldShowは真偽値を反転するため、「表示する条件に当てはまらない要素を隠す」という意味です。

動作を順番に確認する

  1. HTMLボタンを押し、HTMLの記事だけが残ることを確認する
  2. CSSとJavaScriptでも同様に確認する
  3. 「すべて」で3件に戻ることを確認する
  4. 選択中のボタンだけにis-activeが付くことをDevToolsで確認する

よくある間違い

最後の一件しか処理されない

querySelector()は最初の一件だけを返します。複数件を処理する場合はquerySelectorAll()を使います。

forEachの中で同じ変数名を使って混乱する

ボタン全体はbuttons、現在処理中の一件はbuttonのように、単数形と複数形を使い分けます。

NodeListは配列と同じなのか

NodeListは配列に似ていますが、配列のすべてのメソッドを持つわけではありません。forEach()は使えます。filter()map()が必要ならArray.from(buttons)で配列へ変換します。

まとめ

複数要素はquerySelectorAll()で取得し、forEach()で同じ処理を適用できます。次の記事では、JavaScriptから新しいHTML要素を作成・追加・削除します。