WordPress に Google 風の無限スクロールを実装
動作
2018 年 4 月に、Google がモバイル検索結果で無限スクロールを導入しました。
Google がモバイル検索結果で導入した無限スクロールは、「もっと見る」ボタンのタップで、ページを移動せず検索結果の続きが表示されます。
この Google 検索に似た無限スクロールを WordPress に実装する方法をご紹介します。
まずは、実際の動作をご覧ください。Google 検索と同じように、「もっと見る」ボタンのクリック・タップで次のページが読み込まれます。
Infinite Scroll を使用
無限スクロールを導入する際は、下記の 2 つを考慮しないといけません。
- クローラーに配慮する
- ユーザーの使い勝手に配慮する
クローラーは無限スクロールが苦手です。そのため、検索エンジンとの相性を考慮した無限スクロールのベストプラクティスに沿う必要があります。
また、自動的に無限スクロールが始まると、サイトの使い勝手が悪くなる恐れがあります。「フッターを見たいのに、見られない!」と私は何度も思ったことがあります。
この 2 つとも考慮できるのが、JavaScript ライブラリの Infinite Scroll です。設置方法が簡単な魅力もあるため、今回は Infinite Scroll を使用します。
尚、今回は紹介しませんが、Infinite Scroll であれば「もっと見る」ボタンをクリック・タップしない自動的な無限スクロールにも対応できます。
Infinite Scroll の読み込み
最初にすることは、Infinite Scroll の設置と読み込みです。
使用中のテーマフォルダの直下に、infinite-scroll.js ファイルを作成します。
作成した infinite-scroll.js ファイルに、infinite-scroll.pkgd.min.js をそのまま全てコピペをします。
あとは作成した infinite-scroll.js をサイトで読み込みます。下記のコードを使い、</body>
タグ直前で読み込みます(<head>
タグ内でも可)。
<script src="<?php echo get_stylesheet_directory_uri(); ?>/infinite-scroll.js"></script>
上記のコードは、子テーマの使用を想定しています。
「もっと見る」ボタンを作成
次にすることは、無限スクロールを開始する「もっと見る」ボタンの作成です。
テーマフォルダの直下に、infinite-scroll.php ファイルを作成します。作成した infinite-scroll.php ファイルに、下記のコードを追加します。
<?php // 現在のページ数 global $paged; if ( empty( $paged ) ) $paged = 1; // 総ページ数 global $wp_query; $pages = $wp_query -> max_num_pages; if ( ! $pages ) { $pages = 1; } // ページが1ページしかない場合は出力しない・最後のページでも出力しない if ( $pages != 1 && $paged < $pages ) { echo ' <button id="more-button" type="button">もっと見る</button> <div class="scroller-status"> <div class="infinite-scroll-request"></div> <p class="infinite-scroll-last">これ以上は記事がありません</p> <p class="infinite-scroll-error">読み込むページがありません</p> </div> '; }
ページが 1 ページしかない場合は、ボタンは表示しないようにしています。また、最後のページでもボタンは表示されません。読み込むページがない時は、ボタンは不要です。
scroller-status
の class が付いている <div>
は、Infinite Scroll のオプションの status を使うためのものです。status の使用により、最後の記事の下に「これ以上は記事がありません」と表示されます。

読み込むページがない場合は、「読み込むページがありません」と表示されます。

