Dynamic TailwindCSS in Production

Dynamic TailwindCSS in Production

Doing it right and making it fun!

"It’s tiny in production. Tailwind automatically removes all unused CSS when building for production, which means your final CSS bundle is the smallest it could possibly be. In fact, most Tailwind projects ship less than 10KB of CSS to the client."

Right there, is one of the greatest advantages of using TailwindCSS for styling any web project/application. As outlined by its creator Adam Wathan , TailwindCSS is programmed to trim down on the bulk of the entire package to only the style classes and utilities only necessary for your application.

What the Heck is TailwindCSS???

Question beginners ask! According to its creator, Tailwind is a utility-first CSS framework.

In contrast to other CSS frameworks like Bootstrap or Materialize CSS it doesn’t come with predefined components. Instead Tailwind CSS operates on a lower level and provides you with a set of CSS helper classes. By using this classes you can rapidly create custom design with ease. Tailwind CSS is not opinionated and let’s you create you own unique design. Sebastian Eschweiler

If you are a complete beginner to this, you should definitely check out Sebastian's post on Tailwind CSS For Absolute Beginners

As good as the whole TailwindCSS concept might sounds, never forget there is always a unique problem for almost every solution created. In my experience as a web developer, I have had to deal with simple things as trying to figure out why a CSS class style isn't working as expected and would sometimes wonder if the stylesheet isn't properly included in the html template but then, I have come to discover that most of those problems stem from refusal to go through documentation for the things one wishes to use. Hell yeah! that's right...we devs could sometimes be a pain in our own souls.

As annoying as this might sound, trust me I agree with you. Some framework documentation could be a pain but a little glimpse would in most cases reduce the self inflicted pain you bring yourself. You gotta try...it takes discipline and you've gotta build it.

In this post, I want to point out one way TailwindCSS could mess you up if you have never read its homepage...not even the long energy draining documentation as you would feel. On the side, TailwindCSS has one of the best documentations ever written. You can trust me on that.

How Does Tailwind Know What to Keep and What to Get Rid Of During Production Build???

Tree Shaking! Yes, that's the best term for what TailwindCSS does to your project when you are building for production. According to MDN Web Docs, Tree shaking is a term commonly used within a JavaScript context to describe the removal of dead code.

Next point we are looking at is the word "Dead Code". How is it dead??? Well, to put it simply, TailwindCSS ships with its full load on installation and that is about 4MB of CSS styles. During your coding process, you specify the classes you need in your HTML template as required by TailwindCSS and everything works fine as long as you are fetching the styles from the main source of installation but during production build, TailwindCSS, using the tree shaking technique to run through your HTML template, checking against a predefined regular expression(regex) to pick up only the classes it finds in your HTML template.

