【jQuery】一定数以上のリスト・ニュースを「もっと見る」で折りたたむ完全ガイド|nth-child・slideToggle・段階的表示・完全展開まで

ニュース一覧や記事リストで「最初は数件だけ表示して、残りは「もっと見る」ボタンで展開する」というUIはページをすっきりさせるとともに、ユーザーが必要に応じてコンテンツを取得できる優れたUXパターンです。

この記事ではCSSのnth-child・jQueryのslideToggle・段階的に追加表示する方法まで、用途に合わせた複数の実装パターンを解説します。

この記事でわかること

  • CSS nth-child で初期表示件数を制限する
  • 「もっと見る」「閉じる」ボタンのテキスト連動
  • アイテム数が少ない場合にボタンを非表示にする
  • 「もっと見る」を押すたびに数件ずつ追加表示する(段階的表示)
  • 完全展開後にボタンを非表示にする
スポンサーリンク

基本実装: CSS + jQuery で折りたたみ

最もシンプルなパターンです。CSSで4件目以降を非表示にし、ボタンクリックで slideToggle() を使って開閉します。

HTML

<ul class="news-list">
  <li><span class="news-date">2025年12月01日</span>新機能をリリースしました。</li>
  <li><span class="news-date">2025年11月15日</span>メンテナンスのお知らせ</li>
  <li><span class="news-date">2025年10月30日</span>サービス料金を改定しました。</li>
  <li><span class="news-date">2025年10月01日</span>秋のキャンペーンを開始しました。</li>
  <li><span class="news-date">2025年09月12日</span>UI/UXをリニューアルしました。</li>
  <li><span class="news-date">2025年08月25日</span>アプリの最新版を公開しました。</li>
</ul>
<button class="more-btn">もっと見る</button>

CSS(初期表示を3件に制限)

.news-list > li:nth-child(n+4) {
  display: none;
}

JavaScript

$(function () {
  // アイテムが3件以下ならボタンを非表示
  var limit = 3;
  if ($('.news-list > li').length <= limit) {
    $('.more-btn').hide();
  }

  $('.more-btn').on('click', function () {
    var isOpen = $(this).hasClass('is-open');

    // 4件目以降をslideで開閉
    $('.news-list > li:nth-child(n+' + (limit + 1) + ')').slideToggle(300);

    // ボタンのテキストと状態を切り替える
    $(this)
      .text(isOpen ? 'もっと見る' : '閉じる')
      .toggleClass('is-open');
  });
});
nth-child の番号は 1始まり
:nth-child(n+4) は「4番目以降の要素」を意味します。最初の3件(1・2・3番目)を表示し、4番目以降を隠します。表示件数を5件にしたい場合は :nth-child(n+6) に変更してください。

初期表示件数をJavaScriptで制御する(推奨)

CSSではなくJavaScriptで初期表示件数を制御する方法です。WordPressなどで件数を動的に変更したい場合や、スマホとPCで件数を変えたい場合に便利です。

<ul id="news-list">
  <li>ニュース1</li>
  <li>ニュース2</li>
  <li>ニュース3</li>
  <li>ニュース4</li>
  <li>ニュース5</li>
  <li>ニュース6</li>
</ul>
<button id="more-btn">もっと見る</button>
$(function () {
  var LIMIT = 3;  // 初期表示件数
  var $items  = $('#news-list > li');
  var $btn    = $('#more-btn');

  // 初期状態: LIMIT件目以降を非表示
  $items.slice(LIMIT).hide();

  // 件数がLIMIT以下ならボタン不要
  if ($items.length <= LIMIT) {
    $btn.hide();
    return;
  }

  $btn.on('click', function () {
    var isOpen = $(this).hasClass('is-open');

    if (isOpen) {
      // 閉じる: LIMITより後を非表示 + スクロールを先頭へ
      $items.slice(LIMIT).slideUp(300);
      $(this).text('もっと見る').removeClass('is-open');
    } else {
      // 開く: 全件表示
      $items.slice(LIMIT).slideDown(300);
      $(this).text('閉じる').addClass('is-open');
    }
  });
});

「もっと見る」を押すたびに数件ずつ追加表示する

SNSのタイムラインのように、クリックするたびに数件ずつ追加で表示するパターンです。全件表示後はボタンを非表示にします。

