WordPress の AMP ページに amp-list の無限スクロールを実装する方法
動作
2019 年 3 月に、amp-list のアップデートがありました。アップデートにより、AMP で動的に表示するリストの無限スクロールが可能になりました。
この amp-list の無限スクロールを WordPress に実装する方法を紹介します。
まずは、amp-list の無限スクロールの動作をご覧ください。最初は 3 件を表示し、ボタンのクリックで 3 件ずつデータを追加しています。
尚、amp-list の無限スクロールには 2 つのタイプがあり、ボタンをクリックせずに自動的にデータを追加するタイプもあります。
特徴と用途
amp-list の無限スクロールは、以下の特徴があります。
- 現在のページに「データ」を追加する
- 「異なるページ」を追加するわけではないため、ページアドレスは変わらない
- データ追加後の状態は、ブラウザの履歴に残らない
この特徴は、異なるページを追加する一般的な無限スクロールとは異なります。一般的な無限スクロールは、このような動作をするのが基本です。
- 現在のページに「異なるページ」を追加する
- 「異なるページ」を追加後、ページアドレスが変わる
- 追加したページのアドレスが、ブラウザの履歴に残る
一般的な無限スクロールはブラウザの履歴に残るため、ブラウザの「戻る」が使えます。一方、amp-list の無限スクロールは、ブラウザの「戻る」が使えません(「戻る」でデータ追加前の状態に戻らない)。
amp-list の無限スクロールの特徴を考慮すると、このようなリストに適しています。
- 「関連記事」や「関連商品」のリスト
- ブログやニュースサイトのコンテンツページで見かける「人気記事」や「最新記事」のリスト
- 検索結果ページなど「絞り込み」や「並び替え」機能が必要なリスト(これらの機能は amp-bind の併用で実装可能)
一方、不適切だと思うのは、ページネーションのある複数のページに分割した記事一覧リスト(記事一覧ページ)。このようなリストに実装すると、ブラウザの戻るが使えないためユーザビリティが悪化する、SEO に悪影響が出る恐れがあります。
尚、AMP の記事一覧ページで無限スクロールを実装するには、amp-next-page を使います。
実装方法
WordPress での amp-list の無限スクロールの実装は、大まかに 3 ステップで終わります。
今回は、投稿ページに「新着記事」を表示する例として説明します。この「新着記事」は、最初は 5 件を表示し、無限スクロールで「現在の投稿ページ」を除く全件を作成日順(新しい記事から表示する降順)で表示するものです。
WP REST API の独自エンドポイントを作成
最初にすることは、WP REST API の独自エンドポイントの作成です。
amp-list は、JSON から動的にデータを取得します。WordPress の JSON と言えば WP REST API です。
しかし、WP REST API には、amp-list の無限スクロールに必要な「JSON の次のページの URL」(1 ページ目をリクエストしている場合は 2 ページ目の URL)が JSON 内に含まれていません。
JSON 内に次のページの URL を含めるために、下記コードを functions.php に追加し独自のエンドポイントを作成します。
add_action( 'rest_api_init', function() { register_rest_route( 'new', '/id(?P<id>\d+)/page(?P<page>\d+)', [ 'callback' => 'get_rest_api_new', 'methods' => WP_REST_Server::READABLE ]); }); function get_rest_api_new( $request ) { $request_id = $request['id']; $request_page = $request['page']; $the_query = new WP_Query([ 'paged' => $request_page, 'post__not_in' => [$request_id], 'posts_per_page' => 5 ]); /** * 次ページの URL */ $max_num_pages = $the_query->max_num_pages; if ( $request_page < $max_num_pages ) { $next_page = esc_url( home_url() ) . '/wp-json/new/id' . $request_id . '/page' . ( $request_page + 1 ); } else { $next_page = null; } /** * 記事データ */ $posts = null; if ( $the_query->have_posts() ) { while ( $the_query->have_posts() ) { $the_query->the_post(); $thumb_id = get_post_thumbnail_id(); $thumb_src = wp_get_attachment_image_src( $thumb_id, 'large' ); $data['permalink'] = get_permalink(); $data['title'] = get_the_title(); $data['cat_name'] = get_the_category()[0]->cat_name; $data['srcset'] = wp_get_attachment_image_srcset( $thumb_id ); $data['src'] = $thumb_src[0]; $data['img_width'] = $thumb_src[1]; $data['img_height'] = $thumb_src[2]; $data['alt'] = get_post_meta( $thumb_id, '_wp_attachment_image_alt', true ); $posts[] = $data; } wp_reset_postdata(); } /** * WP REST API へ出力 */ $json = [ 'load-more-src' => $next_page, 'items' => $posts ]; return rest_ensure_response( $json ); }
参考:Routes and Endpoints | REST API Handbook | WordPress Developer Resources
記事のデータとして、「記事の URL」「記事タイトル」「カテゴリー名」「画像関係」を取得しています。他に必要なデータがあれば、50 行目以降に $data
として追加します。
この独自エンドポイントには、このような URL でリクエストできます。
https://example.com/wp-json/new/id50/page1
id50 は、「新着記事」を表示する「現在の投稿ページ」の id です。この id は、<amp-list>
タグに設定する the_ID()
で取得します。
末尾の page1 は、JSON のページ数です。page1 であれば 1 ページ目、page2 であれば 2 ページ目の JSON をリクエストします。
ブラウザのアドレスバーに打ち込むと、このような JSON が返ってきます。
// https://example.com/wp-json/new/id50/page1 { "load-more-src": "https://example.com/wp-json/new/id50/page2", "items": [ { "permalink": "https://example.com/amp-list/", "title": "amp-listの無限スクロール", "cat_name": "AMP", "srcset": "https://example.com/wp-content/uploads/2019/05/amp-list.png 1920w, 〜(以下、省略)", "src": "https://example.com/wp-content/uploads/2019/05/amp-list-640x360.png", "img_width": 640, "img_height": 360, "alt": "amp-listの無限スクロール" }, 以下、posts_per_page で指定した件数分の記事データが続く ] }
JSON の次のページの URL は、load-more-src
から取得します。また、記事データは、items
に格納しています。
この load-more-src
と items
の名前は、amp-list の仕様に合わせています。異なる名前にできますが、その場合は <amp-list>
タグを作成時に属性の追加が必要です(注意点にて後述します)。
ライブラリの読み込み
次は、amp-list と amp-mustache のライブラリを読み込みます。amp-mustache は、amp-list のテンプレート作成に必要です。
この 2 つのコンポーネントのライブラリを <head>
で読み込みます。
<script async custom-element="amp-list" src="https://cdn.ampproject.org/v0/amp-list-0.1.js"></script> <script async custom-template="amp-mustache" src="https://cdn.ampproject.org/v0/amp-mustache-0.2.js"></script>
amp-list タグの作成
最後に、<amp-list>
タグを作成します。
作成方法や仕様は、公式ページで詳細に解説されています。
基本的な作り方は、<amp-list>
タグの src
属性に JSON の URL を指定。そして、<template type="amp-mustache">
内で、JSON のデータを {{}}
で囲みテンプレートを作成します。
single.php の「最新記事」を表示したい場所に、このような <amp-list>
タグを設置します。
<amp-list layout="fixed-height" height="500" src="<?php echo esc_url( home_url() ); ?>/wp-json/new/id<?php the_ID(); ?>/page1" binding="no" load-more="manual"> <template type="amp-mustache"> <div> <a href="{{permalink}}"> <div> <amp-img src="{{src}}" srcset="{{srcset}}" alt="{{alt}}" width="{{img_width}}" height="{{img_height}}" sizes="(max-width: {{img_width}}px) 100vw, {{img_width}}px"></amp-img> </div> <div> <h2>{{title}}</h2> <p>{{cat_name}}</p> </div> </a> </div> </template> </amp-list>
amp-list の無限スクロールに必須の属性は load-more>
です。値は、auto
か manual
のいずれかです。
属性と値 | 動作 |
---|---|
load-more="auto" | 自動的にデータを追加する無限スクロール。 |
load-more="manual" | ボタンのクリックでデータを追加する無限スクロール。デフォルトでは「SEE MORE」ボタンが表示される。 |
注意点
今回「JSON の次のページの URL」は、JSON の load-more-src
から取得しています。この load-more-src
は、amp-list がデフォルトで要求する名前です。
もし、WP REST API の独自エンドポイントの作成時に load-more-src
を異なる名前にした場合は、<amp-list>
タグに load-more-bookmark
属性が必要です。
例えば、名前を next-page
にした場合は、load-more-bookmark="next-page"
を追加します。これで「next-page
から JSON の次のページの URL を取得しなさい」と指示できます。
<amp-list load-more-bookmark="next-page" layout="fixed-height" height="1000" src="<?php echo esc_url( home_url() ); ?>/wp-json/new/id<?php the_ID(); ?>/page1" binding="no" load-more="auto"></amp-list>
また、記事データは、JSON の items
に格納しました。この items
も amp-list がデフォルトで要求する名前です。
もし、items
を異なる名前にした場合は、<amp-list>
タグに items
属性が必要です。
例えば、名前を post-data
にした場合は、items="post-data"
を追加します。
<amp-list items="post-data" layout="fixed-height" height="1000" src="<?php echo esc_url( home_url() ); ?>/wp-json/new/id<?php the_ID(); ?>/page1" binding="no" load-more="auto"></amp-list>
オプション
amp-list の無限スクロールには、<amp-list-load-more>
タグを使用するオプションが用意されています。
このタグは <amp-list>
タグの子要素として配置し、任意の属性を指定します。
公式サイトの amp-list のドキュメントに詳細な説明があるため、ここでは簡単に解説します。
ボタンを変更
load-more="manual"
を指定した場合は、デフォルトで「SEE MORE」ボタンが表示されます。

