1. Overview

In this quick tutorial, we’ll learn a few different ways to conditionally add CSS classes in Thymeleaf.

If you are unfamiliar with Thymeleaf, we recommend checking our introduction to it.

2. Using th:if

Let’s assume that our goal is to generate a whose classes are determined by the server:

<span class="base condition-true">
   I have two classes: "base" and either "condition-true" or "condition-false" depending on a server-side condition.
</span>

Before this HTML is served, we need a good way for the server to evaluate a condition and either include the condition-true class or the condition-false class, as well as a base class.

When templating HTML, it’s quite common to need to add some conditional logic for dynamic behavior.

First, let’s use th:if to demonstrate the simplest form of conditional logic:

<span th:if="${condition}" class="base condition-true">
   This HTML is duplicated. We probably want a better solution.
</span>
<span th:if="${!condition}" class="base condition-false">
   This HTML is duplicated. We probably want a better solution.
</span>

We can see here that this will logically result in the correct CSS class being attached to our HTML element, but this solution violates the DRY principle because it requires duplicating the entire block of code.

Using th:if can certainly be useful in some cases, but we should look for another way to dynamically append a CSS class.

3. Using th:attr

Thymeleaf offers us an attribute that will let us define other attributes, called th:attr.

Let’s use it to solve our problem:

<span th:attr="class=${condition ? 'base condition-true' : 'base condition-false'}">
   This HTML is consolidated, which is good, but the Thymeleaf attribute still has some redundancy in it.
</span>

You may have noticed that the base class is still duplicated. Also, there is a more specific Thymeleaf attribute we can use when defining classes.

4. Using th:class

The th:class attribute is a shortcut for th:attr=”class=…” so let’s use it instead, along with separating the base class out of the condition result:

<span th:class="'base '+${condition ? 'condition-true' : 'condition-false'}">
   The base CSS class still has to be appended with String concatenation. We can do a little bit better.
</span>

This solution is pretty good because it meets our needs and is DRY. However, there is still yet another Thymeleaf attribute that we can benefit from.

5. Using th:classappend

Wouldn’t it be nice to completely decouple our base class from the conditional logic? We can statically define our base class and reduce the conditional logic to only the relevant pieces:

<span class="base" th:classappend="${condition ? 'condition-true' : 'condition-false'}">
   This HTML is consolidated, and the conditional class is appended separately from the static base class.
</span>

6. Conclusion

With each iteration of our Thymeleaf code, we learned about a useful conditional technique that might come in handy later. Ultimately, we found that using th:classappend provides us with the best combination of DRY code and separation of concern while also satisfying our goal.

All of these examples can be seen in a working Thymeleaf project available over on GitHub.