手軽に実装するもっと見るボタン

# はじめに
一覧表示を行うようなページでは、スクロールと共にコンテンツが表示されたり、もっと見るリンククリックでコンテンツが追加されるといったSPA（シングルページアプリケーション）での実装を検討する事も多いと思います。

しかしコンテンツ数が500件にも満たない規模だと、すべて表示するには量が多いけどわざわざAPIを用意するほどではない、そんな悩みも出てくるのではないでしょうか？

どうにか~~手を抜く~~工数をかけずに実装できる方法はないだろうか？

そこでdisplay:noneの特性に注目しました。
予め要素を非表示にしておき、スクロールされたりもっと見るリンクを押されたタイミングで表示してやればフロントサイドだけで解決できるのでは？

# display:none
> 値 none を使用すると、要素を非表示にできます。 none は、すべての子孫要素も非表示にします。文書は、要素が文書木に存在しないかのようにレンダリングされます。

つまりdisplay:noneはDOM上は存在するが、子孫要素に至るまでボックスを生成しない（不可視のボックスを生成するのではなく！）ということなので、
display:noneが指定されたimgタグで大きな画像を読んでも、描画に時間がかかるといった事はないそうです。


# サンプルソース
やってみました。
まずはリストで画像を並べるサンプルHTMLです。
一つ一つのコンテンツであるliタグは読み込み時はCSSで非表示にしておきます。

```sample.html
<!DOCTYPE html>
<html>

<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width">

  <title>sample</title>

  <style>
    #tileList {
      list-style: none;
    }

    #tileList .content {
      display: none;
    }

    .readMoreBtn {
      display: none;
    }

  </style>

  <script src="https://code.jquery.com/jquery-3.2.1.min.js"></script>
  <script src="./js/sample.js"></script>
</head>

<body>
  <div id="wrapper">
    <ul id="tileList" class="tileList">
      <li class="content"><img src="./img/contents_01.jpg"></li>
      <li class="content"><img src="./img/contents_02.jpg"></li>
      <li class="content"><img src="./img/contents_01.jpg"></li>
      <li class="content"><img src="./img/contents_02.jpg"></li>
      <li class="content"><img src="./img/contents_01.jpg"></li>
      <li class="content"><img src="./img/contents_02.jpg"></li>
    </ul>
    <a href="#" class="readMoreBtn">
      <span class="moreText">もっと見る</span><span class="arrowDown"></span>
    </a>
  </div>
</body>

</html>
```

つぎにJavaScriptです。
初期表示数ともっと見るリンククリックで追加表示する件数を予め指定しておきます。
初期描画時にコンテンツ数（liタグの数）をカウントし、もっと見るリンクがクリックされるたびに追加表示件数分だけdisplay:blockにしています。

```javascript:sample.js
const defaultDispCnt = 2; // 初期表示件数
const addDispCnt = 3;     // 追加表示件数

(function ($) {
  $(function () {
    let maxDispCnt = 0;     // 最大表示件数
    let currentDispCnt = 0; // 現在の表示件数
    let tileList = $('#tileList').children('li'); // 一覧のli子要素をすべて取得

    // 一覧の初期表示
    $(tileList).each(function (i, elem) {
      // 初期表示件数のみ表示
      if (i < defaultDispCnt) {
        $(this).show();
        currentDispCnt++;
      }
      maxDispCnt++;

      // もっと見るボタンを表示
      let displayed = 0;
      if (maxDispCnt > currentDispCnt && !displayed) {
        $('.readMoreBtn').show();
        displayed = 1;
      }
    });

    // もっと見るボタンクリックイベント
    $('.readMoreBtn').click(function () {
      let newCount = currentDispCnt + addDispCnt; // 新しく表示する件数

      // 新しく表示する件数のみ表示
      $(tileList).each(function (i, elem) {
        if (currentDispCnt <= i && i < newCount) {
          $(this).show();
          currentDispCnt++;
        }
      });

      // もっと見るボタンを非表示
      if (maxDispCnt <= newCount) {
        $(this).hide();
      }

      return false;
    });
  });
}(jQuery));
```

# GitHub
自分用の備忘録ですが、もう少し実用的なサンプルソースをGithubに上げています。
[card-list-html](https://github.com/fakefurcoronet/card-list-html)

# おわりに
なお、display:noneで隠されたコンテンツはGoogleなどのクローラでは「ないもの」として扱われるため、評価されない可能性があるそうです。
このあたりは詳しくないのですが、SEOを気にする場合には検討した方がよいかもしれません。