/[^<>"'`\s]*[^<>"'`\s:]/g

Source: TailwindCSS Docs

This means all set of classes not found in your HTML template, but available in your installation package, is "Dead Code" and TailwindCSS ignores them while building. This is very good practice and this is why your production build size reduces to about 10KB - 15KB of stylesheet classes depending on the amount of different classes used in your project.

This brings us to the topic of dynamic usage of TailwindCSS and its problems.

Dynamic TailwindCSS

As we know, dynamically setting styles in web projects is inevitable. I personally am a fan of that. However, it is very important to note that TailwindCSS advises against this practice and at the same time, TailwindCSS advises on how to use dynamic classes if one must do so.

Of course I trust by now you know why this is a thing of concern but if you don't, well, here it is. Dynamic classes are in some cases not part of the HTML element class attribute in your template and when TailwindCSS is performing its tree shaking, it doesn't find them and so they are not included in production build even when you intend to use them in your project.

Let's look at some examples.

TailwindCSS 1.png Source: TailwindCSS Docs

In the first code block, the developer wants a class of text-red-600 if error is true and text-green-600 if error is not true. When tree shaking happens, TailwindCSS will not build with these two classes because it fails the regex predefined by TailwindCSS due to string concatenation.

In the second block of code, the classes are properly specified and will be picked up by TailwindCSS during build.

This example is simple and straightforward but what if I wanted to have a background gradient colour change for different pages of my app.

Let's say I have a VueJs app and on the index page, I want a gradient flow of blue down to transparent and red down to transparent on the contact page. I would need to have this class

<div class="bg-gradient-to-b from-blue-600 to-transparent">

but this is not dynamic if injected into my App.vue file which is the main entry point for all pages/components.

To have it dynamically done, I might want to use the code below in my HTML template where pageThemeColor is a prop received from each page/component's router props.

<div :class="addThemeGradientColor" class="bg-gradient-to-b to-transparent">
...
props: ['pageThemeColor']
...

The :class="addThemeGradientColor" section binds the dynamic class name to the already hard coded CSS classes defined by the HTML class attribute.

The index route would send in a pageThemeColor prop value of blue and contact route would send in a prop value of red thus

...
const routes = [
  {
    path: "/",
    name: "Index",
    component: Index,
    props: {
      color: 'blue'
    }
  },
  {
    path: "/contact",
    name: "Contact",
    component: Contact,
    props: {
      color: 'red'
    }
  },
  ]
...

and for each routes, the HTML templates would look like this.

<!-- Index component -->
<div class="bg-gradient-to-b from-blue-600 to-transparent">
<!-- Contact component -->
<div class="bg-gradient-to-b from-red-600 to-transparent">

The code snippet below would definitely help me deal with the dynamic application of the gradient colours as needed.

 <div :class="addThemeGradientColor" class="flex flex-col justify-between relative w-full pt-28 lg:pt-48 bg-gradient-to-b to-transparent h-full">
        <div class="relative w-full px-4 md:px-16 lg:px-32">
          <router-view @setColor="setColor"></router-view>
...
computed: {
      addThemeGradientColor() {
        return this.color ? `from-${this.color}-600` : ''
      }
    },
    props: {
      pageThemeColor: String,
    },
    data() {
      return {
        color: null
      }
    },
...

If you are new to VueJs, well you are new to the fun it has. Follow the blue coloured text to more fun from VueJs

However, during production build, TailwindCSS will not be able to detect the following classes from-blue-600 and from-red-600 which are required by my app to render the background gradient completely because they are not specified in the HTML template but are rather returned as computed properties.

How do We Fix This???

It is important to note that I mentioned reading documentations at the beginning of this post. It is because if one should find his/herself having a production build where these colours are not reflected, without proper knowledge of why that is, one would possible find his/herself sweating on this, but with proper knowledge, one can just fix this in a jiffy.

One way this could be fixed is to have a hidden HTML element where you specify the classes for which you know your project will require. Yes! That's it. I know what you might be thinking...it's damn old but trust me, the good old way helps a to reduce lots of stress.

However, as much as I want to help out novices with this post, I am open to learning something new and sophisticated as well, so if you are well equipped with a better knowledge of how to fix this, the comment section is your plug.

Solution code

<!-- Supplying range of theme colours to be generated by TailwindCSS during production build -->
<!-- Background Gradient Colours -->
<span class="hidden from-red-100 from-red-200 from-red-300 from-red-400 from-red-500 from-red-600 from-red-700 from-red-800 from-red-900"></span>
<span class="hidden from-green-100 from-green-200 from-green-300 from-green-400 from-green-500 from-green-600 from-green-700 from-green-800 from-green-900"></span>
<span class="hidden from-blue-100 from-blue-200 from-blue-300 from-blue-400 from-blue-500 from-blue-600 from-blue-700 from-blue-800 from-blue-900"></span>
<span class="hidden from-pink-100 from-pink-200 from-pink-300 from-pink-400 from-pink-500 from-pink-600 from-pink-700 from-pink-800 from-pink-900"></span>

In the block above, I have used hidden span elements to specify the background gradient classes I will need in my project and this classes will be included during production build such that they can be accessible in the production environment when TailwindCSS is done tree shaking.

Conclusion

In your experience with TailwindCSS, you may or may have not had to use dynamic classes and may or may not have had the experience of trying to sought this out. If you have had this experience before now, I believe this post will clear out your understanding of why you went through that and if not, then you are lucky not to be in such a "frustrating loop" of dynamic styling using Tailwind. Most importantly, this kind of experience may not only apply to TailwindCSS or styling as a whole but can be applicable to other web or other software infrastructures, therefore the need to always have a look at documentation of frameworks, libraries or any tool you might want to use in your development career. This is best practice.

Thank you for reading this far. I appreciate.

If you found this content educative and helpful, do not forget to share the help with a friend. Hit the follow button for more educative and helpful content. A thumbs up would as well make me blush!

Buy Me A Coffee