第4章 トップページを作る

第3章では共通の構造部分を作っていきました。そこではヘッダーやフッターなどはマークアップしましたが、main要素の中身は空だったと思います。この章ではindex.htmlの空のままだったmain要素内をHTMLでマークアップしていきます。

4.1 main要素にトップページと分かるようなIDを付ける

はじめにmain要素へトップページと分かるようなIDを次のように付けます。

<main id="ll-top-page-contents">
</main>

4.2 カルーセル部分のマークアップ

カルーセル部分のマークアップをしていきます。あらためてカルーセルの説明をすると、Nikeなどで使われている「注目させたい複数の画像などをつぎつぎと横にスライド表示する」ものです。

今回カルーセルの実装にslickというライブラリを使います。slick用として次のHTMLを用意します。とはいっても切り替え表示させる画像をjs-slides ll-slidesというクラスを付けたdiv要素で囲むだけです。接頭辞にjs-と付けているクラスはJavaScriptから触ることを明確にするため付けています。

<div class="js-slides ll-slides">
  <img src="images/image_01.jpg" alt="ラブライブ! 2nd グランプリ μ's">
  <img src="images/image_02.jpg" alt="ラブライブ! 1st グランプリ A-RISE">
</div>

4.3 ページネーション部分のマークアップ

カルーセルと連携したページネーション部分のマークアップをしていきます。ページネーションを画像で示すと、図の赤丸部分になります。

アニメではフッター部分に入っているページネーションですが、フッター内にページネーションを含める実装はあまり見ません。そのためmain要素内へ、ページネーションを含めるようにします。

ページネーションは表示される順番が決まっているため、意図的に順序づけられた項目リストを示すol要素を使います。ページネーションは後ほどCSSでスタイルを適用したり、JavaScriptでカルーセルと連携させたりします。

<ol class="js-slides-pagination ll-slides-pagination">
  <li>●</li>
  <li>●</li>
</ol>

4.4 ここまでのHTMLまとめ

トップページのHTMLについてはこれで完成です。ここまでのHTMLをまとめると次のとおりになります。

<main id="ll-top-page-contents">
  <div class="js-slides ll-slides">
    <img src="images/image_01.jpg" alt="ラブライブ! 2nd グランプリ μ's">
    <img src="images/image_02.jpg" alt="ラブライブ! 1st グランプリ A-RISE">
  </div>

  <ol class="js-slides-pagination ll-slides-pagination">
    <li>●</li>
    <li>●</li>
  </ol>
</main>

4.5 main要素の見た目を整える

HTMLによるマークアップが終わったらCSSで見た目を整えていきます。まずトップページのmain要素に対し元の見た目へ近づかせるため、次のように背景色を適用します。

/* トップページ:コンテンツ */
#ll-top-page-contents {
  background-color: #dcdcdc;
}

4.6 カルーセルの見た目を整える

カルーセルに使う要素の見た目を整えます。スタイル定義は簡単でウィンドウの描画領域が狭いときに画像をはみ出させないよう、max-widthというプロパティで要素幅の最大値を指定します。

/* トップページ:カルーセル内の画像 */
.ll-slides img {
  max-width: 100%;
}

次に、カルーセルと連携させるページネーションの見た目を整えます。ここで適用するCSSは次のとおりになります。

ページネーションのマークアップにol要素を使っているため、●の左横に数字が表示されています。左横の数字の表示を消すために.ll-slides-paginationに対してlist-style-type: none;と指定します。

あとはページネーションを中央寄せかつ横並びに表示したり、前景色の指定をします。

/* トップページ:カルーセル連携ページネーションの外枠 */
.ll-slides-pagination {
  margin: 0;
  list-style-type: none;
  text-align: center;
}

/* トップページ:カルーセル連携ページネーションの各要素 */
.ll-slides-pagination li {
  display: inline-block;
  color: #ff64b1;
}

/* トップページ:カルーセル連携ページネーションの現在のページを示す要素 */
.ll-slides-pagination .ll-active {
  color: #fff;
}

トップページのCSS

ここまでをまとめると、次のCSSになります。

/* トップページ:コンテンツ */
#ll-top-page-contents {
  background-color: #dcdcdc;
}

/* トップページ:カルーセル内の画像 */
.ll-slides img {
  max-width: 100%;
}

/* トップページ:カルーセル連携ページネーションの外枠 */
.ll-slides-pagination {
  margin: 0;
  list-style-type: none;
  text-align: center;
}

