Pulled ALL skills from 15 source repositories: - anthropics/skills: 16 (docs, design, MCP, testing) - obra/superpowers: 14 (TDD, debugging, agents, planning) - coreyhaines31/marketingskills: 25 (marketing, CRO, SEO, growth) - better-auth/skills: 5 (auth patterns) - vercel-labs/agent-skills: 5 (React, design, Vercel) - antfu/skills: 16 (Vue, Vite, Vitest, pnpm, Turborepo) - Plus 13 individual skills from various repos Mosaic Stack is not limited to coding — the Orchestrator and subagents serve coding, business, design, marketing, writing, logistics, analysis, and more. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
4.5 KiB
4.5 KiB
title, impact, impactDescription, type, tags
| title | impact | impactDescription | type | tags | |||||||
|---|---|---|---|---|---|---|---|---|---|---|---|
| Prefer Animating Transform and Opacity for Performance | MEDIUM | Animating layout-triggering properties like height or margin causes expensive reflows and janky animations | best-practice |
|
Prefer Animating Transform and Opacity for Performance
Impact: MEDIUM - When creating Vue transitions, you should prefer animating transform and opacity properties. These are GPU-accelerated and do not trigger expensive CSS layout recalculations. Animating properties like height, width, margin, padding, or top/left causes the browser to recalculate layout on every frame, resulting in janky, low-performance animations.
Task Checklist
- Use
transformfor position and size animations (translate, scale, rotate) - Use
opacityfor fade effects - Avoid animating
height,width,margin,padding,top,left,right,bottom - If you must animate height, consider using
max-heightwith a generous value or JavaScript-based solutions - Use
will-changesparingly and only when needed
Problematic Code:
/* BAD: Animating height triggers layout recalculation every frame */
.slide-enter-active,
.slide-leave-active {
transition: height 0.3s ease;
}
.slide-enter-from,
.slide-leave-to {
height: 0;
}
.slide-enter-to,
.slide-leave-from {
height: 200px;
}
/* BAD: Animating margin causes layout thrashing */
.slide-enter-active,
.slide-leave-active {
transition: margin-top 0.3s ease;
}
.slide-enter-from,
.slide-leave-to {
margin-top: -100%;
}
Correct Code:
/* GOOD: Using transform and opacity - GPU accelerated */
.fade-enter-active,
.fade-leave-active {
transition: opacity 0.3s ease;
}
.fade-enter-from,
.fade-leave-to {
opacity: 0;
}
/* GOOD: Using transform for slide animations */
.slide-enter-active,
.slide-leave-active {
transition: transform 0.3s ease, opacity 0.3s ease;
}
.slide-enter-from {
transform: translateX(-100%);
opacity: 0;
}
.slide-leave-to {
transform: translateX(100%);
opacity: 0;
}
/* GOOD: Using scale instead of width/height */
.scale-enter-active,
.scale-leave-active {
transition: transform 0.3s ease, opacity 0.3s ease;
}
.scale-enter-from,
.scale-leave-to {
transform: scale(0);
opacity: 0;
}
When You Must Animate Height
If you absolutely need to animate height (e.g., accordion), consider these alternatives:
<template>
<!-- Option 1: max-height trick (simple but not precise) -->
<Transition name="expand">
<div v-if="expanded" class="content">
<slot />
</div>
</Transition>
</template>
<style>
.expand-enter-active,
.expand-leave-active {
transition: max-height 0.3s ease, opacity 0.3s ease;
overflow: hidden;
}
.expand-enter-from,
.expand-leave-to {
max-height: 0;
opacity: 0;
}
.expand-enter-to,
.expand-leave-from {
max-height: 500px; /* Set to expected max content height */
opacity: 1;
}
</style>
<script setup>
// Option 2: JavaScript hooks for precise height animation
function onEnter(el, done) {
el.style.height = '0'
el.style.overflow = 'hidden'
// Force reflow
el.offsetHeight
el.style.transition = 'height 0.3s ease'
el.style.height = el.scrollHeight + 'px'
el.addEventListener('transitionend', () => {
el.style.height = ''
el.style.overflow = ''
done()
}, { once: true })
}
function onLeave(el, done) {
el.style.height = el.scrollHeight + 'px'
el.style.overflow = 'hidden'
el.offsetHeight
el.style.transition = 'height 0.3s ease'
el.style.height = '0'
el.addEventListener('transitionend', done, { once: true })
}
</script>
<template>
<Transition @enter="onEnter" @leave="onLeave">
<div v-if="expanded">
<slot />
</div>
</Transition>
</template>
Performance Comparison
| Property | Layout | Paint | Composite | Performance |
|---|---|---|---|---|
transform |
No | No | Yes | Excellent |
opacity |
No | No | Yes | Excellent |
background-color |
No | Yes | Yes | Good |
width/height |
Yes | Yes | Yes | Poor |
margin/padding |
Yes | Yes | Yes | Poor |
top/left |
Yes | Yes | Yes | Poor |
Reference
- Vue.js Transition Documentation
- CSS Triggers - Reference for which properties trigger layout/paint
- High Performance Animations