カテゴリ: Thymeleaf 更新日: 2026/01/09

Thymeleaf th属性の種類まとめ!初心者向けに解説

Thymeleaf th属性の種類まとめ!初心者向けに解説
Thymeleaf th属性の種類まとめ!初心者向けに解説

新人と先輩の会話形式で理解しよう

新人

「先輩、画面を作るときにThymeleaf th属性ってよく出てくるんですが、これはどういうものなんですか?」

先輩

Thymeleaf th属性はテンプレートエンジンであるThymeleafが持つ特別な属性で、サーバーから送られてきたデータを動的に表示するために使うんだ。」

新人

「なるほど!じゃあ普通のHTML属性と何が違うんですか?」

先輩

「通常のHTMLは静的に固定された文字やリンクしか書けないけど、Thymeleaf th属性を使うとコントローラから渡した値を差し込めるから、動的なWebページを簡単に作れるんだよ。」

新人

「それは便利ですね。どんな種類のThymeleaf th属性があるのか知りたいです!」

先輩

「じゃあ、基本的なものから順番に見ていこうか。」

1. Thymeleaf th属性とは?(概要と基本の役割)

1. Thymeleaf th属性とは?(概要と基本の役割)
1. Thymeleaf th属性とは?(概要と基本の役割)

Thymeleaf th属性は、テンプレートエンジンThymeleafの中でHTMLタグに追加して利用する特別な属性です。これを使うことで、サーバー側のJavaコードから渡されたデータをブラウザに表示したり、リンクや画像のパスを動的に生成したりすることができます。

通常のHTMLでは固定されたテキストしか書けませんが、Thymeleaf th属性を使うとコントローラで設定した値を直接表示できるため、動的で実用的なWebアプリケーションを作成することが可能です。

例えば、以下のように@Controllerから文字列を渡すと、テンプレートのth:textでその値を画面に表示することができます。


@Controller
public class HelloController {
    @GetMapping("/hello")
    public String hello(Model model) {
        model.addAttribute("message", "こんにちは、Thymeleafの世界!");
        return "hello";
    }
}

<p th:text="${message}">ここにメッセージが入ります</p>

このように、Thymeleaf th属性はJavaから渡された値を画面に表示するための架け橋のような役割を担っています。

2. th:textの基本(文字列の表示方法)

2. th:textの基本(文字列の表示方法)
2. th:textの基本(文字列の表示方法)

Thymeleaf th:textは、最も基本的で頻繁に利用される属性です。タグの中のテキストをサーバーからの値で置き換えることができます。

例えば次のように記述すると、コントローラから渡されたmessageという値が画面に表示されます。


<p th:text="${message}">ここにサーバーからの値が入ります</p>

このとき、HTMLに直接書いている「ここにサーバーからの値が入ります」という文字はプレースホルダーであり、実際のブラウザには表示されず、サーバーからのデータに置き換えられます。

重要なのは、Thymeleaf th:textを使うと値が自動的にHTMLエスケープされる点です。これにより不正なスクリプトがそのまま表示されることを防ぎ、セキュリティを確保できます。

例えば、コントローラで次のように設定します。


@Controller
public class UserController {
    @GetMapping("/user")
    public String user(Model model) {
        model.addAttribute("name", "山田太郎");
        return "user";
    }
}

<p th:text="${name}">ユーザー名が表示されます</p>

この例では「山田太郎」という文字列がブラウザに安全に表示されます。

3. th:utextとの違い(エスケープの有無)

3. th:utextとの違い(エスケープの有無)
3. th:utextとの違い(エスケープの有無)

Thymeleaf th:utextth:textと似ていますが、大きな違いがあります。それは、HTMLエスケープを行わないという点です。つまり、渡された文字列にHTMLタグが含まれていた場合、そのタグが有効に解釈されてしまいます。

例えば次のようなコードを見てみましょう。


@Controller
public class HtmlController {
    @GetMapping("/html")
    public String html(Model model) {
        model.addAttribute("text", "<strong>太字のテキスト</strong>");
        return "html";
    }
}

<!-- th:textの場合 -->
<p th:text="${text}">通常の表示</p>

<!-- th:utextの場合 -->
<p th:utext="${text}">HTMLタグ付きの表示</p>

