[INFINITESCROLL01]無限スクロールを実装する
ここからは、無限スクロールの実装方法について解説する。サンプルは、PCでもスマホでも対応できるようリキッドデザインにし、ページ下までいくと次のコンテンツを読み込むというものだ。なお、誌面の都合でポイントとなる部分のみを解説しているため、詳しくはサンプルファイルを見てほしい。
Ajaxで次のコンテンツを取得する

サンプルでは、3つのHTMLを用意した(01)。一つ目のコンテンツ1(index.html)があり、ページ下までスクロールしたら、Ajaxで次ページのコンテンツ2(index2.html)を読み込む(03)。
読み込みが始まったら、あらかじめページの一番下に設置しておいたローディング画像を表示して(A)、読み込み状態であることをユーザーにわかりやすくしておく。
<div class="scroll-content js-scroll-content"> <div class="js-item-list-wrap"> <div class="item-list js-item-list" // ↓--------------------------------------------------↓ B data-page="1" data-url="index.html" data-prev-url="" data-next-url="index2.html"> // ↑--------------------------------------------------↑ B <div class="item" data-page-url="index3.html"> <h2><a href="#">1</a></h2> </div> <!-- 中略 --> </div> <div class="loading" style="display: none;"><img src="img/loading.gif" alt=""></div> // A </div>
$.ajax({ type: 'GET', url: next_data_url, dataType: 'html', success: function (data) { $loading.show(); // A var $itemList = $(data).find('.js-item-list'); next_data_cache = $itemList; }, complete: function() { $loading.hide(); }, error: function () { $loading.hide(); alert('通信に失敗しました'); } });
次のコンテンツを事前に読み込む
無限スクロールを実装する際、特に注意すべきなのは、表示スピードだ。せっかく無限スクロールにしても、表示が遅ければ、ユーザーにストレスを与えかねない。逆に言えば、そこを改善すれば、さらにユーザーの離脱率を下げることができる。
そこで今回は、一つ目のコンテンツ1を取得してブラウザに反映させたら、Ajaxですぐに次のコンテンツ2を読み込むようにする。コンテンツ1ではdata属性を使って、次に読み込むコンテンツ2の情報を持たせておく(B)。そして、コンテンツ1がブラウザに反映されたら、data属性の情報を取得し、次に読み込むコンテンツ2のURL情報を使ってAjaxを実行する。このとき、まだコンテンツ2はブラウザには反映させず、読み込んだだけの状態にしておく。そして、ページの一番下までスクロールしたら、コンテンツ2をブラウザに表示させるという仕組みだ(04)。
function showNext(data) { $('.js-item-list-wrap').append(data); next_data_url = data.data('next-url'); next_data_cache = false; $.ajax({ type: 'GET', url: next_data_url, dataType: 'html', success: function (data) { var $itemList = $(data).find('.js-item-list'); next_data_cache = $itemList; }, error: function () { alert('通信に失敗しました'); } }); };
コンテンツ2でも同様の処理を行い、コンテンツ3以降もスムーズに表示できるようにする。このようにコンテンツの取得と表示の処理を分けることで、事前ロードが可能になる。
[INFINITESCROLL02]SEOを考慮した無限スクロールにする
無限スクロールを使えばリンクを省略でき、見た目がとてもフラットになり、よりスタイリッシュなデザインを表現できる。では、SEOについてはどうだろうか。ページネーションがないので、検索エンジンが各ページの情報を解析するかどうかは特に気になるところだ。Googleが無限スクロールを実装する上でのベストプラクティス※を公開しているので、その一部を紹介しよう。
JSが無効のブラウザを考慮する
JavaScriptが動かないと、当然、無限スクロールも機能しない。そうなると、次のページへ行く手段がなくなるのでUI的に望ましくない。
そこで、「前ページ」「次ページ」リンクやページネーションを用意し、noscript要素を使用して、JavaScriptが無効時のみ、それらのリンクが表示されるようにしておく(A)。
<div class="loading" style="display: none;"><img src="img/loading.gif" alt=""></div> </div> // ↓--------------------------------------------------↓ A <noscript> <div class="page-link"> <span>1</span> <a href="index2.html">2</a> <a href="index3.html">3</a> </div> </noscript> // ↑--------------------------------------------------↑ A <script src="js/main.js" type="text/javascript"></script>
読み込みに応じてURLを変える
通常、無限スクロールではコンテンツを読み込んだ際にURLは変化しない。そこで、読み込むたびに擬似的にURLを変化させる。
今回は、URLの変更にreplaceStateメソッドを使用する(B)。これはブラウザの履歴には追加せずに、URLの表示だけを変えるものだ。他にpushStateメソッドがあるが、これはブラウザの履歴に追加されるため、ブラウザの「戻る」ボタンを押すと一つ前のURLのスクロール位置に移動してしまう。「戻る」ボタンを押した際のユーザーが期待する挙動は、前ページヘの移動だと思われるので、replaceStateメソッドのほうがいいだろう。
// URLを変えるタイミング if (Math.abs(scroll_pos - last_scroll) > $window.height() * 0.1) { last_scroll = scroll_pos; $('.js-item-list').each(function() { if (mostlyVisible(this)) { history.replaceState(null, null, $(this).attr("data-url")); // B return; } }); }
rel属性で前後のURLを設定する
インデックスへの登録漏れを防ぐために、各ページのhead要素内にlink要素を使って「rel="next"」と「rel="prev"」を設定し、対応する前後のコンテンツのURLをhref属性に記載する(C)。なお、一つ目のコンテンツの「rel="prev"」、最後のコンテンツの「rel="next"」は必要ない。あくまで前後にコンテンツがある場合のみ記述する。
<head> <meta charset="utf-8" /> <title>Items2</title> <script src="https://code.jquery.com/jquery-2.2.0.min.js"></script> <link href="css/eric-meyer-reset.css" rel="stylesheet" type="text/css" /> <link href="css/main.css" rel="stylesheet" type="text/css" /> // ↓--------------------------------------------------↓ C <link rel="next" href="index3.html" /> <link rel="prev" href="index.html" /> // ↑--------------------------------------------------↑ C </head>

Ajaxを使用しているため、ローカル環境では動作しないこともあるので、サーバにアップロードして確認してほしい
※Googleのウェブマスター向け公式ブログ「検索エンジンとの相性を考慮した無限スクロールのベストプラクティス」 http://googlewebmastercentral-ja.blogspot.jp/2014/02/infinite-scroll-search-friendly.html

- Text:橋本裕敬
- 玩具店でマネージャーを経験後、デザイナーとしてWeb制作会社に転職。LINEクリエイターズスタンプなど、Web制作以外のクリエイティブもしつつ、2015年より(株)LIGに入社。 http://liginc.co.jp/

- Text:蓮子和也
- 顔にインパクトがあるフロントエンドエンジニア。アパレル会社でECサイトの運用に携わったのをきっかけにWebデザイナーに転身。大手のサービスの保守運用をメインに行い、数社の制作会社を経て(株)LIGへ参画。LIGでは新規案件を中心にさまざまなUIを実装している。