このボタンを変更できるのが、load-more-button
属性です。
<amp-list>
の子要素として、load-more-button
属性を持つ <amp-list-load-more>
タグを設置します。
<amp-list layout="fixed-height" height="1000" src="<?php echo esc_url( home_url() ); ?>/wp-json/new/id<?php the_ID(); ?>/page1" load-more="manual"> <template type="amp-mustache">〜省略〜</template> <amp-list-load-more load-more-button> <button>もっと見る</button> </amp-list-load-more> </amp-list>

amp-mustache を使い、JSON データの反映も可能です。
尚、ボタンの背景色などを変更する場合は、amp-list-load-more タグに対してではなく、button タグに対して CSS を指定します。でなければ、ローディングアニメーションなどにも CSS が適用されてしまいます。
ローディングアニメーション
デフォルトでは、無限スクロール発動時に一般的なローディングアニメーションが適用されます(一部が欠けた円がクルクルと回る)。
独自のローディングアニメーションにしたい時は、load-more-loading
属性を使います。
<amp-list>
の子要素として、load-more-loading
属性を持つ <amp-list-load-more>
タグを設置します。
<amp-list 以下、省略> ... <amp-list-load-more load-more-loading> <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"> <path d="M12 6v3l4-4-4-4v3c-4.42 0-8 3.58-8 8 0 1.57.46 3.03 1.24 4.26L6.7 14.8c-.45-.83-.7-1.79-.7-2.8 0-3.31 2.69-6 6-6zm6.76 1.74L17.3 9.2c.44.84.7 1.79.7 2.8 0 3.31-2.69 6-6 6v-3l-4 4 4 4v-3c4.42 0 8-3.58 8-8 0-1.57-.46-3.03-1.24-4.26z" /> <path d="M0 0h24v24H0z" fill="none" /> </svg> </amp-list-load-more> </amp-list>
Material icons の Autorenew の SVG を使っています。
あとは、CSS の @keyframes を使えば、独自のローディングアニメーションの完成です。
尚、「読み込み中」などテキストのみの指定もできます。
読み込み失敗時の再読み込み
JSON の次のページの読み込みに失敗した時に備えられるのが、load-more-failed
属性です。
この属性を持つ <amp-list-load-more>
タグがある場合は、JSON の読み込みの失敗時にボタンを表示できます。このボタンのクリックで、JSON の再読み込みが可能です。
ボタンを表示するだけなら、このように指定します。
<amp-list 以下、省略> ... <amp-list-load-more load-more-failed> <button>再読み込み</button> </amp-list-load-more> </amp-list>
また、注意文も表示するのならボタン要素に load-more-clickable
属性を指定します(注意文はクリック要素にはならず、ボタンのみがクリック要素となる)。
<amp-list 以下、省略> ... <amp-list-load-more load-more-failed> <p>読み込みに失敗しました</p> <button load-more-clickable>再読み込み</button> </amp-list-load-more> </amp-list>
これ以上データがない時の注意文
これ以上読み込む JSON のデータがない時に注意文を表示できるのが、load-more-end
属性です。
「これ以上は記事がありません」などの注意文を表示できます。
<amp-list 以下、省略> ... <amp-list-load-more load-more-end> <p>これ以上は記事がありません</p> </amp-list-load-more> </amp-list>

複数の指定
異なる属性を持つ複数の <amp-list-load-more>
タグを設置できます。
<amp-list 以下、省略> ... <amp-list-load-more load-more-button> <button>もっと見る</button> </amp-list-load-more> <amp-list-load-more load-more-end> <p>これ以上は記事がありません</p> </amp-list-load-more> </amp-list>