th:textを使った場合、画面には「<strong>太字のテキスト</strong>」とそのまま表示されます。しかしth:utextを使った場合は、タグが解釈され「太字のテキスト」として太字で表示されます。

このように、Thymeleaf th:textは安全に文字列を表示するのに適しており、Thymeleaf th:utextは信頼できるデータにだけ使うように注意が必要です。特にユーザー入力をそのままth:utextで表示するのは危険なので避けましょう。

4. th:hrefとth:src(リンクや画像パスの動的設定)

4. th:hrefとth:src(リンクや画像パスの動的設定)
4. th:hrefとth:src(リンクや画像パスの動的設定)

ここではThymeleaf th属性の中でも画面遷移や画像表示で頻繁に使う属性として、リンク先を生成するth:hrefと画像パスを生成するth:srcを取り上げます。これらはアプリケーションのコンテキストパスやリバースプロキシの配下など、環境によって変化する部分を安全に組み立てられる点が大きな特徴です。静的なHTMLで絶対パスや相対パスを直書きすると、環境が変わるたびに修正が必要になりますが、@{...}の書式と組み合わせたThymeleaf th属性を使えば、URLの生成をテンプレートエンジンに任せられるため、保守の手間を大幅に減らせます。さらに、クエリパラメータやパス変数の埋め込みも直感的に書けるので、初心者でも読みやすく間違いにくい形で画面遷移の定義を管理できます。

まずは固定のパスをリンクに設定する最小例です。th:href@{/path}の形で書くと、実行時のコンテキストを考慮した完全なURLが出力されます。次に、パラメータを付与する書き方、パス変数を埋め込む書き方を順に確認します。画像パスについても同様で、ビルドやデプロイの構成によってベースパスが変わる場面でも、テンプレート側は同じ記述で安定して動作します。特に一覧画面でユーザーごとに異なるアイコンやサムネイルを出し分けるとき、th:srcは極めて有効です。

固定パスとクエリパラメータの例


<a th:href="@{/users}">ユーザー一覧へ</a>
<a th:href="@{/search(q=${keyword})}">検索結果へ</a>

パラメータは(キー=${値})の形式で渡せます。文字列だけでなく数値や日付など、モデルに入っている値をそのまま展開できます。次はパス変数の埋め込みです。REST風のパス設計でよく使います。

パス変数の例


<a th:href="@{/users/{id}(id=${user.id})}">詳細を見る</a>

画像パスの生成も同じ感覚で書けます。静的リソースの場所が将来変わっても、テンプレートの変更を最小限に抑えられます。ユーザーごとに異なるファイル名を組み合わせる場合は文字列連結を使います。

画像パスの例


<img th:src="@{/images/default.png}" alt="デフォルト画像">
<img th:src="@{'/images/' + ${user.icon}}" alt="ユーザー画像">

これらのThymeleaf th属性を使い慣れることで、開発環境の違いを意識せずに同じテンプレートを複数の環境で再利用できます。pleiades+Gradleで作成したプロジェクトでも同様に機能し、@Controllerで用意したモデルの値を自然な形でURLに反映できます。初心者はまず固定リンクから始め、パラメータ、パス変数の順で段階的に広げていくと理解が深まります。

5. th:ifとth:unless(条件分岐の使い方)

5. th:ifとth:unless(条件分岐の使い方)
5. th:ifとth:unless(条件分岐の使い方)

続いてThymeleaf 条件分岐の基本であるth:ifth:unlessを整理します。これらは要素の表示と非表示を値の状態に応じて切り替える属性で、テンプレート上の分岐を非常に読みやすく表現できます。否定の表現であるth:unlessは「条件が成り立たないときに表示する」という意味を持ち、th:ifと対になる形で覚えると便利です。メッセージの有無、権限の有無、一覧が空かどうかなど、画面でありがちな判断を短い記述で表せます。特にチーム開発では、条件の意味が見た目で分かるため、コーディング規約として採用するとレビューがスムーズになります。

まずは単純な真偽値での切り替えから確認し、その後、リストの空判定や文字列の空判定など実務で頻出のケースに広げます。複雑な条件を一行に詰め込むと読みづらくなるため、条件式はできるだけ短く保ち、必要なら要素を分けるのが安全です。否定条件が重なる場合にはth:unlessを使うと読み手の混乱を防げます。

