Thymeleaf th:classappendの基本と便利な使い方|Spring MVCで学ぶ動的クラス設定
新人
「先輩、ThymeleafでCSSクラスを条件によって変えたいんですが、どうすればいいですか?」
先輩
「それならth:classappendを使うといいよ。Thymeleafのテンプレートエンジンには、動的にクラスを追加できる仕組みがあるんだ。」
新人
「なるほど!th:classとは違うんですか?」
先輩
「そこがポイントだね。今からth:classappendの基本と便利な使い方を、Spring MVCのプロジェクトを使って順に説明していこう。」
1. Thymeleafとは何か(テンプレートエンジンとしての役割)
Thymeleaf(タイムリーフ)は、Spring MVCでよく使われるテンプレートエンジンのひとつです。テンプレートエンジンとは、HTMLファイルの中に変数や条件式を埋め込み、サーバー側で値を動的に反映させる仕組みのことです。たとえば、ユーザー名や商品の一覧などをHTMLに差し込むときに利用されます。
Thymeleafの特徴は、HTMLファイルがそのままブラウザでも開ける「ナチュラルテンプレート構文」を採用している点です。つまり、HTMLとしても正しい文法のまま、サーバー上ではth:で始まる属性を使って動的にデータを表示できます。
例えば、Thymeleafで「こんにちは、〇〇さん」とユーザー名を表示するコードは次のように書きます。
<p th:text="'こんにちは、' + ${userName} + 'さん'"></p>
このように、${userName}にはSpringのコントローラから渡された値が入ります。テンプレートエンジンとしてのThymeleafは、JavaコードとHTMLを分離しつつ、きれいに連携できるのが魅力です。
2. Spring MVCでThymeleafを使うための基本設定(pleiades+Gradle+@Controller構成)
Spring MVCでThymeleafを利用するには、まずプロジェクトを設定する必要があります。今回は、pleiadesでプロジェクトを作成し、依存関係をGradleで管理します。MavenではなくGradleを使用するのが前提です。
プロジェクト作成時に「Spring Web」と「Thymeleaf」にチェックを入れておけば、自動的に依存関係が追加されます。もし手動で設定する場合は、build.gradleに次のように記述します。
dependencies {
implementation 'org.springframework.boot:spring-boot-starter-thymeleaf'
implementation 'org.springframework.boot:spring-boot-starter-web'
}
次に、コントローラクラスを作成します。ここでは、@Controllerアノテーションを使って定義します。@RestControllerではなく@Controllerを使うのがポイントです。
package com.example.demo.controller;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
@Controller
public class ClassAppendController {
@GetMapping("/status")
public String showStatus(Model model) {
boolean active = true;
model.addAttribute("active", active);
return "status";
}
}
このコントローラでは、activeという変数をテンプレートに渡しています。これをThymeleafのHTML側で利用し、CSSクラスを条件によって動的に切り替えられるようにします。
3. th:classappendとは?(静的classと動的classの違い)
th:classappendは、HTML要素に動的にクラスを追加するためのThymeleafの属性です。静的なclass属性と違い、サーバーの変数や条件式をもとにクラス名を制御できます。
たとえば、ユーザーがアクティブ状態ならactiveクラスを追加し、そうでない場合は追加しない、といった制御が可能です。これにより、ボタンの見た目や状態を柔軟に切り替えることができます。
<button class="btn" th:classappend="${active} ? ' active' : ''">ボタン</button>
この例では、${active}がtrueのときに、activeクラスが追加されます。結果的に、HTMLは次のように出力されます。
<button class="btn active">ボタン</button>
もし${active}がfalseなら、activeクラスは追加されません。
<button class="btn">ボタン</button>
th:classappendは、既存のclass属性を保持しながら新しいクラスを「追加」するのが特徴です。これに対してth:classは既存のクラスを「上書き」してしまうため、両者の違いを理解しておくことが大切です。
このように、Spring MVCとThymeleafを組み合わせることで、状態に応じたデザインやレイアウトを簡単に制御できるようになります。たとえば、入力フォームのエラー表示や選択中メニューのハイライトなどにも応用可能です。
4. th:classappendの基本構文と使い方
th:classappendの基本的な構文はとてもシンプルです。HTMLのclass属性に対して、動的にクラスを追加したい場合に使用します。既存のクラスを保持しながら、サーバーの変数や条件によってクラス名を追加できます。
まずは、最も基本的な書き方を確認してみましょう。
<div class="box" th:classappend="' highlight'">メッセージ</div>
上記のコードでは、HTML側でclass="box"を設定した状態に加えて、highlightというクラスを追加しています。実際に出力されるHTMLは次のようになります。
<div class="box highlight">メッセージ</div>
このように、th:classappendはクラスを追加する動作を行います。複数のクラスを追加したい場合は、スペースで区切って記述できます。
<div class="box" th:classappend="' highlight warning'">メッセージ</div>
出力結果では次のように、両方のクラスが追加されます。
<div class="box highlight warning">メッセージ</div>
Thymeleafでは、HTMLを自然な形で記述できるため、テンプレートとしてもブラウザで直接開いて確認しやすいのが特徴です。静的なHTMLに動的なクラスを組み合わせられることで、フロントエンドのデザインを柔軟に制御できます。
5. 条件式(if文や三項演算子)を使ったクラスの動的制御
Thymeleafのth:classappendをより活用するためには、条件式を組み合わせるのがポイントです。状態によってクラスを付けたり外したりすることで、ユーザーの操作やアプリケーションの状態を見た目に反映できます。
Thymeleafでは、Javaの三項演算子(条件 ? 値1 : 値2)を使うことができるため、if文のように分岐処理が可能です。
<div class="status" th:classappend="${active} ? ' active' : ' inactive'">状態表示</div>
この例では、${active}がtrueの場合はactiveクラスが、falseの場合はinactiveクラスが付与されます。結果として、次のようなHTMLになります。
<div class="status active">状態表示</div>
また、条件によってクラスを追加しないケースも簡単に記述できます。
<p class="message" th:classappend="${error} ? ' error' : ''">メッセージ</p>
上記のように、条件がfalseのときは空文字を返すことで、クラスが追加されません。これにより、フォームのバリデーションエラーやメッセージの表示状態を簡単に制御できます。
実際にSpring MVCのコントローラと組み合わせると、次のように使えます。
package com.example.demo.controller;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
@Controller
public class MessageController {
@GetMapping("/message")
public String showMessage(Model model) {
boolean error = false;
model.addAttribute("error", error);
return "message";
}
}
このように、サーバー側で状態を設定し、テンプレートに渡すことで、HTMLの見た目を動的に変更できます。Thymeleaf 条件分岐の考え方を理解すれば、画面の制御がぐっと楽になります。
また、複雑な条件を扱いたい場合は、論理演算子(and、orなど)も使用できます。例えば、次のように書けます。
<div class="box" th:classappend="${active and admin} ? ' highlight' : ''">管理者状態</div>
このように、Thymeleafでは単純な条件式だけでなく、複合条件も柔軟に扱うことができます。Javaの条件分岐と同じような感覚で書けるため、初心者でも理解しやすい構文です。
6. th:classappendとth:classの違い(上書きと追加の使い分け)
ここまで学んだように、th:classappendは既存のクラスを残したまま新しいクラスを追加します。それに対して、th:classは既存のclass属性を完全に上書きします。この違いを正しく理解しておかないと、意図しないデザイン崩れが発生することがあります。
次の例を見てみましょう。
<div class="box" th:class="'highlight'">サンプル</div>
この場合、出力されるHTMLは次のようになります。
<div class="highlight">サンプル</div>
つまり、もともと設定していたclass="box"が消えてしまいます。これがth:classの「上書き」動作です。一方、th:classappendを使えば、既存のクラスに追加するだけなので安全です。
<div class="box" th:classappend="' highlight'">サンプル</div>
このように記述すると、出力結果は以下のようになります。
<div class="box highlight">サンプル</div>
th:classは、条件に応じて完全にクラスを入れ替えたい場合に使用し、th:classappendは既存のクラスを保ったまま動的に追加したいときに使うのが適切です。用途を使い分けることで、HTMLの見た目や動作を意図どおりに制御できます。
たとえば、次のようなケースが考えられます。
- エラー時だけ背景色を赤にしたい →
th:classappendでerrorクラスを追加 - 特定の状態で完全にクラスを切り替えたい →
th:classで新しいクラスを上書き
このように、Spring MVCのコントローラとThymeleafを連携させることで、画面の状態や見た目を柔軟に制御できます。テンプレート側での記述が簡潔になるため、保守性も高まります。
特に初心者のうちは、th:classappendを優先して使うことをおすすめします。既存のクラスを壊さずに追加できるので、誤ってデザインを崩すリスクが少ないからです。
7. 複数の条件を組み合わせてクラスを制御する方法
ここからは、Thymeleaf th:classappend 条件分岐をさらに活用して、複数の条件を組み合わせてクラスを制御する方法を学びましょう。実際の開発では、ひとつの条件だけでなく「ユーザーがログインしていて、かつ管理者の場合だけハイライトする」といった複雑な場面があります。
Thymeleafでは、論理演算子(and、or、not)を使って条件を組み合わせることができます。これにより、Spring MVCで渡された複数の変数をもとに動的クラス設定が可能になります。
<div class="user-status"
th:classappend="${loggedIn and admin} ? ' highlight' : ${loggedIn} ? ' normal' : ' guest'">
ユーザー状態
</div>
この例では、次のように分岐します。
loggedInとadminが両方true→highlightクラスを追加loggedInだけがtrue→normalクラスを追加- どちらも
false→guestクラスを追加
このように三項演算子をネストして使うことで、複数条件を柔軟に処理できます。ただし、可読性が下がるため、条件が多い場合はサーバー側で判定した結果をひとつの変数にしてテンプレートに渡すのがおすすめです。
例えば、Spring MVCのコントローラで次のように書くと、テンプレート側がすっきりします。
package com.example.demo.controller;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
@Controller
public class MultiConditionController {
@GetMapping("/userStatus")
public String userStatus(Model model) {
boolean loggedIn = true;
boolean admin = false;
String statusClass = loggedIn && admin ? "highlight" : loggedIn ? "normal" : "guest";
model.addAttribute("statusClass", statusClass);
return "userStatus";
}
}
テンプレートでは、単純に変数を渡すだけでクラス設定が完了します。
<div class="user-status" th:classappend="' ' + ${statusClass}">状態表示</div>
このように、サーバー側でロジックを整理しておけば、テンプレートの可読性が高まり、保守もしやすくなります。条件が複雑なときほど、Spring MVC側で制御するのがベストです。
8. コントローラとテンプレートの連携による実践例
次に、Spring MVCとThymeleafを連携させて、動的クラス設定を実際に体験してみましょう。今回は、ユーザーのアカウント状態を色で切り替えるサンプルを作ります。
package com.example.demo.controller;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
@Controller
public class AccountController {
@GetMapping("/account")
public String showAccountStatus(Model model) {
String accountStatus = "suspended"; // 状態を「active」「inactive」「suspended」などで変更
model.addAttribute("accountStatus", accountStatus);
return "account";
}
}
次に、Thymeleafのテンプレートを作成します。状態ごとに色分けされるようにth:classappendを設定します。
<div class="account-box"
th:classappend="${accountStatus == 'active'} ? ' active' :
${accountStatus == 'inactive'} ? ' inactive' :
${accountStatus == 'suspended'} ? ' warning' : ''">
アカウント状態:<span th:text="${accountStatus}"></span>
</div>
このように、複数の条件を組み合わせてクラスを付与できます。Spring MVCで設定したaccountStatusの値に応じて、テンプレート側の見た目が自動的に切り替わるのです。
例えば、状態が「active」の場合には「緑色」、状態が「suspended」の場合には「黄色」など、CSSでスタイルを変えることができます。
<style>
.active { color: green; }
.inactive { color: gray; }
.warning { color: orange; }
</style>
この方法を使えば、ユーザーの状態に応じてデザインを自動的に変化させることができます。特に管理画面やダッシュボードなど、状態ごとに見た目を変えたい場面で非常に便利です。
また、テンプレートエンジンの特徴として、HTMLファイルをブラウザで直接開いても構文エラーにならないため、デザイナーとエンジニアの協業にも向いています。
9. よくあるエラーとデバッグのコツ(条件が反映されない・th:classappendが効かないときの原因)
最後に、Thymeleaf th:classappendを使うときに初心者がつまずきやすいポイントを紹介します。Spring MVCと連携していても、条件が反映されないケースはよくあります。その原因を理解しておくことが大切です。
① 変数がコントローラから渡されていない
もっとも多い原因は、Modelに値を追加していないことです。model.addAttribute("active", true);のように、テンプレートで使用する変数を必ず追加しましょう。
model.addAttribute("active", true);
② 条件式のスペースや引用符の誤り
Thymeleafでは、シングルクォーテーション(' ')を忘れたり、余分なスペースを入れると構文が崩れて意図したクラスが付かなくなります。例えば次のようなミスがよくあります。
<!-- 間違い -->
<div th:classappend=${active} ? "active" : "">ボタン</div>
正しくは、属性値全体をクォーテーションで囲み、内部の文字列にはシングルクォートを使います。
<!-- 正しい書き方 -->
<div th:classappend="${active} ? 'active' : ''">ボタン</div>
③ classとth:classappendを混在させて上書きしてしまう
th:classを同時に使用すると、クラスが上書きされてth:classappendの効果が消えてしまう場合があります。動的追加をしたい場合は、必ずth:classappendのみを使うようにしましょう。
<!-- 悪い例 -->
<div class="btn" th:class="'primary'" th:classappend="' active'">ボタン</div>
この場合、th:classが既存のclass属性を上書きしてしまうため、最終的に「btn」が消えてしまいます。解決策は、class="btn"をそのまま残して、th:classappendで追加することです。
<!-- 正しい例 -->
<div class="btn" th:classappend="' active'">ボタン</div>
④ デバッグのコツ
動作確認するときは、まずブラウザで「検証ツール(F12キー)」を開き、実際に出力されたHTMLを確認します。class属性に期待したクラスが含まれていなければ、テンプレート内の条件式が間違っている可能性が高いです。
また、Thymeleafの式評価に慣れていないうちは、次のようにデバッグ用に出力して値を確認するのも有効です。
<p>active変数の値:<span th:text="${active}"></span></p>
これにより、Spring MVCから正しい値が渡っているかを簡単に確認できます。もし値がnullだった場合、コントローラ側のaddAttributeの設定を見直す必要があります。
Thymeleafのテンプレートエンジンは非常に柔軟ですが、構文のミスやデータの未設定によって期待どおりに動かないこともあります。少しずつ確認しながら修正することで、確実に原因を特定できます。
このように、Thymeleaf th:classappendは、シンプルながら強力な機能です。Spring MVCとの連携によって、条件分岐や状態管理を直感的に行うことができるため、動的クラス設定を極めれば見た目の制御が自由自在になります。