6'.静的リソースとレイアウト
学習目標
staticフォルダーに CSS や画像を置き、ルート相対パスでテンプレートから参照できる- フラグメントで共通部分を 1 か所にまとめられる
テンプレート で動的に表示した画面に、CSS や画像を組み込み、共通する部分を 1 か所にまとめます。
1. 静的リソース
Section titled “1. 静的リソース”CSS・画像・favicon のように、コントローラーを経由せずブラウザーから直接読み込まれるファイルを 静的リソース と呼びます。動的に内容が変わらないため、コントローラーで処理する必要がありません。
静的リソースは src/main/resources/static に置きます。static/ 配下のファイルは、ファイル名がそのまま URL のパスになり、Spring Boot が自動で配信します。
| 配置場所 | URL のパス |
|---|---|
static/css/style.css | /css/style.css |
static/images/book.png | /images/book.png |
static/favicon.ico | /favicon.ico |
1-1. CSS の追加
Section titled “1-1. CSS の追加”画面の見た目を整える CSS は、static/css/ に置きます。文字色を変える style.css を作成します。
body { color: #34302d; font-family: sans-serif;}
h1 { color: #6db33f;}テンプレートからは、<link> タグの href 属性で参照します。
<!DOCTYPE html><html lang="ja"><head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <link rel="stylesheet" href="/css/style.css"> <title>Spring Books</title></head><body> <h1>Spring Books</h1></body></html>href="/css/style.css" は、static/css/style.css に対応します。先頭の / から、static/ 配下のパスを書きます。ブラウザーで / を開くと、本文が濃いチャコール、見出しの Spring Books が緑色で表示されます。
1-2. 画像と favicon
Section titled “1-2. 画像と favicon”画像は static/images/ に置きます。book.png を表示するには、<img> タグの src 属性で参照します。
<img src="/images/book.png" alt="本">ブラウザーのタブに表示される favicon は、static/favicon.ico に置きます。Spring Boot がデフォルトで配信するため、テンプレートに <link> を書かなくても自動で読み込まれます。
1-3. ルート相対パスと相対パス
Section titled “1-3. ルート相対パスと相対パス”CSS や画像の参照は、/css/style.css のように先頭に / を付けた ルート相対パス で書きます。先頭の / はアプリケーションのルートを指し、Spring Boot ではそれが static/ に対応します。先頭に / を付けない 相対パス でも書けます。
<!-- ルート相対パス --><link rel="stylesheet" href="/css/style.css">
<!-- 相対パス --><link rel="stylesheet" href="css/style.css">相対パスは、ブラウザーで表示しているページの URL を基準に解決されます。テンプレートが templates/ のどこに置かれているかは関係しません。基準にする URL が変わると、同じ css/style.css でも参照先が変わります。
| 書き方 | URL が / のページ | URL が /books/new のページ |
|---|---|---|
/css/style.css(ルート相対パス) | /css/style.css | /css/style.css |
css/style.css(相対パス) | /css/style.css | /books/css/style.css |
ルート相対パスは、どのページから参照しても同じ /css/style.css を指します。相対パスは、URL が /books/new のページでは /books/css/style.css を指し、そこに CSS はないためスタイルが適用されません。複数のページで共有する CSS や画像は、ルート相対パスで書きます。
2. 共通レイアウトの部品化
Section titled “2. 共通レイアウトの部品化”各ページは、<head> の中身(文字コード・スタイルシート・タイトル)を、それぞれのファイルに同じように書いています。同じ内容を複数のファイルに持つと、スタイルシートを 1 つ足すだけでも全ページの <head> を直すことになります。
Thymeleaf では、共通する部分を 1 か所に定義し、各ページから読み込めます。この共通部分を フラグメント(fragment)と呼びます。
2-1. フラグメントの定義
Section titled “2-1. フラグメントの定義”共通にする部分のタグに th:fragment を付けて、フラグメントを定義します。ページごとに変わる値は、引数で受け取れます。
<タグ th:fragment="フラグメント名(引数)"> ... 共通の内容。引数は ${引数} で参照する ...</タグ>各ページ共通の <head> を、fragments/layout.html にフラグメントとして定義します。ページごとに変わるタイトルは、引数 title で受け取ります。
<!DOCTYPE html><html xmlns:th="http://www.thymeleaf.org"><head th:fragment="head(title)"> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <link rel="stylesheet" href="/css/style.css"> <title th:text="${title}">タイトル</title></head></html>th:fragment="head(title)" は、head という名前のフラグメントを、引数 title を取る形で定義しています。<title th:text="${title}"> は、受け取った title をタイトルに表示します。
2-2. フラグメントの挿入
Section titled “2-2. フラグメントの挿入”定義したフラグメントは、th:replace で挿入します。引数には、そのページの値を渡します。
<タグ th:replace="~{テンプレートのパス :: フラグメント名(引数の値)}"></タグ>books.html の <head> を、フラグメントの挿入に置き換えます。
<!DOCTYPE html><html lang="ja" xmlns:th="http://www.thymeleaf.org"><head th:replace="~{fragments/layout :: head('書籍一覧')}"></head><body> <h1>書籍一覧</h1> <!-- ... --></body></html>~{fragments/layout :: head('書籍一覧')} は、「templates/fragments/layout.html の head フラグメントに、引数 '書籍一覧' を渡したもの」を指します。th:replace は、この <head> をフラグメントの内容で丸ごと置き換えます。
各ページの <head> を同じように置き換えると、<head> の定義は fragments/layout.html の 1 か所にまとまります。スタイルシートを足すときも、フラグメントを 1 か所直すだけで全ページに反映されます。