単純な条件の切り替え


<p th:if="${login}">ようこそ</p>
<p th:unless="${login}">ログインが必要です</p>

次はリストが空かどうかで表示を分ける例です。一覧が空のとき、明確な案内を出すのはユーザー体験の観点でも重要です。#lists.isEmpty(...)のユーティリティは読みやすく安全な書き方です。

一覧の空判定を伴う案内表示


<div th:if="${#lists.isEmpty(items)}">まだ項目がありません</div>
<ul th:unless="${#lists.isEmpty(items)}">
    <li th:each="it : ${items}" th:text="${it}"></li>
</ul>

文字列の空判定もよく使います。フォーム投稿後の結果メッセージや検索キーワードの有無で説明文を出し分ける場面に役立ちます。テンプレートの読みやすさを保つため、条件と文言を合わせた表現にするのがこつです。

文字列の空判定


<p th:if="${keyword != null and !#strings.isEmpty(keyword)}"
   th:text="'検索ワード:' + ${keyword}"></p>
<p th:unless="${keyword != null and !#strings.isEmpty(keyword)}">検索ワードが未指定です</p>

このようにth:ifth:unlessを使い分けると、Thymeleaf 条件分岐をシンプルな形で保ちやすくなります。条件は短く、役割は分割、文言は明確に、という三点を守ることで、将来の変更にも強いテンプレートになります。

6. th:each(繰り返し処理の基本)

6. th:each(繰り返し処理の基本)
6. th:each(繰り返し処理の基本)

最後にThymeleaf 繰り返しの中心であるth:eachを取り上げます。th:eachはコレクションを反復して要素を順番に表示するための属性で、一覧、表、カードレイアウトなど多くの画面で活躍します。最小の形はth:each="item : ${items}"で、モデル上のitemsに入っている値を一つずつitemに取り出して表示します。さらに、反復の状態を表すオブジェクトを併用すると、インデックスや先頭末尾、奇数偶数などの情報を簡単に利用できます。これにより行番号の表示、区切りの挿入、ストライプ表示など、見た目の工夫が少ないコード量で実現できます。

まずは最小例で値の出力を確認したあと、状態オブジェクトを使って番号付けを行い、空の一覧への配慮まで含めた実務的な書き方に広げます。とくに業務画面では空の状態を適切に案内することが品質に直結するため、繰り返しの前に条件分岐を置く基本形を身につけておくと安心です。さらに、リンク生成や画像表示と組み合わせることで、th:eachはリスト項目から詳細画面への導線作成にも役立ちます。

最小の繰り返し


<ul>
    <li th:each="u : ${users}" th:text="${u.name}"></li>
</ul>

続いて、反復状態を併用する例です。状態オブジェクトはカンマで区切って二つ目の変数名を置くことで利用できます。ここではインデックスを使って番号付けを行い、先頭と末尾を判定して区切りを入れるヒントも示します。

反復状態の併用と番号付け


<ol>
    <li th:each="u, stat : ${users}"
        th:text="${stat.index + 1} + '.' + ${u.name}"></li>
</ol>

表形式の画面では列ごとに異なる表現を出し分けることがあります。行の奇数偶数を使って背景の濃淡を切り替えると読みやすさが向上します。スタイルはプロジェクトの方針に合わせますが、ここではテンプレート上の条件だけ示します。

表形式での出し分け


<table>
    <thead>
        <tr><th>No</th><th>名前</th><th>詳細</th></tr>
    </thead>
    <tbody>
        <tr th:each="u, s : ${users}">
            <td th:text="${s.index + 1}"></td>
            <td th:text="${u.name}"></td>
            <td>
                <a th:href="@{/users/{id}(id=${u.id})}">ひらく</a>
            </td>
        </tr>
    </tbody>
</table>

一覧が空のときに何も出ないと、利用者は操作の手がかりを失います。空の状態に明確な案内を出すことは基本的な配慮であり、th:eachth:if/th:unlessを組み合わせると自然な形で実現できます。

空の状態への配慮


