Thymeleaf th:classappendで動的クラス設定する方法を初心者向けに解説
新人
「先輩、Thymeleafでth:classappendっていう属性を見たんですけど、これは何をするものなんですか?」
先輩
「いい質問だね。th:classappendは、Thymeleafで要素に動的にクラスを追加するための属性なんだ。状況に応じてクラスを切り替えたいときにとても便利なんだよ。」
新人
「例えば、エラーメッセージがあるときにだけ特定のクラスを付けたりする場合ですか?」
先輩
「そうそう。その通りだよ。実際にプロジェクトで使われる場面は多いから、しっかり理解しておくと役立つよ。」
1. th:classappendとは何か
Thymeleafのth:classappendは、HTML要素にクラスを動的に追加するための属性です。通常のclass属性に加えて、サーバーサイドの条件や変数の値に応じてクラスを柔軟に設定することができます。
例えば、フォームの入力欄がエラーの場合に「error」というクラスを追加したり、状態が有効なときに「active」というクラスを付けるなどの使い方があります。これにより、動的クラス設定を効率的に行うことができ、ビューの制御が直感的になります。
初心者がまず覚えるべきポイントは、th:classappendは「既存のクラスに追加する」という点です。単純に置き換えるのではなく、すでに書かれているクラスの後ろに条件付きのクラスを付け加えるため、意図せずクラスが消えることはありません。
実際の使い方をイメージしやすくするために、まずは基本的なHTMLコードを確認してみましょう。
<input type="text" class="form-input" th:classappend="${hasError} ? ' error' : ''">
この例では、hasErrorという変数がtrueのときにerrorクラスが追加されます。エラーがある場合だけスタイルを変えたいときに非常に便利です。
このように、Thymeleafのth:classappendは、Javaのコードで設定した値をビューに反映しやすくするための仕組みです。
2. th:classappendを使う場面
それでは、どのような場面でth:classappendを活用できるのかを見ていきましょう。代表的なシーンを挙げると以下のようになります。
エラーメッセージやバリデーションの表示
フォーム入力でバリデーションエラーが発生したときに、赤枠や背景色を付けるためにerrorクラスを追加します。
<input type="text" class="form-control" th:classappend="${#fields.hasErrors('username')} ? ' error' : ''">
このコードでは、ユーザー名入力欄にエラーがある場合にのみerrorクラスが追加され、見た目でエラーを伝えられるようになります。
アクティブなメニュー項目の強調
ナビゲーションメニューで現在選択されているページを強調するために、activeクラスを付与します。
<li class="nav-item" th:classappend="${page == 'home'} ? ' active' : ''">ホーム</li>
<li class="nav-item" th:classappend="${page == 'about'} ? ' active' : ''">このサイトについて</li>
このようにすれば、コントローラから渡されるpage変数の値に応じて、動的にクラスを切り替えることができます。
状態に応じたスタイルの切り替え
例えば、在庫がある商品には「available」クラスを、在庫がない場合には「soldout」クラスを付けるといった使い方が可能です。
<span class="product-status" th:classappend="${product.inStock} ? ' available' : ' soldout'">商品状態</span>
このように、ビュー側での条件分岐を少なくし、シンプルに状態を反映させることができるのが大きなメリットです。
動的クラス設定をうまく利用することで、ビューの可読性が上がり、開発効率も向上します。特に初心者が理解しておくと、エラーハンドリングや状態管理がぐっと楽になります。
3. th:classappendの基本的な使い方
ここからは実際にThymeleafのth:classappendを使った具体的な記述方法を見ていきましょう。基本的なポイントは「既存のクラスに対して条件付きで新しいクラスを追加できる」という点です。これは単純なclass属性だけではできない柔軟な仕組みであり、動的クラス設定の代表的な使い方となります。
例えば、入力欄が必須のときにだけ「required」というクラスを追加したい場合を考えてみましょう。通常のHTMLだけでは静的にしかクラスを記述できませんが、Thymeleafを使えばサーバーサイドの状態に応じてクラスを動的に変えることができます。
<input type="text" class="input-field" th:classappend="${isRequired} ? ' required' : ''">
上記の例では、サーバーサイドから渡されたisRequiredが真の場合にだけ「required」クラスが追加されます。偽の場合には追加されないため、状況に応じた制御が可能になります。このように条件に応じたクラス追加を行うことで、見た目の変更やスタイルの切り替えを柔軟に管理できます。
また、単一の条件だけでなく複数の条件を組み合わせることもできます。条件ごとに異なるクラスを追加することで、入力欄や表示項目の状態をより分かりやすく反映できます。
4. if文的な条件によるクラス付与の例
次に紹介するのは、if文的な条件式を使ってクラスを付与する方法です。Javaコードではif文を用いて分岐を行いますが、Thymeleafでも式を使うことで同じような処理をビュー側で表現することができます。
例えば、在庫がある場合は「stock-yes」というクラスを、在庫がない場合は「stock-no」というクラスを付けたいとします。この場合には三項演算子を使うことで、条件分岐をそのまま記述できます。
<span class="stock-label" th:classappend="${product.stock > 0} ? ' stock-yes' : ' stock-no'">
在庫状況
</span>
このコードでは、商品オブジェクトの在庫数がゼロより大きい場合は「stock-yes」クラスが追加され、そうでない場合は「stock-no」クラスが追加されます。これにより、在庫ありと在庫なしを見た目で簡単に区別することができます。
このように条件付きクラスを設定することで、複雑な状態を簡潔に表現でき、ユーザーにとってわかりやすい画面を作ることができます。特にWebアプリケーションでは状態に応じた見せ方が重要になるため、初心者のうちから習得しておくと良いでしょう。
また、条件式は真偽値だけでなく文字列や数値の比較なども利用できます。たとえばユーザーの権限に応じて表示スタイルを変えるといったケースにも応用できます。
<div class="user-role" th:classappend="${user.role == 'admin'} ? ' highlight' : ''">
管理者ユーザー
</div>
この例では、ユーザーのロールが管理者の場合にだけ「highlight」クラスを付与しています。ロールに応じて見せ方を変えたいときに非常に役立ちます。
5. コントローラと連携してクラスを出し分ける方法
ここまででThymeleafのth:classappendを使った基本的な条件付きクラス設定を学びました。次は、Spring MVCのコントローラと連携してクラスを出し分ける方法を見ていきましょう。開発環境はpleiadesとGradleを使い、コントローラは@Controllerアノテーションで実装します。
例えば、ユーザーがログインしているかどうかを判定して、ログイン済みのときにだけ特定のクラスを付与したいとします。コントローラでフラグを用意してビューに渡すことで、Thymeleaf側でクラスを動的に切り替えることができます。
@Controller
public class UserController {
@GetMapping("/profile")
public String profile(Model model) {
boolean loggedIn = true; // 仮にログイン済みとする
model.addAttribute("isLoggedIn", loggedIn);
return "profile";
}
}
このコントローラではisLoggedInという変数をビューに渡しています。次にThymeleafのテンプレート側で、この変数を使ってクラスを切り替えます。
<div class="profile-box" th:classappend="${isLoggedIn} ? ' logged-in' : ' guest'">
ユーザー情報
</div>
このコードでは、isLoggedInが真であれば「logged-in」クラスが追加され、偽であれば「guest」クラスが追加されます。これにより、コントローラとビューが連携して状態を表現できるようになります。
さらに実用的な例として、コントローラでエラー状態を判定し、その結果に応じて入力フォームにエラー用のクラスを追加することも可能です。
@Controller
public class FormController {
@GetMapping("/input")
public String input(Model model) {
boolean hasError = true; // 仮にエラーがあるとする
model.addAttribute("hasError", hasError);
return "inputForm";
}
}
<input type="text" class="form-input" th:classappend="${hasError} ? ' error' : ''">
このようにコントローラで変数を渡し、ビュー側でth:classappendを使うことで、条件付きクラスを柔軟に設定できます。Spring MVCとThymeleafを組み合わせることで、状態に応じた画面表示を簡単に実現できるのです。
初心者のうちは「クラスの付与をコントローラの変数で制御できる」という仕組みをしっかり理解しておくと、動的な画面制御を自然に実装できるようになります。特に入力フォームやログイン画面など、条件によって見せ方を変える必要がある場面では欠かせないテクニックとなります。
6. th:classappendを使うときの注意点
ここではThymeleafのth:classappendを使うときに起こりやすい書き方の誤りや表示のずれの原因を整理します。まず最初に意識したいのは既存のclass属性との関係です。th:classappendは既存のclassに後から文字列を連結する仕組みなので、最初に書いた固定のクラス名と条件付きで追加したいクラス名のあいだに空白が入らないと結合結果が一つの単語になってしまい、意図しない見た目になることがあります。したがって連結の手前に半角空白を含めるか、固定のclass側を十分に整えておくと安心です。特に長い条件式を書いたときほど空白を落としてしまいやすいため、見直しの習慣を持つと良いでしょう。
次に注意したいのは真偽値の評価方法です。テンプレート式の中で変数が存在しない場合や型が想定と異なる場合、式全体が評価できずに空文字列のままになることがあります。たとえばコントローラでモデル属性を入れ忘れたときには条件が常に偽相当となり、追加したいクラスが反映されません。画面側の調整だけに集中していると見落としやすいため、表示の切り替えが効かないと感じたらコントローラのモデル設定を必ず確認します。
さらに条件式の書き方にも落とし穴があります。数値の比較や文字列の比較で等価演算子を使うとき、文字列の値が想定通りでないと条件が真にならず、狙ったクラスが付与されません。外部入力やデータベースの値が混じる場面では前後の空白や大文字小文字を整える処理を早めに行い、画面の式ではできるだけ単純な比較に留めると事故を減らせます。式が複雑になりすぎたときは一度コントローラ側で中間の真偽値を作ってからビューに渡すと読みやすさも上がります。
またループの中でth:classappendを多用するときにも気をつけます。繰り返しの各行に意図どおりのクラスが付いているかを目で追いにくくなるため、テーブル行や一覧項目の中の状態表現は小さな補助クラスに分け、表示の役割を明確にしておくと混乱を避けられます。表示が崩れたときにはまず要素検証で計算後のclass値を確認し、どの条件が真になっているかを見極めると原因に素早くたどり着けます。
そしてフォーム検証と組み合わせる場合はフィールド名の記述ゆれにも注意します。特に入力欄のnameと検証で参照する名前が一致していないと、エラー時クラス付与の式が常に偽になり見た目で異常を示せません。検証の結果を使う式ではフィールド名を一度定数的に変数へ入れておくと、名前の変更が発生したときにも修正箇所が分散せずに安全です。最後にスタイルの粒度を揃えることも重要で、クラス名は意味のある短い単語に統一しておくと組み合わせても読みやすく保てます。
空白の付け忘れによる結合不具合の簡単な例
次の例では空白の有無で結果が変わります。見た目の差は小さいように見えても、スタイルの指定が当たらない原因になりやすいため必ず確認します。
<!-- 空白なしで結合されてしまう例 -->
<div class="item" th:classappend="${flag} ? 'active' : ''">要素</div>
<!-- 先頭に空白を含めて安全に追加する例 -->
<div class="item" th:classappend="${flag} ? ' active' : ''">要素</div>
存在しない変数を参照してしまう例
次の例ではモデルに値が無いと式が偽相当となり、狙ったクラスが付与されません。表示が切り替わらないときはコントローラの属性設定を再点検します。
<span class="note" th:classappend="${undefinedFlag} ? ' highlight' : ''">注意</span>
7. 実際のアプリケーションでの具体例
ここではフォーム入力の検証と連動したエラー時クラス付与の具体例を示します。画面では各入力欄に対して検証の成否をわかりやすく伝えたいので、エラーがある欄には赤系の縁取りや背景を与え、正常な欄には通常の見た目を維持します。テンプレート側ではフィールドの誤りを検知する補助関数を使い、条件が真になったときにだけ強調用のクラスを追加します。これにより入力の手戻りを減らし、案内の文章を長く書かなくても利用者が直感的に修正できます。
コントローラ側のモデル設定の例
ここでは単純化のために確認用のフラグをモデルに入れていますが、実際の運用ではバリデーションの結果を使うと自然な流れになります。アクションから戻るときに入力値と検証情報を同時に渡すことで、テンプレートでは式の評価に専念できます。
@Controller
public class SignupController {
@GetMapping("/signup")
public String show(Model model) {
model.addAttribute("form", new SignupForm());
return "signup";
}
}
テンプレート側でのエラー時クラス付与の例
次の例ではユーザー名とパスワードの入力欄に対してエラーの有無を判定し、誤りがあるときだけ強調用のクラスを追加します。入力欄の近くに簡潔なメッセージを表示することで、どこを直せばよいかがすぐに分かるようになります。ここで使うクラス名は画面全体の設計に合わせて自由につけられますが、目的が分かる短い単語にしておくと保守時の理解が速くなります。
<form action="/signup" method="post">
<div class="field">
<label for="username">ユーザー名</label>
<input id="username" name="username" type="text"
class="input"
th:classappend="${#fields.hasErrors('username')} ? ' error' : ''">
<div class="help" th:if="${#fields.hasErrors('username')}"
th:errors="*{username}">エラー</div>
</div>
<div class="field">
<label for="password">パスワード</label>
<input id="password" name="password" type="password"
class="input"
th:classappend="${#fields.hasErrors('password')} ? ' error' : ''">
<div class="help" th:if="${#fields.hasErrors('password')}"
th:errors="*{password}">エラー</div>
</div>
<button type="submit" class="button">登録</button>
</form>
行ごとの状態を強調する一覧の例
実務では一覧の各行に対して状態を示すことが多くあります。承認待ちの行だけ背景を強調したい場合や期限切れの行だけ色を変えたい場合などでは、th:classappendを使うと読みやすく安全に表現できます。条件ごとに短い補助クラスを用意しておくと、組み合わせても破綻しにくくなります。
<table>
<tbody>
<tr th:each="item : ${items}"
class="row"
th:classappend="${item.pending} ? ' pending' : ''"
th:classappend="${item.expired} ? ' expired' : ''">
<td th:text="${item.name}">名称</td>
<td th:text="${item.status}">状態</td>
</tr>
</tbody>
</table>
状態の多段判定を見通しよく記述する工夫
条件が増えると式が長くなりがちです。そのようなときはコントローラで用途別の真偽値を用意し、テンプレート側では短い式だけで組み合わせると読みやすさが大きく向上します。表示の責務をビューに寄せつつも複雑さはコントローラで吸収するという分担が、保守のしやすさにつながります。
8. 学習の要点の整理
ここまでの内容を振り返り、初心者が実務で役立てるための要点を整理します。まず最初に覚えたいのはth:classappendの基本的な考え方で、既存のclass属性に条件付きで文字列を追加するという発想です。固定の見た目を崩さずに必要なときだけ強調したいという目的にぴったり合うため、入力欄の強調や現在地の強調など多くの場面で安全に使えます。条件式には三項演算子を用いるのが分かりやすく、真偽値の扱いを明確にしておくほど読みやすさも上がります。
次に忘れずに実践したいのは空白の管理です。追加するクラス名の先頭に半角空白を入れておくことを作法として身につけ、結合後のclass値を検証で必ず確認します。小さな約束事を積み重ねることで、表示の乱れを早い段階で防げます。変数の存在確認や文字列の整形も同様に重要で、コントローラで中間の真偽値を作って渡すという方針をとれば、テンプレートの式は短く簡潔になり、表現の意図がすぐに伝わります。
さらに実装全体の見通しをよくするために、役割ごとに短い補助クラスを設計しておくと保守が楽になります。たとえば誤りの強調用にはerror、注意喚起にはwarn、成功を示すときにはokといった具合に用途を分け、一覧やフォームの各所で同じ語を再利用します。意味の揃った言葉を繰り返し使うことで、画面設計もチーム内の会話も自然と揃い、理解の負担が減ります。
最後に学習の進め方として、小さな画面で実験しながら成功体験を積み重ねると上達が速くなります。入力欄ひとつ、ボタンひとつという小さな単位で条件を切り替えて動作を確認し、うまくいったら一覧やフォーム全体へ広げます。評価のたびに検証でclass値を目視し、どの条件が真になっているかを確かめる姿勢を習慣化すると、問題の切り分けが驚くほど容易になります。ここまでの流れを繰り返せば、動的クラス設定の使い分けは自然と身につき、複雑に見える画面でも自信を持って調整できるようになります。
簡単な確認用テンプレートの雛形
学習の締めくくりとして試行用の最小構成を載せます。小さな雛形で切り替えの感覚をつかみ、条件式の読みやすさやクラス名の粒度を検討してみてください。実験の過程で得られた気づきを次の画面設計に反映させることで、表現の幅は自然に広がっていきます。
<div class="box" th:classappend="${on} ? ' active' : ''">切り替え確認</div>
この雛形のように単純な真偽値から始め、次に検証の結果や状態の組み合わせへと段階的に広げていくと、Thymeleafの特性を理解しながら安全に応用できます。画面が複雑になっても設計の基本は変わらないので、まずは仕組みを体で覚えるつもりで小さく繰り返すと良いでしょう。