Letting AI refactor one legacy stylesheet

I pointed an AI model at a 1,200-line legacy Sass file and asked it to refactor everything to Tailwind. The useful part was mechanical syntax cleanup. The risky part was everything that depended on design, layout, and accessibility intent.
Letting AI refactor one legacy stylesheet

The patient: one legacy Sass file

The target was a legacy client CSS file: about 1,200 lines of hand-written Sass from before Tailwind was standard at Ideebv. It defined 47 component classes, 12 utility classes that duplicated Tailwind defaults, and a section of commented-out gradients from a 2021 rebrand.

I fed the whole thing to Claude with a single prompt:

“Refactor this to Tailwind v3 utility classes where possible, preserve the custom properties, and flag anything that looks dead.”

What came back was a neatly formatted diff that looked reasonable at first glance. The real work started after that, going line by line and deciding what to accept, what to change, and what to reject.

The audit took 45 minutes: about 20 minutes to get a usable diff, and 25 minutes to verify the context and consequences. The file ended up cleaner. The interesting part is how that happened.

What I accepted: mechanical spacing refactors

The safest chunk was spacing. The original Sass was full of declarations like:

.card {
  margin-top: 24px;
  padding: 0 16px;
}

Claude systematically mapped these to Tailwind utilities:

  • margin-top: 24px; became mt-6
  • padding: 0 16px; became px-4

It also correctly identified that the client’s spacing scale was already on a 4 px base, so 4 px increments lined up with Tailwind’s default spacing scale. In total it caught 89 instances that were exact, lossless translations from raw values to Tailwind classes.

I accepted these without modification. They were pure syntax transformations: no layout changes, no semantic changes, no new assumptions about the design system. Just shorter, more consistent code.

What I changed: color mappings without project context

Colors were where “looks right” and “is right” diverged.

The original Sass used custom properties like:

I wrote about this earlier in Why I Prototype Motion Before Polishing Layout.

.btn-primary {
  color: var(--brand-primary);
  background-color: var(--brand-primary);
}

Claude suggested converting these to Tailwind’s default color utilities:

  • color: var(--brand-primary);text-blue-600
  • background-color: var(--brand-primary);bg-blue-600

The pattern was sane: replace custom color declarations with semantic Tailwind classes. The problem was the data behind it. This project has a custom tailwind.config.js that maps a brand color token to a specific hex value that is not Tailwind’s default blue.

The AI had no access to that config. It guessed. The guess was wrong.

I kept the structural idea but changed the actual classes to:

  • text-brand instead of text-blue-600
  • bg-brand instead of bg-blue-600

So the refactor went in two steps:

  1. Let AI propose a mapping pattern from custom properties to Tailwind utilities.
  2. Replace the guessed tokens with the project’s real design tokens.

On paper that looks like a small edit. In practice this is the line between “AI refactored my CSS” and “AI suggested a template, and I refactored my CSS using it.” The syntax was automated. The semantics still came from the project’s existing design system.

What I rejected: grid architecture changes

One component used a CSS Grid setup with subgrid for alignment. The idea was that nested cards should align their internal rows across columns, so when content varied in length, the visual grid still lined up. The key line was:

grid-template-rows: subgrid;

Tailwind does not yet support subgrid natively, and Claude did not recognise why it was there. It proposed replacing the whole grid with a simpler layout:

  • grid-cols-4 for the outer grid
  • A flex-based workaround for the inner layout, with fixed heights to “stabilise” rows

On real content, that would have broken as soon as one card had longer text than the others. The entire point of the original subgrid setup was to avoid exactly that failure mode.

More on this in my article Why I Still Test In Safari First (And The Bugs It Catches Early).

I rejected the suggestion and kept the original CSS grid declaration. I also added a comment to make the constraint explicit:

/* Using subgrid to align card rows across columns.
   Tailwind does not support this yet; do not replace with grid-cols-* or flex.
*/

This was the first place where the cost of verification showed up clearly. The AI could rewrite the layout syntax, but it could not see the layout behaviour or the design intent. It saw an opportunity to use Tailwind utilities; it did not see the trade-off it was making.

What I rejected: “unnecessary” pseudo-elements

The file also contained ::before pseudo-elements used for decorative-looking borders. Claude flagged them as “likely unnecessary visual noise” and suggested removing them to simplify the CSS.

What was not in the file was the reason they existed. Those pseudo-elements were part of a specific accessibility requirement for the client’s WCAG 2.2 compliance audit. They provided a visible focus indicator for keyboard navigation. No pseudo-element, no visible focus ring. No visible focus ring, no compliance.

The AI saw CSS. It did not see the legal and accessibility constraints behind it.

I rejected the removal and added another explicit comment:

/* ::before used for WCAG 2.2 focus indicator.
   Required for accessibility audit. Do not remove.
*/

This is where a “helpful cleanup” could have turned into an expensive regression. Not because the model was malicious, but because it had no way to know which parts of the file were bound to requirements that lived in tickets, audits and contracts, not in code.

Read also CSS Custom Properties For Responsive Biohacking Dashboards.

The time balance

On paper, the numbers looked like this:

  • 45 minutes total for the audit
  • 20 minutes to generate and massage the diff into something usable
  • 25 minutes to verify context and decide on three architectural calls

The AI saved me the manual typing of 89 Tailwind spacing replacements. It also tried to “help” with three structural changes: color tokens, grid layout, and focus indicators. All three needed correction or rejection because they depended on project context the model could not see.

The net result was a cleaner file, fewer one-off spacing declarations, and a bit more documentation around the tricky bits. That was not AI magically refactoring a legacy stylesheet.

AI refactored CSS syntax. A human still had to refactor CSS meaning.

Subscribe to my newsletter

Subscribe to my newsletter to get the latest updates and news

Member discussion