無限スクロール Infinite Scroll

スクロールに応じてコンテンツを自動的に追加読み込みする。

使用場面: SNSフィードやニュースサイトなど連続的にコンテンツを閲覧する場合 採用例: Twitter/X, Instagram

ライブデモ

記事タイトル 1 — ここにコンテンツのプレビューテキストが入ります。
記事タイトル 2 — ここにコンテンツのプレビューテキストが入ります。
記事タイトル 3 — ここにコンテンツのプレビューテキストが入ります。
記事タイトル 4 — ここにコンテンツのプレビューテキストが入ります。
記事タイトル 5 — ここにコンテンツのプレビューテキストが入ります。
読み込み中…

ソースコード

<div class="demo-infinite">
  <div class="demo-infinite-list" id="demoInfiniteList">
    <div class="demo-infinite-card">記事タイトル 1 — ここにコンテンツのプレビューテキストが入ります。</div>
    <div class="demo-infinite-card">記事タイトル 2 — ここにコンテンツのプレビューテキストが入ります。</div>
    <div class="demo-infinite-card">記事タイトル 3 — ここにコンテンツのプレビューテキストが入ります。</div>
    <div class="demo-infinite-card">記事タイトル 4 — ここにコンテンツのプレビューテキストが入ります。</div>
    <div class="demo-infinite-card">記事タイトル 5 — ここにコンテンツのプレビューテキストが入ります。</div>
  </div>
  <div class="demo-infinite-loader" id="demoInfiniteLoader">
    <div class="demo-infinite-spinner"></div>
    <span>読み込み中…</span>
  </div>
  <p class="demo-infinite-status" id="demoInfiniteStatus"></p>
</div>
.demo-infinite { min-height: 400px;
  max-height: 280px; overflow-y: auto; border: 1px solid #e5e7eb;
  border-radius: 10px; padding: 12px;
}
.demo-infinite-list { display: flex; flex-direction: column; gap: 8px; }
.demo-infinite-card {
  padding: 14px 16px; border-radius: 8px;
  background: color-mix(in srgb, var(--ui-primary) 5%, #fff);
  border-left: 3px solid var(--ui-primary);
  font-size: 13px; color: #444; line-height: 1.5;
  transition: background 0.2s;
}
.demo-infinite-card:hover {
  background: color-mix(in srgb, var(--ui-primary) 10%, #fff);
}
.demo-infinite-loader {
  display: flex; align-items: center; justify-content: center;
  gap: 8px; padding: 16px; color: var(--ui-primary); font-size: 13px;
}
.demo-infinite-loader.hidden { display: none; }
.demo-infinite-spinner {
  width: 18px; height: 18px;
  border: 2px solid color-mix(in srgb, var(--ui-primary) 25%, transparent);
  border-top-color: var(--ui-primary); border-radius: 50%;
  animation: demoInfSpin 0.7s linear infinite;
}
@keyframes demoInfSpin { to { transform: rotate(360deg); } }
.demo-infinite-status {
  text-align: center; font-size: 12px; color: #999; margin: 8px 0 0;
}
(function() {
  const container = document.querySelector('.demo-infinite');
  const list = document.getElementById('demoInfiniteList');
  const loader = document.getElementById('demoInfiniteLoader');
  const status = document.getElementById('demoInfiniteStatus');
  let count = 5, loading = false, max = 20;
  container.addEventListener('scroll', function() {
    if (loading || count >= max) return;
    if (container.scrollTop + container.clientHeight >= container.scrollHeight - 30) {
      loading = true;
      setTimeout(() => {
        for (let i = 0; i < 5 && count < max; i++) {
          count++;
          const card = document.createElement('div');
          card.className = 'demo-infinite-card';
          card.textContent = '記事タイトル ' + count + ' — ここにコンテンツのプレビューテキストが入ります。';
          list.appendChild(card);
        }
        loading = false;
        if (count >= max) {
          loader.classList.add('hidden');
          status.textContent = 'すべて読み込みました(' + count + '件)';
        }
      }, 800);
    }
  });
})();

AIプロンプト

Basic
無限スクロールをHTML/CSS/JSで作ってください。ページ下部までスクロールすると新しいコンテンツが自動的に読み込まれます。
Custom
以下の仕様で無限スクロールを実装してください。
- Intersection Observer APIを使用
- スケルトンローディング表示
- 読み込み完了時に「すべて表示しました」メッセージ
- プライマリカラー: #2563eb
- 読み込み中のスピナーアニメーション
- 一度に10件ずつ読み込み
Advanced
アクセシビリティ対応の無限スクロールを実装してください。
- aria-liveリージョンで新着コンテンツを通知
- 「もっと読み込む」フォールバックボタン(自動読み込み無効時)
- キーボードフォーカス管理(新規アイテムにフォーカスを移す)
- prefers-reduced-motion対応
- メモリリーク防止(DOM要素のリサイクル/仮想化)
- エラーハンドリングとリトライ機能
- Back/Forward時のスクロール位置復元