<div th:if="${#lists.isEmpty(users)}">まだユーザーが登録されていません</div>
<ul th:unless="${#lists.isEmpty(users)}">
    <li th:each="u : ${users}">
        <span th:text="${u.name}"></span>
        <a th:href="@{/users/{id}(id=${u.id})}">詳細</a>
    </li>
</ul>

このように、th:hrefth:srcといったURL関連のThymeleaf th属性th:ifth:unlessThymeleaf 条件分岐、そしてth:eachThymeleaf 繰り返しを組み合わせることで、実用的な画面を無理なく組み立てられます。pleiades+Gradleで作成したプロジェクトでも同じ手順で活用でき、@Controllerで渡したモデルの値を直感的に反映できます。まずは最小例を動かし、次にパラメータや状態オブジェクトを加え、空の状態の設計までカバーする、という学習の順番を守ると理解が着実に深まります。小さな成功体験を積み重ねながら、画面の目的に合わせて属性を選び、読みやすく安全なテンプレートを育てていきましょう。

7. th:switchとth:case(条件分岐の応用)

7. th:switchとth:case(条件分岐の応用)
7. th:switchとth:case(条件分岐の応用)

ここではThymeleaf th属性の中でも少し応用的な分岐として、値ごとに表示内容を切り替えるth:switchth:caseを整理します。多数の条件を順番に評価するth:ifの連続より、ひとつの値をもとに分岐させる場面ではth:switchが読みやすく、レビューでも意図が明確になります。状態コード、種別、権限の段階など、サービス層で決まった識別子を画面にわかりやすく置き換える用途に向いています。特にリストの中で行ごとにバッジや説明文を切り替えるときに効果が高く、初学者でも「ひとつの値に対して複数の表現」という考え方を自然に学べます。複雑な条件式を避け、可読性と保守性の双方を高められるのが大きな利点です。

使い方は、親要素にth:switchで基準となる値を与え、子要素にth:caseで分岐ごとの表現を並べます。どの分岐にも当てはまらない場合に出す既定値は、特別なワイルドカード*で記述します。これにより条件漏れのリスクを抑えつつ、例外的な状態にも丁寧に対応できます。まずは最小構成の例から確認し、次に繰り返し表示と組み合わせた現場的な書き方に広げていきましょう。

th:switchとth:caseの最小例


<div th:switch="${status}">
    <p th:case="'NEW'">新規</p>
    <p th:case="'IN_PROGRESS'">処理中</p>
    <p th:case="'DONE'">完了</p>
    <p th:case="*">不明な状態</p>
</div>

次は一覧の中で状態ごとに表示するバッジを切り替える例です。反復と合わせても構造が崩れにくく、後から状態が増えたときも変更箇所を局所化できます。視覚的な装飾はプロジェクトの方針に合わせ、まずは意味のわかるラベル付けから始めると安全です。

繰り返しと組み合わせた応用


<ul>
    <li th:each="t : ${tasks}">
        <span th:text="${t.title}">タイトル</span>
        <span th:switch="${t.status}">
            <em th:case="'NEW'">新規</em>
            <em th:case="'IN_PROGRESS'">処理中</em>
            <em th:case="'DONE'">完了</em>
            <em th:case="*">不明</em>
        </span>
    </li>
</ul>

この書き方に慣れると、複数のth:ifの重複を避けられます。条件の数が増えやすい画面ほどth:switchを軸に構造化することで、Thymeleaf th属性の読みやすさを長期的に維持できます。

8. th:objectとth:field(フォーム入力とデータバインド)

8. th:objectとth:field(フォーム入力とデータバインド)
8. th:objectとth:field(フォーム入力とデータバインド)

次にThymeleaf フォーム入力で中心となるth:objectth:fieldを整理します。これらはフォームの入力値と@Controllerで扱うモデルオブジェクトを自動的にひも付ける仕組みで、名前付けやname属性の記述を毎回手動で行う手間を減らし、記述ゆれによる不具合を防ぎます。フォームの各入力要素にはth:fieldを与え、フォーム全体にはth:objectで対象のコマンドオブジェクト(フォームクラス)を指定します。これにより、画面とサーバーの間で値が自然に往復するようになり、初学者でも正確なバインドを習得しやすくなります。