/* トップページ:カルーセル連携ページネーションの各要素 */
.ll-slides-pagination li {
  display: inline-block;
  color: #ff64b1;
}

/* トップページ:カルーセル連携ページネーションの現在のページを示す要素 */
.ll-slides-pagination .ll-active {
  color: #fff;
}

4.7 JavaScriptを使ってカルーセルの実装をする

トップページのHTMLマークアップやCSSによるスタイル適用が終わったので、JavaScriptを使ってカルーセルの実装をします。index.htmlが置いてあるディレクトリーと同じ場所にscriptsディレクトリーを作り、JavaScriptファイルをmain.jsという名前で作ります。

JavaScriptを書き始める前に、処理の流れを洗い出しておきしょう。今回は次の流れでカルーセルやカルーセルと連携したページネーション(以下ページネーション)を実装していきます。

  1. 他のJavaScriptと競合しないようにする
  2. カルーセルのためにHTML要素を取得する
  3. カルーセルの実装をする
  4. ページネーションの実装をする
  5. カルーセルが動くようにする
  6. ページネーションが動くようにする
  7. カルーセル表示が切り替わったときの処理を設定する

処理の流れを洗い出したところで、上から順に説明します。

4.8 他のJavaScriptと競合しないようにする

はじめに定義した変数や関数が他のJavaScriptに干渉しないよう、JavaScriptのソースコード全体を無名関数で囲みます。JavaScriptは宣言した変数や関数の有効範囲(スコープ)が関数単位で閉じられるため無名関数を使います。無名関数はfunction() {}と書きます。ここから無名関数の全体を()で囲み最後に()を付けることでJavaScriptを即時実行します。つまり(function() {})();となります。こうすることにより無名関数内で宣言した変数や関数が他のJavaScriptへ干渉することを防げます。このように無名関数で全体を囲み即時に実行する関数のことを即時関数と呼びます。

jQueryを使う場合は(function() { ... })();の前に$を書いて最後の()を削除します。つまり$(function() { ... });となります。$を書く理由はブラウザーがHTMLを読み込んで解釈した後にJavaScriptを実行させるためです。HTMLを解釈した後にJavaScriptの実行をしない場合、JavaScript内でHTMLの要素を取得できない可能性があります。また最後の()を削除した理由は、$というのはjQueryの関数だからです。$関数の引数として関数を指定するため、最後の()がいらなくなります。

続いて$(function() { ... });の中には"use strict";という文字列を書いています。これはJavaScriptをコーディングする上でミスしやすい部分をエラーとして検出してくれるものです。将来に備えていくつかの単語を自由に使えなくする(たとえばletyieldなど)効果があるため、"use strict";は書いても損はありません。

ここまでをまとめると次のソースコードになります。上に書いたことはなかなか覚えづらいので、JavaScriptを書くときにjQueryを使う場合は図のようにすると覚えておけば大丈夫です。

$(function() {
  "use strict";

  // ここにソースコードを書いていく
});

4.9 カルーセルのためにHTMLの要素を取得する

JavaScriptでHTMLの要素を扱えるようにします。これはjQueryの$関数を使って、HTMLの要素をJavaScriptから次のとおり取得します。

準備の節では、ブラウザーがJavaScriptをHTMLの解釈後に実行するため$関数を使いました。ここではHTMLの要素をJavaScriptで利用できるようにするため$関数を使います。jQueryの$関数はこのように万能なものとなります。

var carouselElement = $(".js-slides");
var paginationElement = $(".js-slides-pagination");
var paginationItemElements = $(".js-slides-pagination li");

4.10 カルーセルの実装をする

HTMLの要素を取得したらカルーセルの実装をしていきます。今回カルーセルの実装をする上でslickというライブラリを使っていきます。このslickを使えるよう初期化する関数と、いま表示しているページがどこか示すための関数を実装していきます。

まずカルーセルの元になるCarousel関数から説明します。Carousel関数はパラメーターとして、次のふたつがあります

これらのパラメーターを元にCarousel関数でslickが使えるようにします。

次にgetCurrentIndexを説明します。これはページネーションで使う関数となります。getCurrentIndexはカルーセルでいま表示しているページがどこか示す数字を返す関数です。この実装にはslickで定義されているslickCurrentSlideという関数を使います。

function Carousel(carouselElement, config) {
  this.carouselElement = carouselElement;
  carouselElement.slick(config);
}

