レイアウト

レイアウトとは

Webシステムのビュー表示では、各ページ同じHTML部分をコーディングするのは非効率です。レイアウトはWebアプリケーションのHTMLを共通化し、テンプレートの再利用性を高めることができます。

レイアウト(共通部分)

HTMLの共通部分を用意(htmlやheadタグなど)を用意します。

<!DOCTYPE html>
<html lang="ja">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>My Page</title>
</head>

<body>
  <main class="container">
      <!-- 各ページのコンテンツ -->
  </main>
</body>

</html>

コンテンツ1

各ページはそのコンテンツ部分だけコーディングします。

<div>
    コンテンツ1
</div>

コンテンツ2

<div>
    コンテンツ2
</div>

Thymeleafのレイアウト

Spring Bootのレイアウト作成は、Thymeleafのレイアウト機能を使用すると便利です。

レイアウトフォルダ作成

まず、src/main/resources/templateslayoutsフォルダを作成します。

レイアウトファイル作成

layoutsフォルダに user.html を作成します。

Thymeleaf Layout Dialect

Thymeleaf Layout Dialectとは

Thymeleaf Layout Dialectは、Thymeleafのレイアウト機能拡張ライブラリです。Thymeleafのデフォルトレイアウトは若干利用しずらいので、今回はこのライブラリを利用します。

  • 各種バージョンや追加方法によって、ライブラリがうまく動作しない場合があるので注意が必要です

依存追加

Thymeleaf Layout Dialect を利用するには、「pom.xml」に thymeleaf-layout-dialectを追加する必要があります。

ライブラリ依存追加

dependency(ライブラリ依存)の追加は、以下の方法があります。

  • 「pom.xml」に直接記述
  • VSCodeのMavenツールで追加

pom.xml に直接記述する場合

今回は「pom.xml」で直接設定します。 「pom.xml」に以下のdependencyを追加します。

pom.xml
<dependency>
    <groupId>nz.net.ultraq.thymeleaf</groupId>
    <artifactId>thymeleaf-layout-dialect</artifactId>
</dependency>
  • groupId、artifactIdを事前に調べる
  • dependencyの中に記述

「pom.xml」を保存すると以下のダイアログが表示されるので、【YES】ボタンでビルドします。

ビルド

「pom.xml」を保存すると以下のダイアログが表示されるので、【YES】ボタンでビルドします。

キャッシュクリア

キャッシュが残っていると、「」が利用できない場合があるので、【Rebuild All】ボタンでリビルドします。

pom.xml
<dependency>
    <groupId>nz.net.ultraq.thymeleaf</groupId>
    <artifactId>thymeleaf-layout-dialect</artifactId>
</dependency>

レイアウトの利用

レイアウト作成

layoutsフォルダ作成

templates/layoutsフォルダを作成します。

HTML作成

layouts/default.html を作成します。headタグにはBootstrap5(CDN)とCSS外部リンクを追加します。

layouts/default.htm
<!DOCTYPE html>
<html lang="ja">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>My News</title>
    <link href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css" rel="stylesheet">
    <link rel="stylesheet" th:href="@{/css/style.css}">
</head>
<body>
  
</body>
</html>

layout:fragment

レイアウトフラグメントとは

layout: fragment タグは、ページの共通部分を切り出し、再利用可能なコンポーネントとして定義できます。このコンポーネントされたHTMLはフラグメントといい、フラグメント名で識別します。

<div layout:fragment="フラグメント名"></div>

レイアウトフラグメント追加

各ページのコンテンツを表示する領域に、フラグメント名 contents でフラグメントを追加します。

templates/layouts/default.html
...
<body>

  <main class="container">
    <div class="row">
      <div class="col-md-12">
        <!-- 以下のdivの中に各ページコンテンツが表示 -->
        <div layout:fragment="contents"></div>
      </div>
    </div>
  </main>

</body>
...

コンテンツページ

home/index.html のコンテンツをレイアウトで表示できるように修正します。

レイアウト指定

<div layout:decorate="レイアウトのファイルのパス">

</div>

フラグメント指定

レイアウト(親)でコンテンツ表示(子)するには、表示コンテンツ(子)のlayout:fragmentプロパティに、レイアウト(親)のフラグメント名を設定します。

<div layout:fragment="レイアウトのフラグメント名">

</div>

レイアウト読み込み

「home/sample.html」をレイアウト「layouts/default.html」から読み込みます。

  • layout:decorate: layouts/default
  • layout:fragment: contents
templates/home/sample.html
<!-- レイアウトとフラグメントの指定 -->
<main layout:decorate="layouts/default" layout:fragment="contents">
  <div>
    <h2>最新ニュース</h2>
    <div>
      <h3>ニュースタイトル1</h3>
      <p>
        <span>2023/07/01 13:15</span>
      </p>
    </div>

    <div class="mb-3">
      <img src="/images/tokyo_station.jpg" width="500">
    </div>

    <div>
      <h3>ニュース一覧</h3>
      <ul class="list-group">
        <li class="list-group-item"><a th:href="@{/article/1}">ニュース1</a></li>
        <li class="list-group-item"><a th:href="@{/article/2}">ニュース2</a></li>
        <li class="list-group-item"><a th:href="@{/article/3}">ニュース3</a></li>
      </ul>
    </div>
  </div>
</main>

ブラウザで確認

レイアウトを利用してコンテンツが表示されるか確認してみましょう。

結果

演習

問題1

「article/sample.html」をレイアウト「layouts/default.html」から読み込みましょう。

問題2

「layouts/admin.html」を作成し、「/admin/」にアクセスして表示してみましょう。

layouts/admin.html
<!DOCTYPE html>
<html lang="ja">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>My News</title>
    <link href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css" rel="stylesheet">
    <link rel="stylesheet" th:href="@{/css/style.css}">
</head>

<body>

  <main class="container">
    <div class="row">
      <div class="col-12">
        <div layout:fragment="contents"></div>
      </div>
    </div>
  </main>

  <script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/js/bootstrap.bundle.min.js"></script>
</body>

</html>

問題3

「/admin/article/」にアクセスしてHTMLを表示してみましょう。

Spring超入門