112

By using Thymeleaf as template engine, is it possible to add/remove dynamically a CSS class to/from a simple div with the th:if clause?

Normally, I could use the conditional clause as follows:

<a href="lorem-ipsum.html" th:if="${condition}">Lorem Ipsum</a> 

We will be creating a link to the lorem ipsum page, but only if condition clause is true.

I'm looking for something different: I'd like the block to always visible, but with changeable classes according to the situation.

Shubham Dixit
  • 9,242
  • 4
  • 27
  • 46
vdenotaris
  • 13,297
  • 26
  • 81
  • 132
  • what about this one http://stackoverflow.com/questions/35530096/thymeleaf-add-to-existing-values-instead-of-replacing-them/35533872#35533872 – Robert Ellis Apr 12 '16 at 06:51

10 Answers10

289

There is also th:classappend.

<a href="" class="baseclass" th:classappend="${isAdmin} ? adminclass : userclass"></a>

If isAdmin is true, then this will result in:

<a href="" class="baseclass adminclass"></a>
nilsi
  • 10,351
  • 10
  • 67
  • 79
  • 3
    I think this should be the accepted answer. `th:class` replaces/rewrite your class attribute. `th:classappend` is what you want. – Aboodz Jan 28 '16 at 07:47
  • Alternatively you could just inject the desired class into the model from the controller, and then have `th:classappend="${theRightClass}"` – demaniak Sep 07 '17 at 14:30
  • 1
    One more thing to remember is that you unfortunately can't have multiple ```th:classappend``` attributes. Max one is allowed. ```Fatal error during parsing org.xml.sax.SAXParseException: Attribute "th:classappend" was already specified for element "img".``` – user1053510 Sep 29 '17 at 13:38
  • Is there no `th:classremove` to remove a single class without affecting the others or hard coding an entire classlist in your binding xml? Or is leaving any dynamic class off and conditionally appending the only way to go? – Drazen Bjelovuk Apr 18 '18 at 15:10
  • How to do, If need to change more than 2 classes – Sineth Lakshitha Jan 22 '20 at 10:43
  • @SinethLakshitha https://attacomsian.com/blog/thymeleaf-dynamically-add-remove-css-classes#:~:text=To%20dynamically%20add%20or%20remove%20a%20CSS%20class%20to%20an,without%20overwriting%20already%20defined%20classes.&text=In%20the%20above%20case%2C%20if,appended%20to%20the%20anchor%20tag. – S. Carr Aug 27 '20 at 23:33
37

Yes, it is possible to change a CSS class dynamically according to the situation, but not with th:if. This is done with the elvis operator.

<a href="lorem-ipsum.html" th:class="${isAdmin}? adminclass : userclass">Lorem Ipsum</a> 
riddle_me_this
  • 8,575
  • 10
  • 55
  • 80
Michiel Bijlsma
  • 583
  • 5
  • 10
  • @atilkan: You could simply google Elvis operator and see it's a variant of the Ternary operator. Even wikipedia explains it in the first few lines: https://en.wikipedia.org/wiki/Elvis_operator – Kenny Jul 31 '18 at 11:35
7

For this purpose and if i dont have boolean variable i use the following:

<li th:class="${#strings.contains(content.language,'CZ')} ? active : ''">
Fleky
  • 91
  • 1
  • 5
5

Another very similar answer is to use "equals" instead of "contains".

<li th:class="${#strings.equals(pageTitle,'How It Works')} ? active : ''">
lit
  • 450
  • 4
  • 14
5

If you just want to append a class in case of an error you can use th:errorclass="my-error-class" mentionned in the doc.

<input type="text" th:field="*{datePlanted}" class="small" th:errorclass="fieldError" />

Applied to a form field tag (input, select, textarea…), it will read the name of the field to be examined from any existing name or th:field attributes in the same tag, and then append the specified CSS class to the tag if such field has any associated errors

Stephane L
  • 2,879
  • 1
  • 34
  • 44
3

Just to add my own opinion, in case it might be useful to someone. This is what I used.

<div th:class="${request.read ? 'mdl-color-text--grey-800 w500' : ''}"> </div>
Charles
  • 251
  • 4
  • 12
3

Yet another usage of th:class, same as @NewbLeech and @Charles have posted, but simplified to maximum if there is no "else" case:

<input th:class="${#fields.hasErrors('password')} ? formFieldHasError" />

Does not include class attribute if #fields.hasErrors('password') is false.

Adrian Adamczyk
  • 3,000
  • 5
  • 25
  • 41
2

What @Nilsi mentioned is perfectly correct. However, adminclass and user class need to be wrapped in single quotes as this might fail due to Thymeleaf looking for adminClass or userclass variables which should be strings. That said,

it should be: -

 <a href="" class="baseclass" th:classappend="${isAdmin} ? 'adminclass' : 
 'userclass'"> 
 </a>

or just:

<a href="" th:class="${isAdmin} ? 'newclass' : 
  'baseclass'"> 
 </a>
N Djel Okoye
  • 950
  • 12
  • 10
1

If you are looking to add or remove class accordingly if the url contains certain params or not .This is what you can do

<a th:href="@{/admin/home}"  th:class="${#httpServletRequest.requestURI.contains('home')} ? 'nav-link active' : 'nav-link'"  >

If the url contains 'home' then active class will be added and vice versa.

Shubham Dixit
  • 9,242
  • 4
  • 27
  • 46
1

Just in case someone is using Bootstrap, I was able to add more than one class:

<a href="" class="baseclass" th:classappend="${isAdmin} ?: 'text-danger font-italic' "></a>
Charlie
  • 53
  • 6