Dynamic Attributes in Thymeleaf
Sometimes you need to set HTML attributes dynamically. Thymeleaf gives you several ways to do this, from simple value replacements to complex multi-valued attributes.
th:attr for Any Attribute
The th:attr attribute sets any HTML attribute dynamically. Use it when there's no specific Thymeleaf attribute for what you need.
<img th:attr="src=@{/img/product.png}, alt=${product.name}"/>
This sets both src and alt at once. The @{...} syntax handles the context path for the source.
Custom Attributes
Custom HTML attributes work the same way. Use th:attr to set them based on model data.
<div th:attr="data-user-id=${user.id}"></div>
<button th:attr="data-action=${actionUrl}">Click</button>
This generates data-user-id="42" and data-action="/api/process". JavaScript can read these with dataset.
th:altappend and Similar
Some attributes like altappend let you add to an existing value instead of replacing it.
<img src="base.png" th:altappend=" - Product Image" th:text="${product.name}"/>
The alt becomes "Base Product - Product Image". Useful for building on existing attribute values.
Try it Yourself →Multi-Valued Attributes
For attributes that accept multiple values (like CSS classes), separate them with commas in th:attr.
<div th:attr="class=${isActive} ? 'active highlighted' : 'inactive'"></div>
This conditionally sets multiple classes. You can also use th:classappend for adding classes without removing existing ones.
Practical Example: Product Card
Here's a real-world example using multiple dynamic attributes.
<div class="product-card">
<img th:attr="src=@{/images/} + ${product.image},
alt=${product.name},
data-price=${product.price}"/>
<h3 th:text="${product.name}">Product</h3>
<button th:attr="data-product-id=${product.id},
disabled=${product.stock == 0}">
Add to Cart
</button>
</div>
Each attribute pulls its value from the model. The template stays clean while the output adapts to the data.