8

In a sentence: Why does calculations with JS variables does not apply any style using TailwindCSS v3?

I am using VueJS for my project, and this example works as expected as it simply applies calc as string:

...
<div class="w-[calc((100%-12rem)*2/3)]">
...

While this doesn't (there are JS variables involved):

...
<div :class="`w-[calc(${props.languages.length * 1.25 + 3}rem)]`">
...

When I inspect the console, I can see HTML with the correct class:

...
<div class="flex w-[calc(14.25rem)]"
...

... but styles are not applied. Any ideas? What am I doing wrong? I think this is a very powerful feature as it lets you dynamically style your HTML based on underlying data, but I can't make it work although I think am so close.

Thanks in advance.

6
  • 1
    I'm not sure, but if you're doing the calculation in JavaScript wouldn't it be "easier" to simply use class=`flex w-[${calculation-result}]`, leading to - from your example - class=`flex w-[14.25rem]`(edited after checking the docs). Commented Sep 4, 2023 at 11:39
  • Thanks @DavidThomas, I am using VueJS and have to prepend : to the class attribute for Vue to consider it as a "JS string". But I am basically doing what you suggest. Commented Sep 4, 2023 at 11:49
  • Fair enough, I admit that I didn't even notice the prepended : character; given your comment I'm rather glad that I didn't, since I'd probably have raised that as an issue (not knowing that Vue was in use). I have added the vue.js to the question so others are more aware, feel free to edit it back out though. Commented Sep 4, 2023 at 11:51
  • 1
    Just edited the question to add the VueJS dependency. Commented Sep 4, 2023 at 11:54
  • Yes, just wrote an answer with my own research and results. Thanks anyway! Commented Sep 4, 2023 at 12:20

2 Answers 2

7

Do this instead:

<script src="https://cdn.tailwindcss.com"></script>

<div id="el" class="w-[calc(var(--languages-length)_*_1.25rem_+_3rem)] h-10 bg-red-300"></div>

<script>
el.style.setProperty('--languages-length', 6);
</script>

Equivalent in Vue:

<div 
 class="w-[calc(var(--languages-length)_*_1.25rem_+_3rem)] h-10 bg-red-300" 
 :style="{ '--languages-length': props.languages.length }"
></div>
Sign up to request clarification or add additional context in comments.

Comments

4

I finally found the cause: Tailwind's JIT, which is enabled and working by default in TailwindCSS v3.

Here is the interesting part: they say not to construct class names dynamically, which is precisely what I was trying to do.

So I finally followed their recommendation (see this very useful v2 docs link) and bypassed Tailwind for one time, directly using a style attribute to set the width of my element like this:

<div :style="`width: ${props.languages.length * 1.25 + 3}rem;`">

Thanks anyway ;)

2 Comments

@dogukan's answer is much better. It builds a dynamic class, but it uses CSS variables, so the Tailwind CSS compiled code will reference the CSS variable. You can also manipulate the CSS variable at runtime with JavaScript, and the class will not change.
However, what you've shared is useful. The problem with dynamically declared class names using JS variables is that, during native CSS compilation, the variable's value is unknown, which can be practically anything. Therefore, using JS variables in dynamic class names, as you mentioned, is incorrect and should not be followed. Great research work!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.