DEV Community

Jack H. Peterson
Jack H. Peterson

Posted on

Secretly Tailwindcss


I love tailwind, but using it at work is an idea I've been unable to sell. There are a bunch of reasons to love utility css which I won't cover here.

Here I'm just showing how to USE tailwind and converting it into more familiar css pretty easily.

Today, I'll just cover what our system is at work, and how to I use tailwind within it, without conflicting with a non-tailwind codebase.

Constraints at work

ZERO command line build steps.

We only use sass compiled with codekit. Many devs don't have node on their PATH.

$ node -v
> node: command not found
Enter fullscreen mode Exit fullscreen mode

SASS Nested CSS Codebase.

We build components which are namespaced via SASS nesting.

.component {
    .card {...}
    .title {...}
    .button {...}
/* Which compiles to: */
.component .card {...}
.component .title {...}
.component .button {...}
Enter fullscreen mode Exit fullscreen mode

The Stack

Server rendered html via twig and jQuery. Bringing in anything like react, vue, lit-html, simply isn't done. Most pages should work without any javascript or a build step.

ie11 compat matters.

Several things in tailwindcss v2 won't work in ie. So I gotta test in ie11, and patch as needed. Tailwind doesn't support ie11, so this would be a constraint regardless.



Twind is a JS module which is an in browser compiler for tailwind. Write tailwind classes like you normally would, and Twind will only generate the needed styles.

Your Browser Inspector and Code Editor of Choice

I'm using Firefox and vsCode, but this should work with any decent browser and editor.

The Process

This works best if you work one section/component at a time.

1) Split tailwind classes from normal classes.

Move tailwind classes from the class attribute to the tw attribute. (You could name it whatever you want, I'm just using tw here.)

2) Generate the CSS.

Drop this script into your html.

<script type="module">
  // Import the needed Modules
  import { tw, apply } from "";
  import { domSheet } from "";

  // find all of the classes with the tw classes.
  [...document.querySelectorAll("[tw]")].forEach((el) => {

    // get the string of tailwind classes
    const listOfClasses = el.getAttribute("tw");

    // @apply the tailwind utils on 1 class, 
    // rather than into several util classes.
    const bundledClass = apply`${listOfClasses}`;

    // this will append the class to the <head>
    const generatedClass = tw`${bundledClass}`;

    // this will add the class to the element
    // which will apply the expected styles
    // the styles were initally removed when 
    // you moved the tw classes to the tw attribute 
Enter fullscreen mode Exit fullscreen mode

3) Move the Generated HTML into your Code.

Copy the outerHTML from your component and generated style tag (at the bottom of your <head>) from your browser and into your template. The class names are random characters. Don't worry about this, we'll fix it later.

4) Add the Generated classes to your Code.

This is the most confusing part to explain, but vscode and other editors have nice find and replace features. Essentially you want to find all of the new classes AND their order in the HTML and paste them into your template HTML elements in the same order. If you know the right shortcuts this can be pretty painless. If your component template isn't using if/for/etc, you can do this in about 10 seconds with a combination of CMD + D, Shift, Alt, and your arrow keys. I'll make a video of this if someone is interested.

5) Remove the Browser HTML.

You can delete the component HTML you pulled from the browser, we just needed that to have all of the generated classes in order for step 4.

6) Rename Your Classes.

Technically, your template code works right now! But folks will think you're a bit wacky if your CSS class names are .tw-dgt4fd. So we'll find and replace all instances of those wacky class names with more sensible class names. My process for doing that: Highlight a generated class in your html Cmd + Shift + L (It'll select all instances of that text.) From there, I'll rename the class while I'm looking at the HTML structure.

7) Clean up the CSS.

At this point, I'll drop a component namespace class in the HTML and then namespace the CSS with nesting. Some media queries can be redundant across the generated classes, but merging them is simple enough.

7) Set up Templates for Production. (optional)

I have a variable I can reference in twig to see if the site is being rendered for Production or Development. I'll just slip the tw classes into something like:

    class="component button"
    {{ dev ? 'tw="w-32 h-10"' }} 
Enter fullscreen mode Exit fullscreen mode

That won't render the tw attribute unless you're on dev. Which means your code won't have excess attributes. I also apply the same principle for the script I included above. No no need to include it in prod.
Super optionally, I have a component level variable which can prevent the tw attributes from rendering for that component.

You're Done!

That's basically it. A little more testing on ie, maybe you need to move the style tag into a SASS partital, but all of those steps will vary from task to task.


Your tailwind classes are preserved which means you can easily go back to using tailwind when you're back on the project. Meanwhile, tailwind isn't being used on the site publicly at all! The only traces of tailwind are the tw attributes, and a script tag that will only appear on dev.


This post outlined a good compromise between being highly effective using tailwind and working in a code-base that isn't friendly with tailwind. DM me on twitter if you need any help getting this set up or have any questions.

Top comments (0)