ここではpleiades+Gradle環境、依存関係はpleiadesのチェックで追加済みという前提で、コントローラとテンプレート、フォーム用のクラスを最小構成で示します。ポイントは「表示時も送信後の再表示時も同じテンプレートで値が入る」こと、そして「検証エラーのメッセージや既定値の反映が素直に書ける」ことです。まずはフォームクラスとコントローラの骨格から確認します。

フォームクラスと@Controllerの例


package com.example.demo.web;

public class UserForm {
    private String name;
    private String email;

    // getter / setter
    public String getName() { return name; }
    public void setName(String name) { this.name = name; }
    public String getEmail() { return email; }
    public void setEmail(String email) { this.email = email; }
}

package com.example.demo.controller;

import com.example.demo.web.UserForm;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.*;

@Controller
public class UserController {

    @GetMapping("/signup")
    public String showForm(Model model) {
        UserForm form = new UserForm();
        form.setName("山田太郎"); // 表示確認用の既定値
        model.addAttribute("userForm", form);
        return "signup";
    }

    @PostMapping("/signup")
    public String submit(@ModelAttribute("userForm") UserForm form, Model model) {
        model.addAttribute("saved", true);
        return "signup";
    }
}

テンプレートではth:objectuserFormを指定し、各入力にはth:fieldでプロパティ名を与えます。これだけでname属性、id属性、現在値の反映が自動で行われます。送信後に同じテンプレートを返すと、入力内容が保持された状態で再表示されるため、確認画面なしの簡素なフローでも体験が損なわれません。

フォームのテンプレート例(th:object/th:field)


<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <title>ユーザー登録</title>
</head>
<body>
<h1>ユーザー登録</h1>

<form th:action="@{/signup}" method="post" th:object="${userForm}">
    <div>
        <label for="name">名前</label>
        <input type="text" th:field="*{name}">
    </div>
    <div>
        <label for="email">メール</label>
        <input type="email" th:field="*{email}">
    </div>
    <button type="submit">登録</button>
</form>

<p th:if="${saved}">登録が完了しました</p>
</body>
</html>

th:object直下のth:field="*{...}"は相対指定の表記で、対象オブジェクトのプロパティを簡潔に参照できます。エラー表示や必須チェックを段階的に足す際にもこの構造を保てば、画面が複雑になっても迷いにくくなります。さらに、Thymeleaf th属性の他の要素(th:ifth:eachなど)と組み合わせることで、確認メッセージ、入力の復元、一覧への反映まで一貫した表現で記述できます。

9. よく使うth属性の整理と開発での活用シーン

9. よく使うth属性の整理と開発での活用シーン
9. よく使うth属性の整理と開発での活用シーン

最後に本記事で扱った属性を学習の順番と活用シーンごとに整理します。まずは表示の基本であるth:textと、信頼できるデータだけに限定して使うth:utextを押さえ、動的な画面の基礎を固めます。次に、画面遷移や静的リソースの参照を安定させるth:hrefth:srcを覚えると、環境差異やURL設計の変更に強いテンプレートが作れます。条件分岐はth:ifth:unlessを起点に、状態ごとの切り替えが多い画面ではth:switchth:caseへ広げます。繰り返しはth:eachに反復状態を組み合わせ、空の状態を丁寧に扱うことで一覧の品質を底上げできます。フォームではth:objectth:fieldを導入し、表示と送信の往復を安全に保つのが基本です。

実務の流れに沿って考えると、最初にモックの静的画面を用意し、そこへth:textを差し込んで動的化します。次に導線のth:href、画像のth:srcで遷移や表示を安定させ、メッセージや権限による出し分けをth:ifth:unlessで実装します。状態の種類が増えて読みづらくなってきたらth:switchへ移行し、一覧の完成度をth:eachで高めます。フォームが登場したらth:objectth:fieldでデータバインドを確実にし、送信後の再表示や完了メッセージの分岐まで一貫した書き方でまとめます。これらはすべてpleiades+Gradleで作成したプロジェクト、@Controllerでビュー名を返す構成でそのまま活用できます。