Carousel.prototype.getCurrentIndex = function() {
  return this.carouselElement.slick("slickCurrentSlide");
};

カルーセルの実装が終わったところで、現在どのページを表示しているのか視覚的に分かりやすくするページネーションの実装をしていきます。

4.11 ページネーションの実装をする

ページネーションの元になるCarouselPagination関数を説明します。CarouselPagination関数ではパラメーターとして、次の3つがあります。

これらのパラメーターを元にCarouselPagination関数でページネーションが使えるようにします。あとはカルーセルの表示を切り替えるときにactivatePage関数とdeactivatePage関数を呼び出してページネーションの表示を変えられるようにします。

function CarouselPagination(paginationElement, paginationItemElements, activePageName) {
  this.activePageName = activePageName;
  this.paginationElement = paginationElement;
  this.paginationItemElements = paginationItemElements;
}

CarouselPagination.prototype.activatePage = function(index) {
  this.paginationItemElements[index].classList.add(this.activePageName);
};

CarouselPagination.prototype.deactivatePage = function() {
  var _this = this;

  Array.prototype.map.call(this.paginationItemElements, function(paginationItemE) {
    paginationItemE.classList.remove(_this.activePageName);
  });
};

いよいよカルーセルやページネーションが動作するようにします。

4.12 カルーセルが動くようにする

先ほど実装したカルーセルを次のとおり呼び出して動くようにします。カルーセルの設定として3項目設定します。

var carousel = new Carousel(carouselElement, {
  autoplay: true,
  autoplaySpeed: 5000,
  arrows: false
});

4.13 ページネーションが動くようにする

カルーセルと同じように、実装したページネーションを次のとおり呼び出してページネーションを動かします。ページネーションの初期設定として、ページネーション内はじめのli要素に現在アクティブであることを示すクラス名が付くようにします。

var carouselPagination = new CarouselPagination(paginationElement, paginationItemElements, "ll-active");
carouselPagination.activatePage(carousel.getCurrentIndex());

4.14 カルーセル表示が切り替わったときの処理を設定する

カルーセル表示が切り替わったときに、連動してページネーションの表示を切り替えるようにします。この実装にはslickで定義されているafterChangeというイベントをjQueryのon関数を使って拾えるようにします。

carouselElement.on("afterChange", function() {
  carouselPagination.deactivatePage();
  carouselPagination.activatePage(carousel.getCurrentIndex());
});

4.15 トップページのJavaScriptまとめ

これまでのJavaScriptをまとめると次のとおりになります。次のコードでは関数などの書き順が説明した順番と違います。しかしこの書き順で書いたほうが自分は見やすいと感じるため、あえて書き順を変えています。

$(function() {
  "use strict";

  //////////////////////////////////////////////////

  function Carousel(carouselElement, config) {
    this.carouselElement = carouselElement;
    carouselElement.slick(config);
  }

  Carousel.prototype.getCurrentIndex = function() {
    return this.carouselElement.slick("slickCurrentSlide");
  };

  //////////////////////////////////////////////////

  function CarouselPagination(paginationElement, paginationItemElements, activePageName) {
    this.activePageName = activePageName;
    this.paginationElement = paginationElement;
    this.paginationItemElements = paginationItemElements;
  }

  CarouselPagination.prototype.activatePage = function(index) {
    this.paginationItemElements[index].classList.add(this.activePageName);
  };

  CarouselPagination.prototype.deactivatePage = function() {
    var _this = this;

    Array.prototype.map.call(this.paginationItemElements, function(paginationItemE) {
      paginationItemE.classList.remove(_this.activePageName);
    });
  };

  //////////////////////////////////////////////////

  var carouselElement = $(".js-slides");
  var paginationElement = $(".js-slides-pagination");
  var paginationItemElements = $(".js-slides-pagination li");

  var carousel = new Carousel(carouselElement, {
    autoplay: true,
    autoplaySpeed: 5000,
    arrows: false
  });

  var carouselPagination = new CarouselPagination(paginationElement, paginationItemElements, "ll-active");
  carouselPagination.activatePage(carousel.getCurrentIndex());

  carouselElement.on("afterChange", function() {
    carouselPagination.deactivatePage();
    carouselPagination.activatePage(carousel.getCurrentIndex());
  });
});

トップページのスクリーンショットは次のとおりになります。

完成したトップページ

図4.2: 完成したトップページ