// CSS animation and transition creator. Generates optimized @keyframes, transitions, and transform sequences with performance best practices and motion accessibility. Use when adding animations, transitions, or micro-interactions.
| name | animation-creator |
| description | CSS animation and transition creator. Generates optimized @keyframes, transitions, and transform sequences with performance best practices and motion accessibility. Use when adding animations, transitions, or micro-interactions. |
| allowed-tools | Read, Write, Edit |
This skill helps you create performant, accessible CSS animations and transitions. I'll guide you through animation requirements and generate optimized code that respects user preferences and follows performance best practices.
Tell me what you want to animate and I'll create the CSS. I'll ask:
I always follow these rules for smooth animations:
/* โ GOOD - GPU accelerated */
.animated {
transition: transform 0.3s, opacity 0.3s;
}
/* โ BAD - Triggers layout/paint */
.animated {
transition: width 0.3s, height 0.3s, left 0.3s;
}
.animating {
will-change: transform, opacity;
}
.animating.complete {
will-change: auto; /* Remove after animation */
}
@media (prefers-reduced-motion: reduce) {
*,
*::before,
*::after {
animation-duration: 0.01ms !important;
animation-iteration-count: 1 !important;
transition-duration: 0.01ms !important;
}
}
@keyframes fadeIn {
from {
opacity: 0;
}
to {
opacity: 1;
}
}
.fade-in {
animation: fadeIn 0.5s ease-in;
}
@keyframes slideInLeft {
from {
transform: translateX(-100%);
opacity: 0;
}
to {
transform: translateX(0);
opacity: 1;
}
}
.slide-in-left {
animation: slideInLeft 0.5s ease-out;
}
@keyframes bounce {
0%, 20%, 50%, 80%, 100% {
transform: translateY(0);
}
40% {
transform: translateY(-30px);
}
60% {
transform: translateY(-15px);
}
}
.bounce {
animation: bounce 1s ease;
}
@keyframes pulse {
0% {
transform: scale(1);
}
50% {
transform: scale(1.05);
}
100% {
transform: scale(1);
}
}
.pulse {
animation: pulse 2s ease infinite;
}
@keyframes spin {
from {
transform: rotate(0deg);
}
to {
transform: rotate(360deg);
}
}
.spinner {
width: 40px;
height: 40px;
border: 4px solid #f3f3f3;
border-top: 4px solid #3498db;
border-radius: 50%;
animation: spin 1s linear infinite;
}
.button {
transition: all 0.2s ease;
}
.button:hover {
transform: translateY(-2px);
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.2);
}
.button:active {
transform: translateY(0);
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2);
}
@keyframes modalFadeIn {
from {
opacity: 0;
transform: scale(0.9) translateY(-20px);
}
to {
opacity: 1;
transform: scale(1) translateY(0);
}
}
.modal {
animation: modalFadeIn 0.3s ease-out;
}
/* Backdrop fade */
@keyframes backdropFadeIn {
from {
opacity: 0;
}
to {
opacity: 1;
}
}
.modal-backdrop {
animation: backdropFadeIn 0.3s ease;
}
@keyframes shake {
0%, 100% {
transform: translateX(0);
}
10%, 30%, 50%, 70%, 90% {
transform: translateX(-10px);
}
20%, 40%, 60%, 80% {
transform: translateX(10px);
}
}
.shake {
animation: shake 0.5s ease;
}
@keyframes shimmer {
0% {
background-position: -1000px 0;
}
100% {
background-position: 1000px 0;
}
}
.skeleton {
background: linear-gradient(
90deg,
#f0f0f0 25%,
#e0e0e0 50%,
#f0f0f0 75%
);
background-size: 1000px 100%;
animation: shimmer 2s infinite linear;
}
.menu {
transform: translateX(-100%);
opacity: 0;
transition: transform 0.3s ease, opacity 0.3s ease;
}
.menu.open {
transform: translateX(0);
opacity: 1;
}
/* Linear - constant speed */
transition: all 0.3s linear;
/* Ease (default) - slow start and end */
transition: all 0.3s ease;
/* Ease-in - slow start */
transition: all 0.3s ease-in;
/* Ease-out - slow end */
transition: all 0.3s ease-out;
/* Ease-in-out - slow start and end (more pronounced) */
transition: all 0.3s ease-in-out;
/* Bouncy */
transition: transform 0.5s cubic-bezier(0.68, -0.55, 0.265, 1.55);
/* Smooth */
transition: transform 0.3s cubic-bezier(0.4, 0, 0.2, 1);
/* Fast out, slow in */
transition: transform 0.3s cubic-bezier(0, 0, 0.2, 1);
animation-duration: 0.3s; /* Fast */
animation-duration: 0.5s; /* Normal */
animation-duration: 1s; /* Slow */
animation-duration: 2s; /* Very slow */
animation-iteration-count: 1; /* Once */
animation-iteration-count: 3; /* Three times */
animation-iteration-count: infinite; /* Forever */
animation-direction: normal; /* Forward */
animation-direction: reverse; /* Backward */
animation-direction: alternate; /* Forward then backward */
animation-fill-mode: none; /* No persistence */
animation-fill-mode: forwards; /* Keep final state */
animation-fill-mode: backwards; /* Start in first keyframe */
animation-fill-mode: both; /* Both forwards and backwards */
animation-play-state: running; /* Playing */
animation-play-state: paused; /* Paused */
I always include:
@media (prefers-reduced-motion: reduce) {
.animated {
animation-duration: 0.01ms;
transition-duration: 0.01ms;
}
}
.button:focus-visible {
outline: 2px solid #0066cc;
outline-offset: 2px;
transition: outline-offset 0.2s ease;
}
โ Animate transform and opacity only when possible
โ Use will-change sparingly and temporarily
โ Avoid animating width, height, top, left
โ Keep animations under 300-500ms for UI interactions
โ Test on low-end devices
โ Use requestAnimationFrame for JavaScript animations
โ Remove animations from elements outside viewport
You say: "Create a fade and slide up animation for cards appearing on page load"
I'll provide:
@keyframes fadeSlideUp {
from {
opacity: 0;
transform: translateY(30px);
}
to {
opacity: 1;
transform: translateY(0);
}
}
.card {
animation: fadeSlideUp 0.5s ease-out;
animation-fill-mode: backwards;
}
/* Stagger the animations */
.card:nth-child(1) { animation-delay: 0.1s; }
.card:nth-child(2) { animation-delay: 0.2s; }
.card:nth-child(3) { animation-delay: 0.3s; }
/* Respect reduced motion */
@media (prefers-reduced-motion: reduce) {
.card {
animation: none;
opacity: 1;
transform: translateY(0);
}
}
Tell me what animation you need:
I'll create performant, accessible CSS animations for you!