【Craft 3 サイト構築の基本】ベーステンプレートの作成

これは Craft CMS Advent Calendar 2018 12日目の記事です。
連載「サンプル制作で覚える Craft 3 サイト構築の基本」の一環として、サイト共通のベーステンプレートを作成します。

ここでは、次の作業を行います。

  1. 空テンプレートファイルの作成
  2. レイアウトテンプレートの作成
  3. テンプレートの継承
  4. ブロックの定義
  5. ブロックの上書き
  6. セグメントを利用した分岐処理

テンプレートのカスタマイズにあたり、公式ドキュメントの「フロントエンド開発」にひと通り目を通してください。あわせて、「素材データ専用リポジトリ vol-7 ブランチ」に工程ごとの差分データをコミットしてありますので、参考にしてください。

空テンプレートファイルの作成

ここで作成するテンプレートファイルの構成を下記とします。ファイルの保存先はプロジェクトディレクトリ直下の templates、拡張子は .html とします。Twig のシンタックスハイライトが適用されるようエディタの設定を適宜調整してください。

index.html は Craft 3 に同梱しているデフォルトテンプレートの中身を書き換える形で流用します。_layout.html は全体のレイアウト、_parcials 下層のファイルはインクルードパーツが含まれます。また、news/index.html が「ニュース」セクションのインデックスページ、news/_entry.html は「ニュース」セクションのエントリ詳細ページとして利用する想定です。

それぞれのディレクトリや空のファイルをあらかじめ作成しておきます。【ダウンロードはこちら】

templates
├── _layout.html
├── _partials/
│   ├── header.html
│   └── footer.html
├── about/
│   └── index.html
├── index.html
├── news/
│   ├── _entry.html
│   └── index.html
├── search/
│   └── index.html
├── services/
│   ├── _entry.html
│   └── index.html
└── work/
    ├── _entry.html
    └── index.html

素材データ専用リポジトリのサンプルコードには、最低限のコメント文を含めてあります。【参考コミット】

レイアウトテンプレートの作成

コーディングデータのトップページ web/html/index.html の内容をコピーして、templates/_layout.html にペーストします。【参考コミット】

共通ヘッダー / フッターのモジュール化

共通ヘッダー部分は templates/_layout.html に記述された div#barheader#header のコードを templates/_partials/header.html にコピーし、代わりに

{# 共通ヘッダーのインクルード #}
{% include '_partials/header' %}

へ書き換えます。

同様に、共通フッター部分は templates/_layout.html に記述された footer#footer のコードを templates/_partials/footer.html にコピーし、代わりに

{# 共通フッターのインクルード #}
{% include '_partials/footer' %}

へ書き換えます。【参考コミット】

なお、サンプルコードの内容であればモジュール化する必要性が低いものの、共通ヘッダーのみで利用する変数をモジュールテンプレート内にまとめるなど、コードの可読性を維持するのに役立つと思います。

テンプレートの継承

ページ別テンプレートの修正前に、Craft 3 のデフォルトテンプレート(templates/index.html)の内容を削除し、他とあわせてコメント文だけ記述しておきます。【参考コミット】

次に、レイアウトテンプレートを継承するため {% extends %} タグを記述します。

{# ベースレイアウトを extends #}
{% extends '_layout' %}

修正対象は、継承元となる次のファイルです。【参考コミット】

  • templates/about/index.html
  • templates/index.html
  • templates/news/_entry.html
  • templates/news/index.html
  • templates/search/results.html
  • templates/services/_entry.html
  • templates/services/index.html
  • templates/work/_entry.html
  • templates/work/index.html

ブラウザからフロントエンドにアクセスすると、リクエストしたページに関わらず以下の内容が表示されます。

テンプレートの表示サンプル

レイアウトテンプレートを継承しているため、これは正しいレンダリング結果です。ページ別テンプレートで上書きするには「ブロック」を定義する必要があります。

ブロックの定義

継承元のページ別テンプレートで上書きしたい場所に {% block %} タグを記述します。

ここでは、サンプルコードにあわせて次の2つのブロックを定義してください。【参考コミット】

ブロック名概要
seoMetameta や OGP 関連のタグを挿入するためのブロック
mainページごとのメインコンテンツ(main#main)を挿入するためのブロック

なお、ページ別テンプレートに対応する {% block %} タグが存在しない場合、レイアウトテンプレートに記述された内容がデフォルトで出力されます。

{# seoMeta ブロック #}
{% block seoMeta %}
 <title>{% if metaTitle is defined %}{{ metaTitle }} | {% endif %}{{ siteName }}</title>
{% endblock %}

そこで、seoMeta ブロックが未定義の場合でも title タグだけは出力するようにし、さらに変数 metaTitle が定義されていればサイト名の前に出力するよう分岐処理を加えてあります。

このように「イレギュラーな場合にページ別テンプレートで上書きできるようにしつつ、未定義であれば共通フォーマットで出力する」といった使い方ができて便利です。

ページごとに CSS や JavaScript を追加する際の注意点

{% css %} タグや {% js %} タグで追加されたコードは、レイアウトテンプレートに特別な記述をすることなく、レンダリング時に自動挿入される仕組みになっています。

ただし、style タグ、または script タグの内容として出力されるため、外部ファイルをリンクさせたい場合は {% block %} タグや変数を利用して出力するようにしてください。

ブロックの上書き

次に、ページ別テンプレートでブロックを上書きできるようにします。「ニュース」セクションのインデックスページ(templates/news/index.html)を例にすると {% extends %} タグに続けて {% block %} タグを定義しています。

{# ベースレイアウトを extends #}
{% extends '_layout' %}

{# main ブロック #}
{% block main %}
{% endblock %}

試しに任意のテキストを {% block main %}{% endblock %} の間に記述後、ブラウザからアクセスして上書きできていることを確認してみてください。

なお、ひとまずインデックス系のテンプレートのみを対象に修正しておきます。【参考コミット】

  • templates/about/index.html
  • templates/index.html
  • templates/news/index.html
  • templates/services/index.html
  • templates/work/index.html

それぞれ、以下のように変数 metaTitle にテキストをセットしているため、ブラウザでアクセスすると title 要素がページごとに切り替わっていることを確認できます。

{# meta タイトル #}
{% set metaTitle = 'ニュース' %}

セグメントを利用した分岐処理

最後に、セグメントを利用した分岐処理を行います。

グローバルナビゲーションのアクティブ表示

https://craft3.dev/html/news/ などのコーディングデータにブラウザからアクセスすると、グローバルナビゲーションのアクティブなセクションに「▲」が表示されているのがわかります。これは1つめの URL セグメントにあわせて CSS のクラスを追記している状態です。

そこで、共通ヘッダーモジュール(templates/_partials/header.html)に次のコードを追加し、最初のセグメントを変数にセットします。

{# リクエストされた最初のセグメントをセット #}
{% set firstSegment = craft.app.request.segments | first %}

あとは「ニュース」ボタンのマークアップ部分で {% if %} タグを加え、条件にマッチすればクラスを追記するようにします。

<a href="{{ siteUrl }}news/"{% if firstSegment == 'news' %} class="sel"{% endif %}>

同様に、それぞれのボタンに分岐処理を加えておきましょう。【参考コミット】

まとめ

今回は、Craft 3 向けにベーステンプレートを作成する流れを見てみました。

基本的にコーディングデータをそのまま流用しつつ、必要な箇所だけモジュール化したりブロックや分岐処理などを加えれば良いため、慣れてしまえば意外とサクサク進められそうですよね?

次回は「ニュース」セクションの作成に戻り、「詳細ページのテンプレート作成」について解説します。

comments powered by Disqus