テンプレートにボタンを設置
作成した infinite-scroll.php ファイルを、記事一覧を呼び出しているテンプレートのお好きな場所に設置します。
設置するためのコードは、下記のとおりです。
<?php get_template_part( 'infinite-scroll' ); ?>
テーマによって、記事一覧を呼び出しているテンプレートは違います。Simplicity であれば list.php 。Cocoon であれば tmp/list.php です。
最適なボタンの設置場所はサイトによって異なりますが、おすすめはページネーションの上です。
JavaScript で設定
次は Infinite Scroll の設定です。下記の JavaScript を追加します。コードを追加するファイルは、テーマが用意している JavaScript 用のファイル、または最初に作成した infinite-scroll.js ファイルのどちらでも構いません。
var infScroll = new InfiniteScroll('#list', { append: '.entry', path: '.next a', hideNav: '.pagination', button: '#more-button', scrollThreshold: false, status: '.scroller-status', history: 'push', });
1 行ずつ解説します。
まず 1 行目の #list
は、記事一覧を囲む要素を指定します。例えば、記事一覧の HTML が下記のものだとします。
<div id="list"> <article class="entry"></article> <article class="entry"></article> <article class="entry"></article> ... </div>
各記事の <article>
を <div id="list"></div>
が囲んでいます。この囲んでいる要素の id または class を指定します。
append: '.entry'
の .entry
は、各記事(上記の HTML では <article>
)の class を指定します。この append に指定した要素が、無限スクロールで読み込まれたページに追加されていきます。
path: '.next a'
の .next a
は、次のページへの URL を指定します。URL は、ページネーションから拾います。例えば、ページネーションの HTML が下記のものだとします。
<ul class="pagination"> <li><a href="最初のページのURL"></a></li> <li><a href="現在のページの前のURL"></a></li> <li>現在のページ数</li> <li><a href="現在のページの次のURL"></a></li> <li><a href="現在のページの次の次のURL"></a></li> ... <!-- この a タグを指定します --> <li class="next"><a href="次のページのURL"></a></li> <li><a href="最後のページのURL"></a></li> </ul>
.next a
が、次のページの URL です。たいてい「次へ」とか「 > 」で表示されています。この <a>
タグの id または class を指定します。
それ以外の部分は、変更する必要はありません。
Infinite Scroll の詳細な設定は、Options にて公式の説明をご覧いただけます。
Safari のバグへの対策
iOS(Safari)でバグがあることを教えていただきました。
各記事に画像があり、その画像に srcset 属性があると、無限スクロールで読み込まれたページで画像が表示されないというものです。
GitHub の Safari not displaying loaded srcset images にて、開発者さんが問題の原因と解決方法をお書きになっています。
Infinite Scroll の設定の JavaScript の後に JavaScript を追加すれば、この問題を解決できます。
jQuery で書く場合は、以下のコードを追加します。2 行目の #list
には、記事一覧を囲む要素を指定します。
jQuery(function ($) { $('#list').on( 'append.infiniteScroll', function (event, response, path, items) { $(items) .find('img[srcset]') .each(function (i, img) { img.outerHTML = img.outerHTML; }); }, ); });
Vanilla JS(素の JavaScript)で書く場合は、以下のコードを追加します。1 行目の .entry
には、各記事の class を指定します。ただし、こちらのコードは実際に検証していません。
var infiniteItem = document.querySelectorAll('.entry'); infScroll.on('append', function (response, path, items) { for (var i = 0; i < items.length; i++) { reloadSrcsetImgs(infiniteItem[i]); } }); function reloadSrcsetImgs(infiniteItem) { var imgs = infiniteItem.querySelectorAll('img[srcset]'); for (var i = 0; i < imgs.length; i++) { var img = imgs[i]; img.outerHTML = img.outerHTML; } }
CSS で装飾
あとは「もっと見る」ボタンなどの CSS を指定すれば終わりです。
CSS の一例は下記のとおり。サイトによって、CSS はだいぶ違うはずです。
#more-button { background: #eee; height: 56px; margin: 40px 0 0; width: 100%; } .scroller-status { display: none; margin-top: 40px; } /* ローディングアイコン */ .infinite-scroll-request { animation: scroll-request 1.1s infinite linear; border: 4px solid #00b8d4; border-left: 4px solid #fff; border-radius: 50%; height: 48px; margin: auto; width: 48px; } @keyframes scroll-request { 0% { transform: rotate(0deg); } 100% { transform: rotate(360deg); } } .infinite-scroll-last, .infinite-scroll-error { color: #757575; text-align: center; }
ローディングアイコンを指定している部分があります。ローディングアイコンは、「もっと見る」ボタンをクリック・タップした後に表示されます。

ローディングアイコンの CSS は、Single Element CSS Spinners をご参考にするといいかもしれません。