【JavaScript】指定した要素が一定数以上ある場合にアコーディオンを実装する方法

リストの件数が多いとき、最初の数件だけ見せて残りは「もっと見る」で折りたためると、ページがすっきりします。この記事では、要素が一定数を超えたときだけ折りたたみ(アコーディオン)を適用する方法を解説します。

この記事の結論:querySelectorAll で件数を数え、最大表示数を超えたときだけ超過分を display: none で隠し、「もっと見る」ボタンを追加します。ボタンのクリックで表示を切り替え、aria-expanded も更新します。件数が最大数以下なら、ボタンは作りません。
スポンサーリンク

完成イメージ(動くデモ)

↓ 6件目以降が隠れ、「もっと見る」で開閉します:

  • アイテム1
  • アイテム2
  • アイテム3
  • アイテム4
  • アイテム5
  • アイテム6
  • アイテム7
  • アイテム8

件数をチェックして超過分を隠す

まず対象の要素を取得し、最大表示数を超えているかを確認します。超えていなければ折りたたみは不要なので、何もしません。

JavaScript:超過分を隠す
const items = document.querySelectorAll(".item");
const MAX = 5; // 最初に見せる件数

if (items.length > MAX) {
  // 6件目以降を隠す
  items.forEach((item, index) => {
    if (index >= MAX) item.style.display = "none";
  });
  // …続けてボタンを追加(次の節)
}

「もっと見る」ボタンで開閉する

createElement でボタンを作り、リストの最後に追加します。クリックで隠れている要素の表示を切り替え、aria-expanded とボタンの文言も更新します。

JavaScript:ボタンの生成と開閉
const button = document.createElement("button");
button.textContent = "もっと見る";
button.className = "show-more";
button.setAttribute("aria-expanded", "false");

// リストの最後(最後のアイテムの後ろ)に置く
items[items.length - 1].after(button);

let isOpen = false;
button.addEventListener("click", () => {
  isOpen = !isOpen;
  items.forEach((item, index) => {
    if (index >= MAX) item.style.display = isOpen ? "" : "none";
  });
  button.textContent = isOpen ? "閉じる" : "もっと見る";
  button.setAttribute("aria-expanded", String(isOpen));
});

要素の表示/非表示の切り替えは要素の表示/非表示を切り替える方法、ボタンの動的生成はcreateElementで要素を作って追加する方法も参考になります。

ボタンに残りの件数を表示する

「もっと見る」だけより、「もっと見る(あと3件)」のように残りの件数を見せると、ユーザーが押すか判断しやすくなります。隠した件数は items.length - MAX で計算できます。

JavaScript:残り件数つきのボタン
const hidden = items.length - MAX; // 隠れている件数
button.textContent = `もっと見る(あと${hidden}件)`;

button.addEventListener("click", () => {
  isOpen = !isOpen;
  items.forEach((item, index) => {
    if (index >= MAX) item.style.display = isOpen ? "" : "none";
  });
  // 開いているときは「閉じる」、閉じているときは残数を表示
  button.textContent = isOpen ? "閉じる" : `もっと見る(あと${hidden}件)`;
  button.setAttribute("aria-expanded", String(isOpen));
});

単純な開閉なら details 要素も検討

「件数で出し分ける」必要がなく、単純に1つのブロックを開閉するだけなら、HTML標準の <details> / <summary> が手軽です。JavaScriptなしで開閉でき、キーボード操作にも標準対応します。

HTML:detailsで開閉(JS不要)
<details>
  <summary>もっと見る</summary>
  <ul>
    <li>追加のアイテム1</li>
    <li>追加のアイテム2</li>
  </ul>
</details>

ただし「最初の数件は常に表示し、超過分だけ折りたたむ」という今回の用途では、件数判定が必要なため、上記のJavaScript実装が向いています。

開閉にアニメーションを付ける(任意)

displayはアニメできない:display: none ⇔ block の切り替えはアニメーションできません。ふわっと開きたいときは、隠す要素を1つのコンテナにまとめ、コンテナに max-height: 0; overflow: hidden; transition: max-height .3s; を設定して、クラスで max-height を切り替える方法が定番です。クラス操作はclassListの使い方を参照してください。
CSS:max-heightで開閉アニメ
.more-area {
  max-height: 0;
  overflow: hidden;
  transition: max-height 0.3s ease;
}
.more-area.open {
  max-height: 500px; /* 中身が収まる十分な値 */
}

よくある質問(FAQ)

Q要素の数が一定以上のときだけ折りたたむには?
AquerySelectorAll で件数を数え、items.length > 最大数 のときだけ処理します。超過分を display: none で隠し、「もっと見る」ボタンの click で表示を切り替えます。件数が最大数以下なら、ボタンは作りません。
Qアコーディオンの開閉アニメーションを実装するには?
Adisplay はアニメーションできないため、隠す範囲をコンテナにまとめ、max-height: 0 から大きな値への transition を使います。overflow: hidden も必須です。
Qデフォルトで何件まで表示するのが良いですか?
A3〜5件が一般的です。多すぎると見きれず、少なすぎると魅力が伝わりません。モバイルでは少なめにするなど、画面サイズに応じて調整するのも有効です。
Qアクセシビリティで気をつけることは?
Aトグルボタンに aria-expanded を付け、開閉に合わせて true / false を更新します。これでスクリーンリーダーにも開閉状態が伝わります。

まとめ

要素が一定数を超えたときだけ折りたたむには、querySelectorAll で件数を数え、超過分を display: none で隠して「もっと見る」ボタンで開閉します。件数が最大数以下ならボタンは不要です。

ボタンには aria-expanded を付けて状態を伝え、ふわっと開きたいときは max-heighttransition でアニメーションさせましょう。