howtocenterdiv.com — "Software engineering is more than just centering a div."
Your part renders. Tests go well. The product is happy. Then, six months later, no one wants to touch that file. That's when refactoring becomes necessary.
But not every problematic file needs to be rewritten. The real talent is knowing when to refactor and when to leave things alone.
The Real Signal: Code That Fights Back
It's not about being clean when you refactor. It's about resistance. When a codebase starts to resist change, delivery slows down, defects multiply, and onboarding takes a week.
Signal
What It Means
Priority
A bug fix needs changes in 4+ files
Logic is scattered
🔴 High
Adding a feature breaks unrelated tests
Coupling is too tight
🔴 High
The bundle size grew 40% without a feature
Dead code / bloated deps
🔴 High
You copy-paste instead of reuse
No shared abstraction
🟠 Medium
You need to read code twice
Abstraction is wrong
🟠 Medium
New devs ask "why is this here?"
Structure doesn't match intent
🟡 Low
Do you see two or more of these signals? Refactoring gives a direct return on investment.
The !important is a sign. Three layers of nesting that can't be changed in a predictable way.
✅ After — Flat + Custom Properties
css
1:root{2--nav-link-color:#3b82f6;3--nav-link-hover:#1d4ed8;4}56.nav-link{7color:var(--nav-link-color);8transition: color 150ms ease;9}1011.nav-link:hover{12color:var(--nav-link-hover);13}1415[data-theme="purple"]{16--nav-link-color:#6366f1;17--nav-link-hover:#4f46e5;18}
CSS Custom Properties — Browser Support:
Browser
Min Version
Support
Chrome
49+
✅ Full
Firefox
31+
✅ Full
Safari
9.1+
✅ Full
IE 11
—
❌ None
Use postcss-custom-properties at build time for IE11. Ship natively for everyone else.
No matter how sophisticated the selector is, a utility inside @layer utilities has lower specificity than any style that isn't layered. Tailwind comes with its own @layer setup. This is the fix if you're using !important to fight it.
Browser Support — @layer:
Browser
Min Version
Support
Chrome
99+
✅ Full
Firefox
97+
✅ Full
Safari
15.4+
✅ Full
Edge
99+
✅ Full
For earlier targets, use @csstools/postcss-cascade-layers as a polyfill.
Tailwind: The cn() Pattern
tsx
1// ❌ No conflict resolution — px-4 + px-6 both stay in the DOM2className={`px-4 py-2 ${variant ==='primary'?'bg-blue-600':'bg-zinc-100'}${className}`}34// ✅ tailwind-merge fixes conflicts — last one wins5import{ clsx,typeClassValue}from'clsx';6import{ twMerge }from'tailwind-merge';78constcn=(...inputs:ClassValue[])=>twMerge(clsx(inputs));910className={cn(11'px-4 py-2 rounded-lg font-medium text-sm',12 variant ==='primary'&&'bg-blue-600 text-white',13 variant ==='secondary'&&'bg-zinc-100 text-zinc-900',14 disabled &&'opacity-50 cursor-not-allowed',15 className
16)}
The Refactoring Checklist
Does a test suite exist? If not, write tests first.
Is this on the critical path? ← Talk to your team about it.
What does "done" mean? Define the goal: e.g. "decouple UserCard from fetch."
PR diff under 400 lines? → Larger diffs can't be properly reviewed or reverted.
Will this change a metric? Use Lighthouse CI to check CLS, LCP, and INP before and after.