Home/Blog/hacking-into-tailwind-componentspeerlist logo
Go Back

Hacking into Tailwind components

11 Jan 2024dev, tailwind

Let's reverse-engineer the components to basic tailwind classes. This will be Tries and a lot of JS in my face.


I don’t intend to usurp the components and I am no Robinhood. On second thought, the title sounds great. However, I love unlocking safes. No more clarification!

The roadmap,

Step One: Get all HTML components

Under every category, there are several variants, and each variant is rendered inside an iframe tag. Iterate over each tag and catch the outerHTML text.

[
    "<footer class=\"aiz\" aria-...",
    "<footer class=\"alo\" aria-...",
    "<footer class=\"aiz\" aria-...",
    "<footer class=\"alo\" aria-...",
    "<footer class=\"aiz\" aria-...",
    "<footer class=\"alo\" aria-...",
    "<footer class=\"aiz\" aria-...",
    "<footer class=\"alo\" aria-...",
    "<footer class=\"alo\"><div ...",
    "<footer class=\"alo\"><div ..."
]

The CSS file was of around 14K lines. It is a lot to parse. Assumption: every component shares the same CSS build file. This can help as we don’t need to worry about different stylesheets.

For the next step, we need to load the components and style into a working environment.

Step Two: Map between CSS styles and Tailwind classes

For reference, I’ll be using the cheat sheet provided by Tailwind Components. Tailwind Components is more easily scrapable than the whole Tailwind official documentation. I managed to scrape around 3000 style rules.

Now, I can match the styles used to their corresponding Tailwind classes. Although, there is a catch. Take the example below, a single style rule can produce 6 different class names because we are not considering any context and the classes here apply the same rule under the hood.

"margin-left: 0;": [
        "mx-0",
        "ml-0",
        "-mx-0",
        "-ml-0",
        "space-x-0",
        "-space-x-0"
    ]

We can minimize collisions by using tailwind-merge when applying forged classes onto the components. The twMerge function removes conflicts, allows refinements and supports modifiers. Another problem, the last conflicting class wins rule can give preference to the last appearing class instead of the relevant one. Alas, classes need to be checked manually.

Kidding, we can pick the most relevant class name by combining the style rules used to fulfil the exact class requirements. Maybe have another class to style map.

"mx-0": [
        "margin-left: 0;",
        "margin-right: 0;"
    ]

Thus, we can create a priority queue based on occurring rules. This can help decide which class to pick.