design/motion-design/skills/animation-performance-auditor/SKILL.md
This skill should be used when the user's animations feel slow, choppy, or frame-drop. Trigger when the user mentions "animation is janky", "animation is choppy", "dropped frames", "stuttering animation", "animation lags", "smooth on desktop but janky on mobile", "animation causes layout shifts", "scroll is not smooth", "60fps fail", "animation slows down page", "will-change", "GPU acceleration", "how to profile animation", "DevTools performance panel", "Chrome performance tab", or asks why their animation feels slow despite looking correct in code. Also trigger when the user asks about optimizing or auditing existing animations for performance.
npx skillsauth add harsh040506/claude-code-unified-skill-plugin-library animation-performance-auditorInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
Jank is the single most damaging animation problem: a choppy animation is worse than no animation. It signals broken software. This skill provides a systematic diagnostic workflow — from identifying the root cause to applying targeted fixes.
The core fact: At 60fps, every frame has a budget of 16.67ms. Any work that exceeds this budget drops a frame. Work that runs on the GPU (compositing) is essentially free; work that reaches Layout is the most expensive. The browser's rendering pipeline is:
JavaScript → Style Calculation → Layout → Paint → Composite
Animations that stay in Composite never block this pipeline. Any animation that reaches Layout must recalculate every affected element's position and size before painting — this is why top/left animation drops frames and transform: translate() does not.
Open Chrome DevTools → Performance panel:
If no red bars: the animation is performing correctly — the problem may be design, not performance.
Shortcut check without profiling:
Open DevTools → More Tools → Rendering → Enable:
If paint flashing shows large green regions during animation: something is triggering paint that should be composited.
Match the property being animated to its pipeline cost:
| Property | Pipeline stage | Cost | Fix |
|----------|---------------|------|-----|
| transform: translate() | Composite | Free ✓ | Already optimal |
| transform: scale() | Composite | Free ✓ | Already optimal |
| transform: rotate() | Composite | Free ✓ | Already optimal |
| opacity | Composite | Free ✓ | Already optimal |
| filter: blur() | Composite (usually) | Low | Test, usually fine |
| background-color | Paint | Medium | Accept for slow transitions; avoid during scroll |
| border-radius (animated) | Paint | Medium | Use clip-path instead for better perf |
| box-shadow (animated) | Paint | High | Use pseudo-element trick (see below) |
| width, height | Layout | Very high | Replace with transform: scale() |
| top, left, right, bottom | Layout | Very high | Replace with transform: translate() |
| margin, padding | Layout | Very high | Use transform-based layout instead |
| font-size | Layout | Very high | Avoid animating |
Fix: Replace top/left with transform: translate()
/* ❌ Triggers layout recalc on every frame */
.element {
position: absolute;
transition: top 300ms, left 300ms;
top: 20px; left: 0;
}
.element.active { top: 0; left: 20px; }
/* ✅ Composite-only — zero layout cost */
.element {
position: absolute;
transition: transform 300ms ease-out;
}
.element.active { transform: translate(20px, -20px); }
Fix: Replace animated box-shadow with a pseudo-element
/* ❌ Triggers repaint on every shadow change */
.card {
box-shadow: 0 2px 8px rgba(0,0,0,0.1);
transition: box-shadow 200ms;
}
.card:hover { box-shadow: 0 8px 24px rgba(0,0,0,0.15); }
/* ✅ Composite-only: fade in a pre-rendered shadow layer */
.card { position: relative; }
.card::after {
content: "";
position: absolute;
inset: 0;
box-shadow: 0 8px 24px rgba(0,0,0,0.15);
opacity: 0;
transition: opacity 200ms ease-out; /* Only opacity changes — composite */
border-radius: inherit;
}
.card:hover::after { opacity: 1; }
Fix: Remove transition: all
/* ❌ Animates every property change, including layout-triggering ones */
.element { transition: all 300ms; }
/* ✅ Only animate safe properties */
.element {
transition:
transform 300ms ease-out,
opacity 200ms ease-out;
}
Fix: Add will-change for elements that animate repeatedly
/* Promotes to its own GPU layer before animation begins */
.animated-card {
will-change: transform;
}
Warning: Do not add will-change to everything. It consumes VRAM. If the browser has too many composited layers, it runs out of GPU memory and performs worse. Use it on:
Never use it as a blanket optimization.
Fix: Contain layout recalc scope
/* Limits layout recalculation to this subtree */
.animation-container {
contain: layout style paint;
}
Layout thrashing happens when JavaScript reads and writes layout properties in an interleaved loop, forcing the browser to recalculate layout synchronously on every iteration.
// ❌ Layout thrashing — read + write + read + write per element
elements.forEach((el) => {
const height = el.offsetHeight; // Forces layout flush (read)
el.style.height = height * 2 + "px"; // Write (invalidates layout)
});
// ✅ Batch reads, then batch writes
const heights = elements.map((el) => el.offsetHeight); // All reads
elements.forEach((el, i) => {
el.style.height = heights[i] * 2 + "px"; // All writes
});
In Chrome DevTools, layout thrashing appears as interleaved purple (Recalculate Style) and green (Layout) blocks in the flame chart, repeating many times within a single frame.
Use requestAnimationFrame for JS-driven animations:
// ❌ setInterval is not frame-synced; produces tearing at non-60fps displays
setInterval(() => updateAnimation(), 16);
// ✅ rAF syncs to the display refresh rate
function tick(timestamp) {
updateAnimation(timestamp);
requestAnimationFrame(tick);
}
requestAnimationFrame(tick);
DevTools → More Tools → Layers:
will-change: transform or position: fixed have their own layerwill-change overuse or unintentional layer promotion from transform: translateZ(0) hacks)View layer reasons: Click any layer to see why it was promoted. "Has a 3D transform" and "will-change: transform" are expected. Long lists of unexpected promotions signal a problem.
Mobile GPUs are significantly weaker than desktop. An animation that runs at 60fps on desktop may drop to 30fps on a mid-range Android phone.
filter: blur() is GPU-composited on desktop but triggers paint on some Android WebViews — test before committingreferences/devtools-profiling.md — Full walkthrough of Chrome Performance panel, flame chart reading, identifying scripting vs. rendering vs. painting bottlenecks, Firefox equivalent tools, mobile remote debugging setuptesting
Performs quality control on single-cell RNA-seq data (.h5ad or .h5 files) using scverse best practices with MAD-based filtering and comprehensive visualizations. Use when users request QC analysis, filtering low-quality cells, assessing data quality, or following scverse/scanpy best practices for single-cell analysis.
tools
Deep learning for single-cell analysis using scvi-tools. This skill should be used when users need (1) data integration and batch correction with scVI/scANVI, (2) ATAC-seq analysis with PeakVI, (3) CITE-seq multi-modal analysis with totalVI, (4) multiome RNA+ATAC analysis with MultiVI, (5) spatial transcriptomics deconvolution with DestVI, (6) label transfer and reference mapping with scANVI/scArches, (7) RNA velocity with veloVI, or (8) any deep learning-based single-cell method. Triggers include mentions of scVI, scANVI, totalVI, PeakVI, MultiVI, DestVI, veloVI, sysVI, scArches, variational autoencoder, VAE, batch correction, data integration, multi-modal, CITE-seq, multiome, reference mapping, latent space.
testing
This skill should be used when scientists need help with research problem selection, project ideation, troubleshooting stuck projects, or strategic scientific decisions. Use this skill when users ask to pitch a new research idea, work through a project problem, evaluate project risks, plan research strategy, navigate decision trees, or get help choosing what scientific problem to work on. Typical requests include "I have an idea for a project", "I'm stuck on my research", "help me evaluate this project", "what should I work on", or "I need strategic advice about my research".
development
Run nf-core bioinformatics pipelines (rnaseq, sarek, atacseq) on sequencing data. Use when analyzing RNA-seq, WGS/WES, or ATAC-seq data—either local FASTQs or public datasets from GEO/SRA. Triggers on nf-core, Nextflow, FASTQ analysis, variant calling, gene expression, differential expression, GEO reanalysis, GSE/GSM/SRR accessions, or samplesheet creation.