メインコンテンツまで移動する

WordPress に Google 風の無限スクロールを実装

  • 公開日
  • 更新日

Akira Web デザイナー

動作

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 をご参考にするといいかもしれません。

フォローする