CSS Development: Refactor
Overview
Transforms existing CSS into semantic component patterns:
- •Extract inline styles to semantic classes
- •Consolidate utility classes from markup into
@applycompositions - •Add dark mode variants
- •Add test coverage
- •Preserve existing functionality (behavior-neutral refactoring)
This is a sub-skill of css-development - typically invoked automatically via the main skill.
When This Skill Applies
Use when:
- •Converting inline styles to semantic classes
- •Extracting repeated utility combinations from markup
- •Migrating from pure utility-first to semantic components
- •Adding dark mode to existing CSS
- •Cleaning up scattered or duplicated CSS
Pattern Reference
This skill refactors toward patterns documented in the main css-development skill:
Semantic naming: .button-primary not .btn-blue
Tailwind composition: Use @apply to compose utilities
Dark mode: Include dark: variants
Composition first: Reuse existing classes before creating new
Test coverage: Static CSS + component rendering tests
Workflow
When this skill is invoked, create a TodoWrite checklist and refactor systematically.
Announce Usage
"I'm using the css-development:refactor skill to transform this CSS into semantic component patterns."
Create TodoWrite Checklist
Use the TodoWrite tool:
Refactoring CSS: - [ ] Analyze existing CSS (identify what needs refactoring) - [ ] Find repeated patterns (look for duplicated utility combinations) - [ ] Check existing components (see if patterns already exist) - [ ] Extract to semantic classes (create new classes using @apply) - [ ] Include dark mode (add dark: variants to new classes) - [ ] Update markup (replace inline/utility classes with semantic names) - [ ] Add tests (write static CSS and rendering tests) - [ ] Document components (add usage comments) - [ ] Verify behavior unchanged (ensure visual output matches original)
Refactoring Checklist Details
Step 1: Analyze Existing CSS
Action: Read and understand the CSS that needs refactoring
Look for:
- •Inline styles in component files
- •Repeated utility class combinations in markup
- •CSS scattered across multiple files
- •Missing dark mode support
- •Lack of semantic class names
Example patterns to refactor:
// Inline styles
<button style={{ background: 'indigo', padding: '1.5rem 2rem' }}>Click</button>
// Repeated utilities in markup
<button class="bg-indigo-500 hover:bg-indigo-700 px-6 py-3 rounded-lg text-white">
Click me
</button>
<button class="bg-indigo-500 hover:bg-indigo-700 px-6 py-3 rounded-lg text-white">
Submit
</button>
// Non-semantic CSS
.btn-blue {
background: blue;
padding: 12px 24px;
}
Capture:
- •File locations
- •Pattern frequency (how many times repeated)
- •Current approach (inline, utilities, old CSS)
Mark as completed when analysis is done.
Step 2: Find Repeated Patterns
Action: Identify duplicated utility combinations that should become semantic classes
Use Grep tool to search for repeated patterns:
# Search for common utility combinations grep -r "bg-indigo-500 hover:bg-indigo-700 px-6 py-3" . grep -r "rounded-lg shadow-md p-6" .
Categorize patterns:
- •High frequency (5+ occurrences): Definitely extract
- •Medium frequency (2-4 occurrences): Probably extract
- •Low frequency (1 occurrence): Keep as-is or compose existing classes
For each pattern:
- •Count occurrences
- •List file locations
- •Identify semantic purpose (is this a button? card? badge?)
Mark as completed when patterns are cataloged.
Step 3: Check Existing Components
Action: Read styles/components.css to see if patterns already exist
Before creating new classes, check:
- •Does a similar class already exist?
- •Can existing classes be composed?
- •Would a variant of an existing class work?
Example:
Pattern found: bg-indigo-500 hover:bg-indigo-700 px-6 py-3 rounded-lg text-white Check: Does .button-primary already exist? YES Solution: Use .button-primary instead of creating new class
Decision for each pattern:
- •✅ Use existing class as-is
- •✅ Compose existing classes
- •✅ Create variant of existing class
- •⚠️ Create new class (only if no existing solution)
Mark as completed when reuse opportunities are identified.
Step 4: Extract to Semantic Classes
Action: Create new semantic classes in styles/components.css for patterns that need extraction
For each pattern being extracted:
- •Choose semantic name following existing patterns
- •Write CSS class using
@apply - •Include dark mode variants
- •Add documentation comment
Example extraction:
Before (in markup):
<button class="bg-indigo-500 hover:bg-indigo-700 px-6 py-3 rounded-lg text-white transition-all duration-200"> Click me </button>
After (in components.css):
/* Primary button - Main call-to-action button with hover states
Usage: <button className="button-primary">Click me</button> */
.button-primary {
@apply bg-indigo-500 hover:bg-indigo-700 dark:bg-indigo-600 dark:hover:bg-indigo-800;
@apply px-6 py-3 rounded-lg text-white;
@apply transition-all duration-200;
}
Use Edit tool to add each new class to components.css
Mark as completed when all semantic classes are created.
Step 5: Include Dark Mode
Action: Ensure all new/refactored classes have dark: variants
For each class created in Step 4:
- •Add
dark:variants for backgrounds - •Add
dark:variants for text colors - •Add
dark:variants for borders - •Test in dark mode (if possible)
Pattern:
.component {
@apply bg-white dark:bg-gray-800;
@apply text-gray-900 dark:text-white;
@apply border-gray-200 dark:border-gray-700;
}
Mark as completed when dark mode coverage is added.
Step 6: Update Markup
Action: Replace inline styles and utility classes with semantic class names
For each file using the old pattern:
- •Read the file with Read tool
- •Use Edit tool to replace old pattern with semantic class
- •Verify the replacement is correct
Example:
Before:
<button class="bg-indigo-500 hover:bg-indigo-700 px-6 py-3 rounded-lg text-white"> Click me </button>
After:
<button class="button-primary"> Click me </button>
Handle custom classes:
<!-- If there were additional custom classes, preserve them --> <button class="button-primary w-full mt-4"> Click me </button>
Track changes:
- •Count files updated
- •Count instances replaced
- •Note any edge cases
Mark as completed when all markup is updated.
Step 7: Add Tests
Action: Add test coverage for refactored components
Static CSS test in styles/__tests__/components.test.ts:
it('should have button-primary class', () => {
const content = readFileSync('styles/components.css', 'utf-8');
expect(content).toContain('.button-primary');
});
it('should have dark mode variants in button-primary', () => {
const content = readFileSync('styles/components.css', 'utf-8');
expect(content).toContain('dark:bg-indigo');
});
Component rendering test (if applicable):
it('applies button-primary class after refactor', () => {
render(<Button variant="primary">Click</Button>);
expect(screen.getByRole('button')).toHaveClass('button-primary');
});
Run tests to ensure they pass:
npm test
Mark as completed when tests are added and passing.
Step 8: Document Components
Action: Ensure all refactored classes have documentation
Documentation includes:
- •Comment in CSS explaining purpose
- •Usage example
- •Migration notes (if helpful)
Example:
/* Primary button - Main CTA button (refactored from inline utilities)
Usage: <button className="button-primary">Click me</button>
Replaces: bg-indigo-500 hover:bg-indigo-700 px-6 py-3 rounded-lg text-white */
.button-primary {
@apply bg-indigo-500 hover:bg-indigo-700 dark:bg-indigo-600 dark:hover:bg-indigo-800;
@apply px-6 py-3 rounded-lg text-white;
@apply transition-all duration-200;
}
Mark as completed when documentation is added.
Step 9: Verify Behavior Unchanged
Action: Ensure visual output and behavior match the original
Verification steps:
- •
Run tests (if project has them):
bashnpm test
- •
Visual inspection (if possible):
- •Start dev server
- •Check refactored components look the same
- •Test in light and dark mode
- •Test interactive states (hover, focus, active)
- •
Check for regressions:
- •Compare before/after screenshots (if available)
- •Verify no console errors
- •Check responsive behavior
If behavior changed:
- •Identify the difference
- •Fix the semantic class to match original behavior
- •Re-test
Behavior must be preserved - refactoring should be visually neutral
Mark as completed when behavior is verified unchanged.
Completion
When all checklist items are completed:
- •Generate summary of refactoring work:
## CSS Refactoring Summary ### Changes Made **Semantic classes created:** - `.button-primary` (extracted from 8 instances across 5 files) - `.card` (extracted from 12 instances across 7 files) - `.badge-success` (extracted from 4 instances across 3 files) **Files modified:** - `styles/components.css` (+45 lines, 3 new classes) - `components/Button.tsx` (replaced utilities with .button-primary) - `components/Card.tsx` (replaced utilities with .card) - `components/Badge.tsx` (replaced utilities with .badge-success) - `styles/__tests__/components.test.ts` (+12 lines, 3 new tests) **Dark mode support:** - ✅ All refactored classes include dark: variants - ✅ Tested in both light and dark mode **Test coverage:** - ✅ Static CSS tests added for all new classes - ✅ Component rendering tests updated - ✅ All tests passing **Behavior verification:** - ✅ Visual output matches original - ✅ No console errors - ✅ Interactive states work correctly ### Impact **Code reduction:** - Removed 247 lines of repeated utility classes from markup - Added 45 lines of semantic CSS - Net reduction: 202 lines **Maintainability:** - Styling centralized in components.css - Changes now made in one place instead of many - Consistent component appearance **Dark mode:** - Added dark mode support that didn't exist before - All components now work in light and dark themes
- •
Suggest next steps:
- •Commit the refactoring
- •Document the new patterns for the team
- •Continue refactoring other components
- •
Offer validation: "Would you like me to validate the refactored CSS using the css-development:validate skill?"
Mark as completed when summary is presented.