$(function () {
  var INITIAL = 3;   // 最初に表示する件数
  var ADD     = 3;   // 「もっと見る」で追加する件数
  var shown   = INITIAL;
  var $items  = $('#news-list > li');
  var $btn    = $('#more-btn');

  // 初期状態: INITIAL件のみ表示
  $items.hide().slice(0, shown).show();

  // 全件以下なら最初からボタンを非表示
  if ($items.length <= INITIAL) {
    $btn.hide();
    return;
  }

  $btn.on('click', function () {
    // 次の ADD 件を表示
    $items.slice(shown, shown + ADD).slideDown(300);
    shown += ADD;

    // 全件表示したらボタンを非表示
    if (shown >= $items.length) {
      $(this).fadeOut(200);
    }
  });
});
段階的表示 vs 全件開閉 の使い分け

  • 段階的表示(追加ロード): ニュース・記事一覧など、戻る必要がない一方向のリスト
  • 全件開閉(アコーディオン): FAQ・チームメンバー一覧など、折りたたむことがある場合

CSS トランジションを使ったスムーズなアニメーション

slideToggle() の代わりにCSSトランジションを使うと、より滑らかなアニメーションが実現できます。ただし height: auto はトランジションが効かないため、max-height を使うテクニックを使います。

.news-list > li:nth-child(n+4) {
  display: block;        /* display:none ではなく */
  max-height: 0;         /* max-height でアニメーション */
  overflow: hidden;
  transition: max-height 0.3s ease, opacity 0.3s ease;
  opacity: 0;
}

.news-list.is-open > li:nth-child(n+4) {
  max-height: 200px;     /* 十分に大きな値 */
  opacity: 1;
}
$(function () {
  $('.more-btn').on('click', function () {
    $('.news-list').toggleClass('is-open');
    var isOpen = $('.news-list').hasClass('is-open');
    $(this).text(isOpen ? '閉じる' : 'もっと見る');
  });
});

「もっと見る」とページネーションの比較

方式 メリット デメリット 向いているケース
もっと見る(全開閉) シンプル・折りたたみ可能 全件DOMが必要 ニュース・FAQ・チームページ
段階的追加表示 軽い初期ロード・自然なUX 戻れない(閉じられない) SNSタイムライン・記事一覧
Ajax追加ロード 大量データに対応・初期ロード軽い 実装が複雑・サーバー連携必要 ECサイト・ブログ一覧
ページネーション URLで状態共有可能・SEO有利 ページ遷移が発生 ブログ・検索結果

まとめ

jQueryで「もっと見る」UIを実装する方法を用途によって選びましょう。

  • シンプル開閉: CSS :nth-child(n+4) + slideToggle()
  • JS管理推奨: $items.slice(LIMIT).hide() で件数を変数管理
  • 段階的表示: slice(shown, shown + ADD).slideDown() で追加表示
  • 全件表示後: fadeOut() でボタンを非表示
  • CSSアニメ: max-height + transition でスムーズな開閉

関連記事: アコーディオン完全ガイド / アコーディオン実装方法の完全比較 / ボタンクリックで要素の表示・非表示を切り替える

よくある質問(FAQ)

Q「閉じる」後に先頭へスクロールしたいです。
A閉じるアクション後に $("html, body").animate({ scrollTop: $("#news-list").offset().top - 20 }, 300) でリストの先頭にスクロールできます。ユーザーが「閉じた後どこを見ていたかわからなくなる」問題を防げます。
Qスマホは3件、PCは5件のように件数を変えたいです。
Avar LIMIT = $(window).width() < 768 ? 3 : 5; のように ウィンドウ幅で初期値を変えてください。リサイズ時の対応が必要な場合は$(window).on("resize") でも再計算するとより確実です。
QWordPressでカスタムフィールドの件数に応じて動的に制御したいです。
APHPでアイテム数を data-count 属性などでHTML側に出力し、JavaScriptで parseInt($(el).data("count")) で取得する方法が安全です。または最初からアイテム数を数えて $items.length で判定しても同じことができます。
Q開閉状態をページ遷移後も保持したいです(前ページで開いていたら次もopen)。
AsessionStorage.setItem("newsOpen", "1") で状態を保存し、ページロード時に sessionStorage.getItem("newsOpen") で読み込んで自動展開する方法が使えます。
QAjaxで動的にリストを追加した場合はどうすれば良いですか?
AAjaxでアイテムを追加した後、$items = $("#news-list > li") で変数を取り直し、shown 変数が更新された件数に合わせてボタンの表示・非表示を再判定してください。段階的表示の場合は新しいアイテムだけ非表示にして追加し、ボタンの状態を再チェックします。