Thymeleaf th:attrで属性をまとめて設定する方法を初心者向けに解説
新人
「先輩、Thymeleafで属性をまとめて設定できると聞いたんですけど、本当ですか?」
先輩
「そうだよ。Thymeleafにはth:attrという便利な属性があって、複数のHTML属性を一度に指定できるんだ。」
新人
「なるほど!でも、そもそもThymeleafって何なんですか?」
先輩
「それじゃあまず、Thymeleafとは何か、そしてth属性がどういう役割を持っているのかから説明しよう。」
1. Thymeleafとは?
Thymeleafは、Javaで開発するWebアプリケーションの画面を作るためのテンプレートエンジンです。特にSpring MVCと組み合わせて使われることが多く、HTMLをベースにしているため、初心者でも直感的に理解しやすい特徴があります。Thymeleafを利用することで、静的なHTMLファイルの中にth属性を使って動的なデータを埋め込めます。例えばコントローラで作成したモデルデータをHTMLに表示したり、条件分岐や繰り返し処理を行ったりすることが可能です。
また、ThymeleafはIDEでのプレビューがしやすい点も魅力です。通常のHTMLとしてブラウザで開いても崩れにくいので、デザイナーとエンジニアが共同で作業する場合にも便利です。特にSpring BootやSpring MVCとセットで使うケースが多いため、Java初心者が最初に学ぶべき技術のひとつといえます。
今回の記事では、開発環境としてpleiadesをインストールしてGradleを利用し、コントローラは@Controllerを使用するという前提で解説していきます。MavenではなくGradleを利用する点や、@RestControllerではなく@Controllerを使う点に注意してください。
2. th属性とは?(特にth:attrの役割の前置き)
th属性とは、Thymeleaf独自の属性の総称で、HTMLタグに追加することでサーバーサイドの値や処理結果を反映させられる仕組みです。例えばth:textを使えばテキストを動的に出力でき、th:hrefを使えばリンク先を動的に切り替えることができます。
その中でも今回のテーマであるth:attrは、複数のHTML属性をまとめて設定できる特別な属性です。通常であれば、th:hrefやth:srcを個別に書く必要がありますが、th:attrを使えばひとつの記述でまとめて指定できるので、コードの可読性や保守性が向上します。
例えば以下のように書けます。
<a th:attr="href=@{/home}, title=${pageTitle}">ホームへ移動</a>
このように、hrefとtitleを同時に設定することができ、コードの簡潔さが大きなメリットとなります。初心者のうちは、th:textやth:hrefなどを個別に使うことから始めると理解が進みやすいですが、慣れてきたらth:attrを活用して効率的な記述を覚えていきましょう。
特に実際の現場では、リンクやボタンに対して複数の属性を同時に設定する場面が多いため、th:attrを知っておくことは非常に重要です。検索エンジン対策(SEO)の観点からも、正しく属性を設定することはWebサイトの評価につながるため、この機能を理解しておくことは初心者にとって大きな学びになります。
3. th:attrで複数の属性を一度に指定する方法
ここからは、実際にThymeleaf th:attrを使って複数の属性を一度にまとめて指定する方法を解説します。通常のHTMLでは、hrefやtitle、altなどを個別に書きます。しかしThymeleafのth:attrを使うと、ひとつのタグに対して複数の属性をまとめて設定でき、コードの管理がとても楽になります。特にリンクやボタンなどは複数の属性を持つことが多いので、この書き方を知っておくことで開発効率が大きく上がります。
例えば以下のように書きます。
<a th:attr="href=@{/user/list}, title=${title}, target=_blank">ユーザー一覧</a>
この例では、href、title、targetを同時に設定しています。もしth:hrefやth:titleを個別に書いた場合は3行分の記述が必要になりますが、th:attrを使えばひとつの属性で済むのでコードがすっきりします。こうした記述は、Spring MVCの@Controllerでモデルに入れた値を効率よく画面に反映させるときに特に役立ちます。
また、属性の区切りはカンマで書く点に注意してください。初心者がよく間違えるのはセミコロンやスペースを使ってしまうことですが、正しくはカンマを使う必要があります。覚えておくと、エラーで悩まずに済みます。
4. th:attrの基本的なコード例
それでは、Thymeleaf th:attrを使った基本的なコード例を確認しましょう。以下の例では、Spring MVCのコントローラで値をモデルに追加し、それを画面で利用するケースを示します。
@Controller
public class UserController {
@GetMapping("/user/info")
public String userInfo(Model model) {
model.addAttribute("username", "山田太郎");
model.addAttribute("profileUrl", "/user/profile");
return "userInfo";
}
}
そしてThymeleafのテンプレートでは次のように書きます。
<a th:attr="href=@{${profileUrl}}, title=${username} + 'のプロフィール'">プロフィールページ</a>
この例では、コントローラから渡したusernameとprofileUrlを使って、リンクのhrefとtitleを一度に設定しています。こうすることで、ユーザー名をそのままタイトルに反映させたり、遷移先のリンクを柔軟に切り替えたりできます。もしth:hrefとth:titleを別々に書くと行数が増えてしまい、コードが読みにくくなりますが、th:attrなら1行でまとめられるので非常に便利です。
特に企業向けのシステム開発や会員制サイトなど、画面のリンクが多いプロジェクトでは、この記述方法を知っているだけでメンテナンス性が大きく向上します。新人エンジニアが実際の業務でまず覚えておきたいのは、こうした小さな効率化のテクニックです。
5. th:attrを使うメリット(コードの見やすさ、管理のしやすさ)
最後に、Thymeleaf th:attrを使うメリットを整理しておきましょう。最大のメリットは、複数の属性をまとめて指定できることでコードがすっきりする点です。特にHTMLテンプレートは長くなりやすいため、見やすさを保つことはとても重要です。
例えば次のようなケースを考えてみましょう。
<!-- th:hrefやth:titleを個別に書いた場合 -->
<a th:href="@{/dashboard}" th:title="${title}" th:target="_blank">ダッシュボード</a>
<!-- th:attrでまとめた場合 -->
<a th:attr="href=@{/dashboard}, title=${title}, target=_blank">ダッシュボード</a>
見比べてみると、後者の方が行数も少なく、全体として整理されています。このように、コードの見やすさが大きく向上するのがth:attrの強みです。
もうひとつのメリットは管理のしやすさです。もし複数の属性を個別に書いていた場合、それぞれを修正する必要があります。しかしth:attrなら一か所でまとめて管理できるため、修正漏れや記述ミスを防ぎやすくなります。特に大規模なプロジェクトや複数人で開発している場合には、この差が後々大きな影響を与えます。
さらに、th:attrはSEO対策にも役立ちます。titleやaltを正しく設定することで、検索エンジンに正確な情報を伝えられます。リンクや画像に適切な属性を設定することはWebサイトの評価を上げる基本ですので、初心者のうちから意識して活用するとよいでしょう。
このように、Thymeleaf th:attrを使えば、コードが見やすくなり、保守性も高まり、さらにSEOの面でも有利になるため、覚えておいて損はありません。実際の現場で役立つ知識として、積極的に練習しながら身につけていきましょう。
6. th:attrを使う際の注意点(属性の上書き、th専用属性との違い)
まず意識したいのは、属性の上書きに関する挙動です。ひとつのタグに対してth:attrで同じ属性名を複数回指定したり、th:hrefなどの専用属性とth:attrの両方で同じ属性を設定したりすると、最終的にどの値が反映されるかが分かりにくくなります。テンプレート処理では各th属性が順番に評価されますが、評価順や指定方法によって結果が変わる可能性があるため、ひとつの属性はどちらか片方の方法に統一して書くのが安全です。
次に、th専用属性との違いです。例えばth:hrefやth:srcは、それぞれリンク先や画像のパスを扱うために最適化された専用属性です。@{...}記法によるコンテキストパス付与などの仕組みは、th:attr内でも利用できますが、可読性という点では専用属性の方が直感的で、コードを読む人に意図が伝わりやすくなります。逆にフォームのラベルやアクセシビリティ関連の属性をまとめたい場合などは、th:attrで一括設定する方が見通しが良くなります。つまり、可読性と保守性を基準に使い分けるのがポイントです。
また、真偽値属性にも注意が必要です。disabledやcheckedといった属性は存在するだけで有効になるため、th:attrで空文字を入れてもブラウザ側では有効と解釈されることがあります。値の有無を切り替えたい場合は、th:ifやth:attrと式を組み合わせて、属性自体の出力を制御する書き方を選ぶと安全です。
さらに、文字列連結やエスケープにも配慮しましょう。タイトルや代替テキストを組み立てるときに、モデルの値をそのまま結合すると意図しない文字列になることがあります。Thymeleafの式では+による連結が可能ですが、th:textと同様に自動エスケープが前提です。信頼できない入力を属性に出力する場合は、適切なサニタイズと検証を行い、ユーザー入力を直接th:attrに埋め込まないという基本を守りましょう。
最後に、デバッグ時の確認手順です。出力された最終HTMLをブラウザの開発者ツールで確認し、属性が想定どおりに反映されているかを逐次チェックする習慣をつけると、Thymeleaf th:attrの挙動を早く理解できます。特に複数の条件や繰り返しの中で属性を切り替える場合、テンプレートだけを眺めても気づけない不整合が生じることがあるため、実際のレンダリング結果を常に検証することが重要です。
7. よく使われる実例(フォームやリンクでの活用)
ここでは、Spring MVCの@Controllerから渡したモデルを前提に、Thymeleaf th:attrで属性設定をまとめる実例を段階的に確認します。フォーム入力やリンク作成では、placeholder、aria-label、required、title、relなど複数の属性を同時に扱うことが多く、th:attrが効果を発揮します。
まずはコントローラ側でフォームに必要な情報を用意します。
@Controller
public class AccountController {
@GetMapping("/account/edit")
public String edit(Model model) {
model.addAttribute("displayName", "山田花子");
model.addAttribute("profileHelp", "ニックネームを入力してください");
model.addAttribute("saveUrl", "/account/save");
model.addAttribute("externalDoc", "https://example.com/policy");
model.addAttribute("isReadonly", false);
return "accountEdit";
}
}
テンプレートでは次のように、入力欄の複数属性をth:attrで一括設定します。プレースホルダやラベルの文言、読み取り専用の切り替えをまとめて書けるため、視認性が高まります。
<input type="text"
th:attr="placeholder=${profileHelp}, aria-label=${profileHelp}"
th:value="${displayName}"
th:attrappend="${isReadonly} ? ' readonly' : ''" />
上記ではth:valueを併用していますが、同じくth:attrに含めても構いません。可読性を優先して分けるか、一か所にまとめるかはチームのコーディング規約に合わせて選びましょう。なお読み取り専用の切り替えは、属性の追加や削除が分かりやすいth:ifやth:attrの条件式を用いる方法が実務では扱いやすいです。
次は、フォームの送信ボタンに複数の属性を持たせる例です。ツールチップ表示やアクセシビリティ説明を一度に指定しつつ、送信先のURLは別の要素で管理しても良いでしょう。
<button type="submit"
th:attr="title='保存します', aria-label='保存ボタン'">保存</button>
リンク要素では、relやtitle、新しいタブで開くtargetなどをまとめます。外部サイトへのリンクはセキュリティ上rel="noopener noreferrer"を付与するのが一般的です。これらもth:attrで一度に管理できます。
<a th:attr="href=@{${externalDoc}}, title='ポリシーを確認', rel='noopener noreferrer', target=_blank">
利用ポリシー
</a>
画像タグでは、代替テキストとパスを同時に扱うことが多いです。altはアクセシビリティと検索エンジンの両面で重要な属性なので、Thymeleaf th:attrで抜け漏れなく指定する習慣を付けましょう。
<img th:attr="src=@{/images/user.png}, alt=${displayName} + 'のアイコン'}" />
これらの実例のとおり、フォームやリンクでは複数の属性を同時に変更する場面が頻出します。テンプレートから見て意味の塊として扱えるように、関連する属性をひとまとめにするという意識が、保守性と読みやすさを大きく高めます。特に画面数が多い業務アプリケーションでは、属性の追加や仕様変更が継続的に発生するため、th:attrの活用が長期的な開発コストの削減につながります。
8. 初心者が次に学ぶべき関連th属性(th:href, th:src など)
最後に、Thymeleaf th:attrと併せて学ぶと理解が深まるth属性を整理します。まずはリンクと画像の定番であるth:hrefとth:srcです。パスの組み立てには@{...}を用いるのが基本で、アプリケーションのコンテキストパスを自動付与できます。これにより、環境が変わってもリンク切れを避けられます。
<a th:href="@{/dashboard}">ダッシュボード</a>
<img th:src="@{/assets/logo.svg}" alt="ロゴ" />
次に、テキスト出力の基本であるth:textと、HTMLをそのまま出力するth:utextです。通常はエスケープされるth:textを使い、どうしても整形済みのHTMLを出したい場合のみth:utextを選ぶというのが安全な指針です。ユーザー入力をth:utextで出力するのは避け、サニタイズを徹底します。
<p th:text="${displayName}"></p>
<p th:utext="${safeHtml}"></p>
スタイルやクラスを条件によって切り替えるときは、th:classappendやth:styleが便利です。複数の見た目のバリエーションを切り替えるケースでは、th:attrで一括指定するよりも、専用属性での追記のほうが意図を読み取りやすいことがあります。
<span class="badge" th:classappend="${isReadonly} ? ' badge-secondary' : ' badge-primary'">状態</span>
表示制御の基本はth:ifとth:unlessです。属性の有無を切り替えるより、要素ごと出し分ける方が分かりやすい場面は少なくありません。条件が複雑な場合は、th:attrで詰め込むよりも、表示ロジックを小さなブロックに分割して可読性を確保します。
<a th:if="${externalDoc != null}"
th:href="@{${externalDoc}}"
rel="noopener noreferrer" target="_blank">外部ドキュメント</a>
フォームバインディングでは、th:objectとth:fieldを理解すると、入力値の反映やエラーメッセージ表示が滑らかになります。まずはth:attrで必要な属性をまとめて設定するやり方に慣れ、そのうえで入力モデルとの連携を学ぶと、テンプレート全体の見通しがさらに良くなります。
<form th:object="${account}" th:action="@{/account/save}" method="post">
<input th:field="*{displayName}"
th:attr="placeholder=${profileHelp}, aria-label=${profileHelp}" />
<button type="submit" th:attr="title='保存します'">保存</button>
</form>
以上のように、th:href、th:src、th:text、th:classappend、th:if、th:object、th:fieldなどの基礎を組み合わせることで、Thymeleaf th:attrの価値が一段と高まります。属性設定を一括化する場面と、専用属性を使って意図を明確にする場面を適切に切り替えられるようになれば、テンプレートは読みやすく、拡張しやすく、保守しやすい構成に育っていきます。学習の次のステップとしては、リストの繰り返しを行うth:eachや条件分岐のパターン化を試し、実案件の画面要件を想定した練習を重ねていくと効果的です。