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

Akira

福岡在住の Web デザイナー。Web サイト制作に役立つ情報を紹介しています。AMP が大好き。

FacebookTwitter で記事の更新をお知らせしています。

2018 年 4 月に、Google がモバイル検索結果で無限スクロールを導入しました。

この Google 検索に似た無限スクロールを WordPress に実装する方法をご紹介します。

動作

Google がモバイル検索結果で導入した無限スクロールは、「もっと見る」ボタンのタップで、ページを移動せず検索結果の続きが表示されます。

今回ご紹介する無限スクロールは、同じように「もっと見る」ボタンのクリック・タップで、次のページが読み込まれます。

Infinite Scroll を使用

無限スクロールを導入する際は、下記の 2 つを考慮しないといけません。

  • クローラーに配慮する
  • ユーザーの使い勝手に配慮する

クローラーは無限スクロールが苦手です。そのため、「検索エンジンとの相性を考慮した無限スクロールのベストプラクティス」に沿う必要があります。

また、自動的に無限スクロールが始まると、サイトの使い勝手が悪くなる恐れがあります。「フッターを見たいのに、見られない!」と私は何度も思ったことがあります。

この 2 つともしっかりと考慮できるのが、JavaScript ライブラリの 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 ページしかない場合は、ボタンは表示しないようにしています。また、最後のページでもボタンは表示されません。読み込むページがない時は、ボタンはいりません。

18 行目から 22 行目は、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 を指定します。

2 行目の .entry は、各記事(上記の HTML では <article> )の id または class を指定します。この append に指定した要素が、無限スクロールで読み込まれたページに追加されていきます。

3 行目の .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>
  ...
  <li class="next"><a href="次のページのURL"></a></li> ← この a タグを指定します
  <li><a href="最後のページのURL"></a></li>
</ul>

.next a(8 行目)が、次のページの URL です。たいてい「次へ」とか「 > 」で表示されています。この <a> タグの id または class を指定します。

それ以外の部分は、変更する必要はありません。

Infinite Scroll の詳細な設定は、Options にて公式の説明をご覧いただけます。

Safari のバグへの対策

コメントにて、iOS(Safari)でバグがあることを教えていただきました。

各記事に画像があり、その画像に srcset 属性があると、無限スクロールで読み込まれたページで画像が表示されないというものです。

上記の 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;
  }
}

バグをご報告いただいたコメントは、下記のリンクよりご覧いただけます。

https://firstlayout.net/install-infinite-scroll-in-wordpress/#comment-126

また、Infinite Scroll の GitHub にて、開発者さんが問題の原因と解決方法をお書きになっています。

Safari not displaying loaded srcset images

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;
}

13 行目から 31 行目は、ローディングアイコンの指定です。ローディングアイコンは、「もっと見る」ボタンをクリック・タップした後に表示されます。

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

各ローディングアイコンの下にある < View Source > をクリックすると、CSS が出てきます。CSS のセレクタの .loader.infinite-scroll-request に変更するだけで真似ができます。

おわりに

Infinite Scroll は、数年前からサイトに無限スクロールを導入するための代表的な JavaScript ライブラリでした。

ただ、数年前より大幅に進化しています。素晴らしい。

今回は紹介していませんが、「もっと見る」ボタンをクリック・タップしない自動的な無限スクロールにも対応できます。

