install
source · Clone the upstream repo
git clone https://github.com/Intense-Visions/harness-engineering
Claude Code · Install into ~/.claude/skills/
T=$(mktemp -d) && git clone --depth=1 https://github.com/Intense-Visions/harness-engineering "$T" && mkdir -p ~/.claude/skills && cp -r "$T/agents/skills/claude-code/css-performance-patterns" ~/.claude/skills/intense-visions-harness-engineering-css-performance-patterns && rm -rf "$T"
manifest:
agents/skills/claude-code/css-performance-patterns/SKILL.mdsource content
CSS Performance Patterns
Optimize CSS performance with content-visibility, containment, efficient selectors, and Core Web Vitals-friendly patterns
When to Use
- Long pages with many elements causing slow initial render
- Cumulative Layout Shift (CLS) issues from images, fonts, or dynamic content
- Large CSS bundles slowing down First Contentful Paint (FCP)
- Animations causing jank (dropped frames below 60fps)
Instructions
- Use
on off-screen sections to skip rendering until they scroll into view.content-visibility: auto - Reserve space for images and embeds with explicit
andwidth
orheight
to prevent CLS.aspect-ratio - Use
sparingly and only on elements about to animate — it allocates GPU memory.will-change - Prefer
andtransform
animations over properties that trigger layout (see animation skill).opacity - Minimize Tailwind output by configuring
paths precisely to avoid scanning unnecessary files.content - Use
for web fonts to prevent invisible text during font loading.font-display: swap
// content-visibility for long lists function ProductList({ products }: { products: Product[] }) { return ( <div> {products.map((product) => ( <div key={product.id} className="contain-layout-style" style={{ contentVisibility: 'auto', containIntrinsicSize: '0 200px', // Estimated height }} > <ProductCard product={product} /> </div> ))} </div> ); } // Prevent CLS with aspect ratio function ResponsiveImage({ src, alt }: { src: string; alt: string }) { return ( <div className="relative aspect-video w-full overflow-hidden rounded-lg bg-gray-100"> <img src={src} alt={alt} className="absolute inset-0 h-full w-full object-cover" loading="lazy" decoding="async" width={1280} height={720} /> </div> ); } // Skeleton loader that matches final layout function CardSkeleton() { return ( <div className="rounded-lg border p-6 space-y-4"> <div className="h-6 w-3/4 bg-gray-200 rounded animate-pulse" /> <div className="h-4 w-full bg-gray-200 rounded animate-pulse" /> <div className="h-4 w-5/6 bg-gray-200 rounded animate-pulse" /> <div className="h-10 w-32 bg-gray-200 rounded animate-pulse" /> </div> ); }
/* Font loading optimization */ @font-face { font-family: 'Inter'; font-display: swap; /* Show fallback immediately, swap when loaded */ src: url('/fonts/inter.woff2') format('woff2'); font-weight: 100 900; }
Details
content-visibility: auto: The browser skips rendering for off-screen elements. On pages with 500+ elements, this can reduce initial render time by 50% or more. The
containIntrinsicSize hint prevents layout shifts when elements come into view.
CSS containment (
contain property):
— element's layout does not affect siblingslayout
— element's content does not render outside its boundspaint
— counters and quotes are scopedstyle
— shorthand forcontentlayout paint style
— shorthand forstrictlayout paint style size
Tailwind utilities:
contain-none, contain-content, contain-strict, contain-layout, contain-paint.
Tailwind bundle optimization:
- Precise
configuration:content['./src/app/**/*.tsx', './src/components/**/*.tsx'] - Do not include
in content paths (massive scan, no utility matches)node_modules - Use
only for truly dynamic classes (from API data)safelist - Tailwind v3 purges unused utilities automatically in production
Core Web Vitals impact:
| Metric | CSS Impact | Solution |
|---|---|---|
| LCP | Large CSS blocks render | Critical CSS inlining, font-display: swap |
| CLS | Dynamic size changes | aspect-ratio, explicit dimensions |
| INP | Layout thrashing from animations | transform/opacity only, containment |
will-change anti-pattern:
/* Bad — permanently allocates GPU memory for all cards */ .card { will-change: transform; } /* Good — only when animation is imminent */ .card:hover { will-change: transform; } .card.animating { will-change: transform, opacity; }
Lazy loading images:
// Native lazy loading <img loading="lazy" decoding="async" src="..." />; // Next.js Image component handles this automatically import Image from 'next/image'; <Image src="..." width={800} height={400} alt="..." />;
CSS performance debugging: Use Chrome DevTools > Performance panel to identify:
- Long "Recalculate Style" events (too many or complex selectors)
- Layout thrashing (forced synchronous layouts)
- Paint storms (large areas repainted frequently)
Source
https://web.dev/articles/content-visibility
Process
- Read the instructions and examples in this document.
- Apply the patterns to your implementation, adapting to your specific context.
- Verify your implementation against the details and edge cases listed above.
Harness Integration
- Type: knowledge — this skill is a reference document, not a procedural workflow.
- No tools or state — consumed as context by other skills and agents.
Success Criteria
- The patterns described in this document are applied correctly in the implementation.
- Edge cases and anti-patterns listed in this document are avoided.