チーム開発では、テンプレートの可読性を保つために「条件は短く」「役割ごとに要素を分割」「空の状態を明示」の三原則を共有しておくと安心です。属性の選択は目的から逆算し、表示だけならth:text、導線ならth:href、繰り返しならth:each、複数状態の切り替えならth:switch、フォームならth:objectth:fieldというように、迷わない指針を持つと品質が安定します。学習時は小さなサンプルから始め、値を差し替えながら表示の変化を体で覚えるのが近道です。Thymeleaf th属性の特性を理解し、要件に応じて最小限の属性で明快に書く習慣を身につければ、長く運用する画面でも安全で読みやすいテンプレートを維持できます。

開発での活用チェックリスト


<!-- 表示の基本 -->
<p th:text="${title}">タイトル</p>

<!-- 導線の基本 -->
<a th:href="@{/items}">一覧へ</a>

<!-- 条件の基本と応用 -->
<p th:if="${notice != null}" th:text="${notice}"></p>
<div th:switch="${role}">
  <span th:case="'ADMIN'">管理者</span>
  <span th:case="'USER'">一般</span>
  <span th:case="*">不明</span>
</div>

<!-- 繰り返しの基本 -->
<ul>
  <li th:each="i, s : ${items}" th:text="${s.index + 1} + ':' + ${i.name}"></li>
</ul>

<!-- フォームの基本 -->
<form th:action="@{/save}" method="post" th:object="${userForm}">
  <input th:field="*{name}">
  <input th:field="*{email}">
  <button type="submit">送信</button>
</form>

このチェックリストを起点に、画面の目的に合わせて必要な属性だけを選び、小さく作って確かめながら拡張していきましょう。Thymeleaf th属性は置き換え、導線、条件、反復、フォームという五つの柱を押さえるだけで、業務アプリに必要な多くの画面要件を無理なく満たせます。迷ったらまず最小の例で動かし、次に値や状態を増やす。そうした小さな反復こそが、堅実で読みやすいテンプレートを育てる最短ルートです。

この記事を読んだ人からの質問

この記事を読んだ人からの質問
この記事を読んだ人からの質問

プログラミング初心者からのよくある疑問/質問を解決します

Thymeleafのth属性とは何ですか?HTMLと何が違うのですか?

Thymeleafのth属性は、HTMLタグに動的な処理を加えるための属性で、サーバーサイドのJavaコードから値を受け取って画面に表示できます。通常のHTMLは静的で固定された内容しか表示できませんが、th属性を使うとコントローラからのデータをそのまま差し込むことができるため、動的なWebアプリケーション開発に適しています。
コメント
コメント投稿は、ログインしてください

まだ口コミはありません。

カテゴリの一覧へ
新着記事
New1
SpringのWeb開発(Spring MVC)
Spring MVCルーティングの基本を完全解説!ワイルドカードとパス変数を初心者向けにやさしく理解
New2
SpringのWeb開発(Spring MVC)
ViewResolverの設定と使い方を完全ガイド!初心者でもわかるSpring MVCのビュー解決
New3
Thymeleaf
Thymeleaf th属性の種類まとめ!初心者向けに解説
New4
Thymeleaf
初心者向けにThymeleaf 公式ドキュメントの活用法とおすすめ情報
人気記事
No.1
Java&Spring記事人気No1
SpringのWeb開発(Spring MVC)
ルーティングとは?基本概念(Spring MVCのURL制御を理解)
No.2
Java&Spring記事人気No2
Thymeleaf
Thymeleaf とは?初心者向けにThymeleafの基本を徹底解説
No.3
Java&Spring記事人気No3
Springの基本
application.properties と YAML の基本をやさしく解説!初心者向けSpring Boot設定ファイル入門
No.4
Java&Spring記事人気No4
SpringのDB操作
JPAの標準クエリメソッド(findById, findAll)を完全解説!初心者でもわかるデータ取得の基本
No.5
Java&Spring記事人気No5
Springの基本
Spring Bootの環境変数の設定方法をやさしく解説!初心者向けapplication.propertiesの使い方
No.6
Java&Spring記事人気No6
Springの基本
Spring Bootのデフォルトログ設定を徹底解説(Logback / SLF4J)
No.7
Java&Spring記事人気No7
Spring認証(Spring Security)
セッション管理の基本(@SessionAttributes)を完全解説!初心者でもわかるセッションの仕組み
No.8
Java&Spring記事人気No8
SpringのWeb開発(Spring MVC)
ループ処理(th:each)の基本を完全ガイド!Thymeafの繰り返し処理の使い方