コメント

  1. Akira様
    初めまして、おおさかと申します。

    このInfinite Scrollをサイトに組み込みたいのですがどうしても上手くいきません。
    初心者なのでご教授頂ければ幸いです。

    上記を記述しますと構文エラーが出ます。

    子テーマを作っていない為、下記は絶対パスで記述しました。
    <script src="/infinite-scroll.js”>
    どうぞよろしくお願いいたします。

    • 申し訳ありません。

      「設置するためのコード」を書いたのですが消えていました。

    • どのようなカスタマイズをされて、どのようなエラーが出ているのか分からないので、何とも言えません。

      サイトを拝見できれば、解決方法が分かるかもしれません。

      または、実際に書かれたコードとエラー内容の 2 つのご提示があると、サイトを拝見せずとも問題箇所を発見できるかもしれません。

      このコメント欄にコードをお書きになる際には、下記のようなツールでエンコードが必要です。

      HTML 特殊文字変換ツール

  2. Akira様
    お忙しいところ恐縮です。

    変換ツール使いました。

    <?php get_template_part( 'infinite-scroll' ); ?>
    ↑これですとテーマに直接コードが出てしまいました。

    エラーメッセージは以下です。
    ParseError thrown
    syntax error, unexpected ‘var’ (T_VAR), expecting end of file

    海外のテーマ(wp-simple)その中にpartsというフォルダの中のblog-pagination.phpです。
    URLは https://www.hidekisaijo.com/ です。

    • <?php get_template_part( 'infinite-scroll' ); ?>
      ↑これですとテーマに直接コードが出てしまいました。

      普通はコードは出てきません。

      そのコードで、infinite-scroll.php ファイルを呼び出しています。「もっと見る」ボタンを作成で作るファイルです。

      その infinite-scroll.php ファイルに、JavaScript をお書きになってはいないでしょうか。例えば、JavaScript で設定のコードなどです。

      ParseError thrown
      syntax error, unexpected ‘var’ (T_VAR), expecting end of file

      このエラーは、PHP では使わない var があると指摘しています。var は、JavaScript で使います。

      この点からも、infinite-scroll.php ファイルに JavaScript がないかのご確認が必要に思えます。

      それと、<head></head> 内で infinite-scroll.js を読み込んでいる <script> タグに、全角のダブルクォーテーションがあります。

      半角の ” に修正が必要です。

      <script src="https://www.hidekisaijo.com/js/infinite-scroll.js">
  3. Akira様
    検証して下さり有難う御座います。

    JavaScriptはfooter.phpに記述しました。

    <?php wp_footer(); ?>
    <script>
    var infScroll = new InfiniteScroll( '#list', {
    append: '.entry',
    path: '.next a',
    hideNav: '.pagination',
    button: '#more-button',
    scrollThreshold: false,
    status: '.scroller-status',
    history: 'push',
    });
    </script>
    </body>
    </html>

    <script src="https://www.hidekisaijo.com/js/infinite-scroll.js"&gt;
    ↑内にしましたがやはり動きません。
    でもエラーは出ていません。
    あともう少しだと思うのですが・・・
    お食事の時間に申し訳ありません。

    • </script> を書いていませんでしたので、<head></head> 内の infinite-scroll.js 読み込み部分は、下記のものにご変更ください。

      <script src="https://www.hidekisaijo.com/js/infinite-scroll.js"></script>

      それと、ページネーションがありません。お使いのテーマの parts / blog-pagination.php にあったコードを消されてはいないでしょうか。ページネーションがなければ、次のページの URL を取得できません。

      お使いのテーマが WP Simple であれば、parts / blog-pagination.php はこのようになっていたはずです。

      <div class="row blog_pagination">
          <div class="col-sm-6 next_posts_link">
          <?php next_posts_link(__('... Older Posts', 'wp-simple' )) ?>
          </div>
          <div class="col-sm-6 previous_posts_link text-right">
          <?php previous_posts_link(__('Newer Posts ...', 'wp-simple' )) ?>
          </div>
      </div>

      実際に試していませんが、parts / blog-pagination.php を下記のように変更するといいと思います。

      <div class="row blog_pagination">
          <div class="col-sm-6 next_posts_link">
          <?php next_posts_link(__('... Older Posts', 'wp-simple' )) ?>
          </div>
          <div class="col-sm-6 previous_posts_link text-right">
          <?php previous_posts_link(__('Newer Posts ...', 'wp-simple' )) ?>
          </div>
      </div>
      
      <?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>
          ';
      }
      ?>

      ちなみに、<?php get_template_part( 'infinite-scroll' ); ?> は、不要です。

      そして、footer.php に追加された JavaScript は、サイトに合わせて下記のように変更します。

      var infScroll = new InfiniteScroll( '.blog_content_col', {
        append: '.frontpage-post',
        path: '.next_posts_link a',
        hideNav: '.blog_pagination',
        button: '#more-button',
        scrollThreshold: false,
        status: '.scroller-status',
        history: 'push',
      });
  4. Akira様
    大変お手数をおかけしました。
    わざわざ海外テーマの検証もして下さり感謝しております。

    只今バタバタしておりますので夜中にじっくり見ています。
    この度は本当に有難う御座いました。

    • Akira様
      おはよう御座います。
      海外のテーマまで調べて頂き恐縮しきりです。

      日本語表記ですと文字化けしますので英語にしましたが
      ちゃんと出来ました!感激です!
      本当にありがとう御座いました。

    • 上手くいったようで良かったです。

  5. はじめまして。
    無限スクロール jQuery の検索でこちらの記事にたどり着きました。
    非常にわかりやすい解説をありがとうございます。

    PHP初心者のわたしでもなんとか設置することができました。
    ありがとうございました。

    ひとつだけご教授いただけると非常に助かるのですが、
    現在
    $paged,
    ‘post_type’ => ‘hoge’,
    ‘posts_per_page’ => $num,
    );

    のような形で、
    スマホの場合はページネーション出現、PC閲覧の場合はページネーションなしで表示させていました。
    Infinite Scroll の読み込みも同じようにスマホでは出現、PCでは出現させないというようにしたいのですが、知識がありません。
    現在は、PCにもスマホにも「もっとみるボタン」は出現しています。PCは全件表示されている状態で「もっとみるボタン」が出ております。
    お時間のある時でよいのでお知恵をお貸しください。
    他に必要な情報がありましたら公開します。

  6. ◆◆◆◆一覧ページ◆◆◆◆

    $paged,
    ‘post_type’ => ‘krc_cast’,
    ‘posts_per_page’ => $num,
    );
    $my_query = new WP_Query($args);
    if ($my_query->have_posts()) :
    while ($my_query->have_posts()) : $my_query->the_post();
    ?>

    この中を繰り返し

    $my_query));?>

    ◆◆◆◆ タグ直前に記述◆◆◆◆
    <script src="/js/infinite-scroll/infinite-scroll.js”>

      var infScroll = new InfiniteScroll( ‘.cssgrid’, {
    append: ‘.item’,
    path: ‘.nextpostslink’,
    hideNav: ‘.wp-pagenavi’,
    button: ‘#more-button’,
    scrollThreshold: false,
    status: ‘.scroller-status’,
    history: ‘push’,
    });

    ◆◆◆◆infinite-scroll.phpに記述◆◆◆◆
    max_num_pages;
    if( !$pages ) {
    $pages = 1;
    }

    // ページが1ページしかない場合は出力しない・最後のページでも出力しない
    if( $pages != 1 && $paged < $pages ) {
    echo '
    もっと見る

    これ以上は記事がありません
    読み込むページがありません

    ‘;
    }

    説明不足で申し訳ございませんでした。
    早速のお返事ご親切にありがとうございます。
    説明補足します。

    is_mobile()を使い、スマホでは4件、PCでは全件表示になっています。
    ページネーションはwp_pagenaviをプラグインしています。
    この状態で現在PCでみると「もっと見る」のボタンで出ています。
    これを非表示にしたいと思います。

    この場合の条件の書き方がどうもわかりません。

  7. 連投すみません。
    投稿文を確認しましたが、記述した一部が欠落しています。
    これでは伝わりませんよね。
    どうしたらコメント欄でソースを見て頂くことができるでしょうか。

    • WordPress のコメント欄に HTML などをお書きになる際には、エンコードしないと削除されてしまいます。エンコードは、下記のツールで行えます。

      HTML特殊文字変換ツール

      解決方法ですが、is_mobile() をお使いになり PC では「もっと見る」ボタンを出力させないのが手っ取り早いように思えます。

      テンプレートにボタンを設置のコードを変更します。

      <?php if ( is_mobile() ) get_template_part( 'infinite-scroll' ); ?>
  8. お世話になっております。
    ご教授頂きました

    <?php if ( is_mobile() ) get_template_part( 'infinite-scroll' ); ?>

    上記を差し替えることでPCでは「もっと見る」が表示されなくなりました。
    ありがとうございました。とても助かりました。

    PCでは表示されなくなりましたが

    スマホ表示の際、
    例>全件数が4件 とした場合において「もっと見る」が出現します。PCは出現しません。
    例>全件数が6件 とした場合においては「もっと見るボタン」は出現し、タップすると次のページが出現し正常な動作が確認できました。

    全件数が4件で、もっとみるボタンは出現させたくないのですが
    どうしたらよいでしょうか。

    エンコードの件、既出でした。お手数をお掛けしました。
    このような質問をするのに慣れていなくてすみません。

    下記にコードを記します。

    ◆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>
    ';
    }

    ◆一覧ページ◆

    <div class="cssgrid">
    <?php
    if( is_mobile() ){
    $num = 4;
    } else {
    $num = -1;
    }
    $args = array(
    'paged' => $paged,
    'post_type' => 'hoge',
    'posts_per_page' => $num,
    );
    $my_query = new WP_Query($args);
    if ($my_query->have_posts()) :
    while ($my_query->have_posts()) : $my_query->the_post();
    ?>

    <div class="item">ここに繰り返す内容</div>

    <?php endwhile; ?>
    </div>

    <?php wp_reset_query();endif; ?>

    <?php if(function_exists('wp_pagenavi')) wp_pagenavi(array('query' => $my_query));?>
    <?php if ( is_mobile() ) get_template_part( 'infinite-scroll' ); ?>

    お忙しいと存じますが、ご教授頂けるととても助かります。
    宜しくお願い致します。

    • やはり、WP_Queryでページネーションがうまくいかなくて対応したことと同じ方法で上手くいくはずです。

      $my_query でループ処理をされているので、$my_query で総ページ数を取得しないといけません。

      まず、下記のコードを削除します。

      <?php if ( is_mobile() ) get_template_part( 'infinite-scroll' ); ?>

      次に、上記のコードがあった場所に、下記のコードを追加します。

      <?php
      global $paged;
      if ( empty( $paged ) ) $paged = 1;
      
      $pages = $my_query->max_num_pages;
      if ( !$pages ) $pages = 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>
        ';
      }
      ?>

      次に、infinite-scroll.php ファイルが不要になったため削除します。

      さらに、すでに追加されている JavaScript で設定の JavaScript を削除します。

      最後に、is_mobile() で条件分岐をし、JavaScript で設定の JavaScript を追加します。</body> 閉じタグ直前あたりに、インラインでの追加を想定しています。

      <?php if ( is_mobile() ) : ?>
      <script>
      var infScroll = new InfiniteScroll('.cssgrid', {
        append: '.item',
        path: '.nextpostslink',
        hideNav: '.wp-pagenavi',
        button: '#more-button',
        scrollThreshold: false,
        status: '.scroller-status',
        history: 'push',
      });
      </script>
      <?php endif; ?>
  9. お世話になっております。
    まだ修正確認できておりませんが、お忙しい中御教授を頂き心から感謝しております。明日にはご報告できるかと思います。こうして、親切に教えて頂ける方々がいて、積み重ねていけることに心から感謝しています。本当にありがとう御座います。また報告します。

  10. お世話になっております。
    上記の通りにしましたところ目的を果たせました。
    忘れないうちに検証しておきたいと思います。
    本当にありがとうございました。
    グーグルが無限スクロールを採用したことで、同じように困っている方がいるかもしれません。
    このやり取りの記録が誰かの一助になれば幸いです。
    本件でまた不明なことがありましたら質問させてくださいm(__)m

    • 上手くいったようで安心しました。

      どのようなご質問でもお待ちしております。

  11. こんばんは。
    再度の質問になります。
    このスクロールスクリプトですが、ブラウザバックが効かないのは仕方ないのでしょうか。
    そして、
    最終ページが表示された状態で再読込すると元々のページャーが出現します。

    気にしなければ良いと言えばそれまでなのですが、チョット気になったので質問させていただきました。

    • > ブラウザバックが効かない

      効かないでしょうか。私の環境では効いています。

      JavaScript で設定history: 'push' で、history.pushState() による履歴を作成しているはずなんですが。

      詳しくは、Infinite Scroll のオプション History options をご覧ください。

      > 元々のページャーが出現

      これは、おそらく Infinite Scroll の仕様です。

      お好みに合わせて CSS での調整が必要です。

      このブログでは、前のページに戻るリンクのみを表示するようにしています。

      サイトによって最適解は異なるので、記事内では言及していません。

  12. お世話になっております。
    リファレンス確認しました。
    確かに設定では指定されていますが想定した挙動には至りません。
    WP-PageNavi のプラグインを使い、カスタム投稿タイプのページにページャーがでるようにし、そのページャーがInfinite Scrollに置き換わるという流れだと思いますが、このWP-PageNavi のプラグインが理由のような気がしますがどう思われますか。
    一度、プラグインなしでページャーを仕込んで、Infinite Scrollを適用させてみるというのはどうでしょう。
    見当違いでしたらご指摘下さると嬉しいです。

    • 私のテスト環境に、鈴木さんがお書きになった $my_query のループ処理、そしてプラグインの WP-PageNavi を使い一覧ページを作りました。

      コードを見返すと <?php wp_reset_query();endif; ?> の位置がおかしいのと、wp_reset_postdata() の使用が望ましいので、ちょっとコードを変更。

      これを…。

      <?php wp_reset_query(); endif; ?>

      こうして…。

      <?php wp_reset_postdata(); endif; ?>

      「もっと見る」ボタンのコードの下に移動させました。

      参考関数リファレンス / WP Query – ふつうのループ(別の書き方)

      結果は、ブラウザバックが効いたり効かなかったりで、上手くいきませんでした。

      試しに、WP_Queryでページネーションがうまくいかなくて対応したことと同じようなページネーションを試してみると、上手くブラウザバックが効くようになりました。

      なので、$my_query を使いページネーションを自作されると上手くいくかもしれません。

      ページネーションの作り方は、上記の Qiita のページか paginate links – カスタムクエリを使用した例をご参考ください。

  13. おはようございます。
    検証までしてしていただけるとは本当に感謝です。
    頂戴した情報を元にトライしてみようと思います。
    また報告いたしますm(__)m
    ご丁寧な対応に心から感謝申し上げます。
    ありがとうございます。

  14. ◆HTML◆

    <div class="cssgrid">

    <?php
    if( is_mobile() ){
    $num = 4;
    } else {
    $num = -1;
    }
    $args = array(
    'paged' => $paged,
    'post_type' => 'krc_cast',
    'posts_per_page' => $num,
    );
    $my_query = new WP_Query($args);
    if ($my_query->have_posts()) :
    while ($my_query->have_posts()) : $my_query->the_post();
    ?>

    <div class="item">繰り返す内容</div>

    <?php endwhile; ?>

    </div>

    ◆◆ページ送り部分◆◆

    <?php
    global $wp_rewrite;
    $pages = $my_query->max_num_pages;
    if ( !$pages ) $pages = 1;
    if ( $pages != 1 && $paged < $pages ) {
    $paginate_base = get_pagenum_link(1);
    if(strpos($paginate_base, '?') || ! $wp_rewrite->using_permalinks()){
    $paginate_format = '';
    $paginate_base = add_query_arg('paged','%#%');
    }
    else{
    $paginate_format = (substr($paginate_base,-1,1) == '/' ? '' : '/') .
    user_trailingslashit('page/%#%/','paged');;
    $paginate_base .= '%_%';
    }
    echo paginate_links(array(
    'base' => $paginate_base,
    'format' => $paginate_format,
    'total' => $wp_query->max_num_pages,
    'type' => 'list', //ul liで出力
    'mid_size' => 1, //カレントページの前後
    'end_size' => 0,
    'current' => ($paged ? $paged : 1),
    'prev_text' => '<',
    'next_text' => '>',
    ));
    }
    ?>

    <?php
    global $paged;
    if ( empty( $paged ) ) $paged = 1;

    $pages = $my_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>
    ';
    }
    ?>

    <?php wp_reset_postdata(); endif; ?>

    ◆◆</body>タグ直前◆◆

    <script src="<?php echo get_stylesheet_directory_uri(); ?>/js/infinite-scroll/infinite-scroll.js"></script>
    <?php if ( is_mobile() ) : ?>
    <script>
    var infScroll = new InfiniteScroll('.cssgrid', {
    append: '.item',
    path: '.page-numbers a',
    hideNav: '.page-numbers',
    button: '#more-button',
    scrollThreshold: false,
    status: '.scroller-status',
    history: 'push',
    });
    </script>
    <?php endif; ?>

    お世話になっております。

    WP-PageNaviプラグインを止め、カスタム投稿タイプにページャーを設置し、
    条件分岐で

    PC    全件表示/ページャー非表示
    モバイル 4件づつの表示/無限スクロール表示

    WordPressの表示設定画面で、「1ページに表示する最大投稿数」をソースで書いた表示件数4と同数に設定しました。

    なんとかできました。

    コードはこんな感じになってしまい、無駄なコードやもっと簡潔な命令の仕方があるのかもしれません。どう思われますか?

    問題のブラウザバックですが、Akira様のブログと同じ動作になったような気がします。
    つまり

    PCでの閲覧
    マウスホイールでスクロールし、もっと見る押下で次のコンテンツ群出現、マウスホイールでスクロールし始めるとURLがhttps://firstlayout.net/page/2/に。さらにマウススクロールしてもっとみるボタン押下で最後のページが出現しhttps://firstlayout.net/page/3/を表示。で、これ以上記事がありません。になります。マウスホイールを上に上げていくとURLも変わっていきます。

    これはマウスホイールでの動作の場合。

    これをブラウザバック、つまり「戻る」ボタンをhttps://firstlayout.net/page/3/の状態でクリックするとhttps://firstlayout.net/page/2/のコンテンツ部分までジャンプするものの、再度戻るボタンを押しても画面偏移なし。さらに戻るボタンを押すとURLはhttps://firstlayout.net/を表示するものの、画面表示はhttps://firstlayout.net/page/2/のまま。
    さらに戻るボタンをクリックすると全件表示になりURLはhttps://firstlayout.net/になります。

    この動作と同じ状況となります。

    スマホで閲覧した場も同じ挙動になります。
    うまく説明できなくてすみません。

    もう一つ困っていた
    >元々のページャーが出現
    は出現しなくなりました。

    ブラウザバックがうまく動作しない現象ですが、何か方法はないでしょうか。
    それとも、これが正しい仕様でしょうか?

    ページ離脱を誘発しそうな気がしますが、googleモバイル検索も無限スクロールを採用したことで可能ならユーザビリティのことも考えるとなんとか導入したいと希望しています。

    • 独自のループまではサポートできないので簡単にしか見ていませんが…。

      ; が 1 つ多いです。

      user_trailingslashit('page/%#%/','paged');;

      2 つあるので、2 つ目は不要です。

      $pages = $my_query->max_num_pages;

      ブラウザバックですが、このブログでの動作は Infinite Scroll の仕様です。

      ブラウザバックはきちんと動作しているのですが、履歴の作成にラグがあります(次のページに移動後すぐに履歴が作成されない)。

      履歴が作成されたポイントが戻るポイントになるので、ラグが生じるときれいにページの先頭に戻りません。

      おそらく、この動作がブラウザバックが効いていないと思われている理由だと思います。

      ただ、開発者の方が、GitHub できれいにページの先頭に戻る JavaScript を提示されています。

      Browser back button not working correctly when used with history push

      この JavaScript を </body>タグ直前に追加されている <script> タグの中にでもお書きになるといいかもしれません。

  15. 他業務でバタバタしておりました。

    <script>
    var infScroll = new InfiniteScroll('.cssgrid', {
    append: '.item',
    path: '.page-numbers a',
    hideNav: '.page-numbers',
    button: '#more-button',
    scrollThreshold: false,
    status: '.scroller-status',
    history: 'push',
    });
    $('.cssgrid').infiniteScroll({//https://github.com/metafizzy/infinite-scroll/issues/834
    path: getPenPath,
    append: '.item',
    status: '.page-load-status',
    history: 'push',
    historyTitle: true,
    debug: true,
    });
    </script>

    をタグ直前に追加されている タグの中に収めましたが、状況変わらずのような気がします。iPhoneのサファリでの検証です。

    何回か戻るボタンを押下することで商品一覧ページに偏移する前のトップページなどには戻ります。

    >履歴が作成されたポイントが戻るポイントになるので、
    >ラグが生じるときれいにページの先頭に戻りません。

    いろいろと御指南を頂戴し心から感謝しております。

  16. こちらの記事を参考に、無限スクロールを導入してみたのですが、iphone7実機で確認したところ、『もっとみる』で読みこんだ部分の画像だけがなぜか表示されません。(PCだと表示されます)
    このサイトのトップページも同じように画像だけ表示されません。
    ~の部分です。
    私のiphoneの問題でしょうか。。。
    ご教授いただきたいです。

    • 特殊記号を変換し忘れました。失礼いたしました。
      『~の部分です。』
      『<div class="list-thumb">~</div>の部分です。』

    • 教えていただき、ありがとうございます。

      もしかすると、GitHub にある下記の問題報告と同じかもしれません。

      Safari not displaying loaded srcset images

      試しにこのサイトで、開発者さんが提示している append event を追加してみました。

      https://github.com/metafizzy/infinite-scroll/issues/770#issuecomment-374600629

      選んだのは、とりあえず 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;
          });
        });
      });

      JavaScript で設定のコードの後に追加しました。

      私が iPhone を持っていないため、手元で確認できません。大変お手数をおかけしますが、もしよろしければこのサイトのトップページで画像が表示されるかご確認いただけると幸いです。(ブラウザのキャッシュの消去、またはシークレットモードでのご確認が必要かもしれません。)

      もし、画像が表示される場合には、同じようにコードを追加されると問題が解消すると思います。

      —– 追記 —–

      vanilla JS の場合には、こんなコードでいいはずです。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;
        }
      }
  17. 教えていただいた方法で無事画像が表示されました!
    (このサイトのトップぺ―ジもちゃんと表示されていました。)
    有難うございます。

    • お手数をおかけしました。また、教えていただき大変助かりました。

      コメントをいただかなければ、バグに気が付かないままでした。誠にありがとうございました。

      本文にもバグの旨を追記いたしました。

送信に失敗しました

ボットと判定された可能性があります。

大変お手数をおかけしますが、以下の内容をご確認の上、再度のコメントの送信をお願い申し上げます。