DEV Community

Cover image for How to Convert Tailwind HTML to Structured, Semantic CSS (Without a Full Rewrite)
Eidon Ze
Eidon Ze

Posted on

How to Convert Tailwind HTML to Structured, Semantic CSS (Without a Full Rewrite)

How to Convert Tailwind HTML to Structured, Semantic CSS (Without a Full Rewrite)
I've been using Tailwind for about two years across a handful of projects. It's fast, it's predictable, and once the muscle memory kicks in you can style things without switching files.
But here's what I kept running into:
That component you built six months ago? The one with ⁠flex items-center justify-between p-4 bg-white rounded-lg shadow-md⁠ on the outer div, plus another half-dozen classes on each child element? When you come back to refactor it, you're reading styling before you're reading structure. And if you want to move that component into a project that doesn't use Tailwind — or hand it off to someone who doesn't know the utility vocabulary — you're stuck.
The tooling gap
I went looking for something that could take a chunk of Tailwind-styled HTML and give me back clean, semantic CSS. Not one-to-one class translation (there are a dozen tools that do ⁠px-4 → padding: 1rem⁠). I wanted something that understood the component structure — that a button inside a card should become ⁠.card-button⁠, not ⁠.element-4⁠.
What I found:
One-to-one converters — great if you just need to know what ⁠gap-4⁠ compiles to, but they output ⁠.element {}⁠ ⁠.div {}⁠ flat rules with no hierarchy
StyleLens (VSCode) — finds duplicate utility patterns and suggests refactoring into ⁠@apply⁠, but it's an editor workflow, not an export tool
Tailwind's own ⁠@apply⁠ — moves the problem from the HTML to the CSS file but doesn't change the naming problem
None of them did what I actually wanted: paste some HTML, get back component-level CSS with meaningful class names.
What I ended up building
Since I couldn't find it, I put together a minimal tool that does exactly that. The idea is simple:

  1. Parse the HTML tree
  2. Translate every Tailwind class to its CSS equivalent
  3. Group declarations by component (the tree structure tells you what belongs where)
  4. Name things based on what they are — semantic tags like ⁠h2⁠ become ⁠.card-title⁠, buttons become ⁠.card-button⁠, etc. Here's what it looks like in practice. Input: < img class="w-full h-48 object-cover" src="img.jpg" />

    Card Title

    Description goes here.

    Get Started Output: .card { max-width: 24rem; margin-left: auto; margin-right: auto; background-color: #ffffff; border-radius: 0.75rem; box-shadow: 0 10px 15px -3px rgba(0,0,0,0.1); overflow: hidden; }

.card-image {
width: 100%;
height: 12rem;
object-fit: cover;
}

.card-body {
padding: 1.5rem;
}

.card-title {
font-size: 1.25rem;
font-weight: 700;
color: #111827;
}

.card-description {
margin-top: 0.5rem;
color: #4b5563;
}

.card-button {
margin-top: 1rem;
padding-left: 1rem;
padding-right: 1rem;
padding-top: 0.5rem;
padding-bottom: 0.5rem;
background-color: #2563eb;
color: #ffffff;
border-radius: 0.25rem;
}

.card-button:hover {
background-color: #1d4ed8;
}

Top comments (0)