avatarDr. Derek Austin 🥳

Summary

The article discusses a bug encountered when using dynamic class names with Tailwind CSS's Just-in-Time (JIT) mode, emphasizing the importance of avoiding string concatenation for class names and the need for complete class names in the HTML for PurgeCSS to work effectively.

Abstract

The author of the article, Dr. Derek Austin, highlights a common pitfall when using Tailwind CSS's JIT mode in a production environment. The bug arises from generating dynamic strings for CSS classes, which Tailwind's JIT engine cannot process correctly, leading to discrepancies between development and production environments. The article explains why using template literals or string concatenation for class names is problematic, as Tailwind's JIT mode requires complete class names to be present in the HTML for the PurgeCSS tool to detect and preserve them. The solution proposed involves using inline styles or CSS-in-JS libraries for truly dynamic styles, while also leveraging Tailwind's JIT capabilities for maintainable web development. The author emphasizes writing purgeable HTML and understanding the limitations of dynamic class generation to avoid common issues.

Opinions

  • The author is a proponent of Tailwind CSS's JIT mode, having used it in production since its introduction.
  • There is a clear recommendation against using string concatenation or template literals for dynamic class names in Tailwind CSS.
  • The author suggests that developers should use complete class names and avoid dynamic generation to ensure PurgeCSS can effectively remove unused CSS.
  • Inline styles or a combination of Tailwind with CSS-in-JS libraries are recommended for situations requiring dynamic styles.
  • The author expresses that understanding how to write purgeable HTML is crucial when using Tailwind CSS's JIT mode.
  • The article conveys that while Tailwind's JIT mode is powerful, developers must adhere to its constraints for optimal results.

The Tailwind CSS “JIT Mode” Bug That Only Happens in Production

In fairness, Adam Wathan & Steve Schoger tried to warn me about this feature of Tailwind CSS’s “Just-in-Time” engine, but I still only caught this bug by accident. Don’t make my mistake!

Photo by Jill Heyer on Unsplash

Can you spot the bug in this React .jsx code using Tailwind CSS? 🐞

View raw code as a GitHub Gist

The bug is an easy mistake to make, and it’s sneaky to detect, too.

The issue is that I’m generating dynamic strings to use for my CSS classes, and that is going to break Tailwind, for reasons I’ll explain shortly.

Plus, if I have another h-5 or w-5 somewhere in my local hot reloading cache, then I might see different behavior in production vs. development.

Here’s what that would look like using social SVG icons taken from SimpleIcons.org, a free repository of brand logos in SVG format:

Production (left) vs. Development when using string concatenation for dynamic “Just-in-Time” (JIT) mode variables with Tailwind CSS

In the code example, I needed to use "h-5 w-5" to specify the width and height, not the dynamic `h-${size} w-${size}` that I tried.

It also won’t work with Tailwind’s awesome “Just-in-Time” (JIT) mode, which allows arbitrary values: h-[1.25rem] w-[1.25rem] will work.

But the alternative, `h-[${size} rem] w-[${size} rem]`, which seems smarter and better, just won’t work with the JIT engine.

Photo by Dustin Humes on Unsplash

What is Tailwind’s Justin Timberlake (JIT) mode?

I’m a big fan of JIT mode and have been using it in production since Adam and Steve introduced it back in March 2021.

“[The] new just-in-time [JIT] compiler for Tailwind CSS […] generates your styles on-demand as you author your templates instead of generating everything in advance at initial build time.”

— Tailwind CSS Docs for “Just-in-Time” Mode

There is a pretty obvious “catch” in the docs, though, and it’s the bug that we looked at before. We need to use the e>? question mark operator.

“❌Don’t use string concatenation to create class names

✅ Do dynamically select a complete class name”

— Tailwind CSS Docs for “Just-in-Time” Mode

In the bug we looked at before, the template literals using `${var}` for variable interpretation were the issue.

These “fancy strings” are also called `` backtick literals in JavaScript, but they won’t work for the on-demand styles we want.

Let’s look at a code example of a React function component to see what this looks like, and why you can’t use string concatenation.

View the raw code as a GitHub Gist
Photo by Charlotte Descamps on Unsplash

Why this happens with Tailwind CSS JIT

Tailwind isn’t JavaScript and doesn’t run anything, so the magic is happening with this regular expression: /[^<>"'`\s]*[^<>"'`\s:]/g.

“Tailwind doesn’t include any sort of client-side runtime, so class names need to be statically extractable at build-time, and can’t depend on any sort of arbitrary dynamic values that change on the client.” — ibid

To put it another way, the Tailwind parser is really dumb (or should I say, genius?) in how it processes files looking for class names.

That means that lovely template literals, while fun and fancy, are not entirely welcome at Tailwind’s retro-modern web development party.

Photo by Kris Mikael Krister on Unsplash

So what’s the solution for dynamic Tailwind CSS?

If you need a truly dynamic value as a CSS style, it’s not actually super clear how to leverage Tailwind’s JIT mode.

But if you’re thinking that way about how to set a dynamic background color in a React app using Tailwind, you’re forgetting something.

“Use inline styles for these situations, or combine Tailwind with a CSS-in-JS library like Emotion if it makes sense for your project.” — ibid

Right, so you could just use an inline style in React for the dynamic value. Of course, the React docs literally say that classes are better, but hey.

With Tailwind, you get the best of both worlds, and that is helping me develop websites that are easier than ever to maintain. JIT’s fantastic.

Photo by Justin Lauria on Unsplash

What else you should know (Purge CSS)

PurgeCSS, everyone’s favorite tool to remove unused CSS, is sort of where the magic happens with Tailwind, under the hood.

So when you’re using the JIT engine, it’s even more important that PurgeCSS can process your .html, .jsx, .tsx, etc. file correctly.

“You still need to write purgeable HTML when using arbitrary values, and your classes need to exist as complete strings for Tailwind to detect them correctly.” — ibid

PurgeCSS is the reason that it’s important to avoid creating dynamic class strings in your templates with concatenation.

If you’re doing “string arithmetic” with the e>+ operator or template literals, then PurgeCSS won’t know to preserve those CSS classes.

Screenshot of the Tailwind CSS Docs by the author, Dr. Derek Austin 🥳

That last bit bears repeating, “As long as a class name appears in your template in its entirety, PurgeCSS will not remove it.”

I hope this article has helped you understand an important rule for “Just-in-Time” Tailwind CSS: Be careful what you concatenate.

And, when in doubt, just write out the entire JIT class exactly how you want it, inside your personal Prettier preference: double or single quotes.

Happy coding! 🎉🛂🥨🚧🏗🎊🧂😵🚧🏗🍾

Photo by Janice Gill on Unsplash

Dr. Derek Austin is the author of Career Programming: How You Can Become a Successful 6-Figure Programmer in 6 Months, now available on Amazon.

JavaScript
Visual Design
UX
Software Engineering
Programming
Recommended from ReadMedium