Harness-engineering css-performance-patterns

CSS Performance Patterns

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.md
source 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

  1. Use
    content-visibility: auto
    on off-screen sections to skip rendering until they scroll into view.
  2. Reserve space for images and embeds with explicit
    width
    and
    height
    or
    aspect-ratio
    to prevent CLS.
  3. Use
    will-change
    sparingly and only on elements about to animate — it allocates GPU memory.
  4. Prefer
    transform
    and
    opacity
    animations over properties that trigger layout (see animation skill).
  5. Minimize Tailwind output by configuring
    content
    paths precisely to avoid scanning unnecessary files.
  6. Use
    font-display: swap
    for web fonts to prevent invisible text during font loading.
// 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):

  • layout
    — element's layout does not affect siblings
  • paint
    — element's content does not render outside its bounds
  • style
    — counters and quotes are scoped
  • content
    — shorthand for
    layout paint style
  • strict
    — shorthand for
    layout paint style size

Tailwind utilities:

contain-none
,
contain-content
,
contain-strict
,
contain-layout
,
contain-paint
.

Tailwind bundle optimization:

  • Precise
    content
    configuration:
    ['./src/app/**/*.tsx', './src/components/**/*.tsx']
  • Do not include
    node_modules
    in content paths (massive scan, no utility matches)
  • Use
    safelist
    only for truly dynamic classes (from API data)
  • Tailwind v3 purges unused utilities automatically in production

Core Web Vitals impact:

MetricCSS ImpactSolution
LCPLarge CSS blocks renderCritical CSS inlining, font-display: swap
CLSDynamic size changesaspect-ratio, explicit dimensions
INPLayout thrashing from animationstransform/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

  1. Read the instructions and examples in this document.
  2. Apply the patterns to your implementation, adapting to your specific context.
  3. 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.