CSS Animations Skill
Expert knowledge for pure CSS animations - lightweight, performant animations using CSS keyframes, transitions, and modern CSS features without JavaScript dependencies.
When to Use
Activate this skill when:
- •User wants lightweight animations without libraries
- •Need simple hover/focus state transitions
- •Building loading spinners or skeleton screens
- •Performance is critical and animation is simple
- •Animating pseudo-elements (::before, ::after)
- •Using Tailwind CSS animation utilities
File Patterns
- •
**/*.csswith@keyframesdefinitions - •
**/*.scssor**/*.sasswith animations - •
**/*.tsxwith Tailwind animation classes - •
**/styles/*.csswith animation utilities - •
tailwind.config.jswith custom animations
Core Concepts
CSS Transitions
css
.element {
transition: transform 0.3s ease-out, opacity 0.3s ease-out;
}
.element:hover {
transform: translateY(-4px);
opacity: 0.9;
}
/* Shorthand */
.element {
transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
}
CSS Keyframe Animations
css
@keyframes fadeIn {
from {
opacity: 0;
transform: translateY(20px);
}
to {
opacity: 1;
transform: translateY(0);
}
}
.element {
animation: fadeIn 0.5s ease-out forwards;
}
Animation Properties
css
.element {
animation-name: slideIn;
animation-duration: 0.5s;
animation-timing-function: ease-out;
animation-delay: 0.2s;
animation-iteration-count: 1; /* or infinite */
animation-direction: normal; /* or reverse, alternate, alternate-reverse */
animation-fill-mode: forwards; /* none, forwards, backwards, both */
animation-play-state: running; /* or paused */
/* Shorthand */
animation: slideIn 0.5s ease-out 0.2s 1 normal forwards;
}
Timing Functions
css
/* Built-in */ transition-timing-function: linear; transition-timing-function: ease; transition-timing-function: ease-in; transition-timing-function: ease-out; transition-timing-function: ease-in-out; /* Cubic bezier */ transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1); /* Material ease */ transition-timing-function: cubic-bezier(0.25, 0.1, 0.25, 1); /* Default ease */ transition-timing-function: cubic-bezier(0.68, -0.55, 0.265, 1.55); /* Back ease */ /* Steps (for sprite animations) */ transition-timing-function: steps(4, end);
Common Keyframes Library
Fade Animations
css
@keyframes fadeIn {
from { opacity: 0; }
to { opacity: 1; }
}
@keyframes fadeOut {
from { opacity: 1; }
to { opacity: 0; }
}
@keyframes fadeInUp {
from {
opacity: 0;
transform: translate3d(0, 20px, 0);
}
to {
opacity: 1;
transform: translate3d(0, 0, 0);
}
}
@keyframes fadeInDown {
from {
opacity: 0;
transform: translate3d(0, -20px, 0);
}
to {
opacity: 1;
transform: translate3d(0, 0, 0);
}
}
Scale Animations
css
@keyframes scaleIn {
from {
opacity: 0;
transform: scale(0.9);
}
to {
opacity: 1;
transform: scale(1);
}
}
@keyframes pulse {
0%, 100% {
transform: scale(1);
}
50% {
transform: scale(1.05);
}
}
@keyframes bounce {
0%, 100% {
transform: translateY(0);
}
50% {
transform: translateY(-10px);
}
}
Loading Animations
css
@keyframes spin {
from { transform: rotate(0deg); }
to { transform: rotate(360deg); }
}
@keyframes shimmer {
0% {
background-position: -200% 0;
}
100% {
background-position: 200% 0;
}
}
@keyframes dotPulse {
0%, 80%, 100% {
transform: scale(0);
opacity: 0.5;
}
40% {
transform: scale(1);
opacity: 1;
}
}
Tailwind CSS Animations
Built-in Animations
html
<div class="animate-spin">Loading...</div> <div class="animate-ping">Notification</div> <div class="animate-pulse">Skeleton</div> <div class="animate-bounce">Scroll down</div>
Custom Tailwind Animations
javascript
// tailwind.config.js
module.exports = {
theme: {
extend: {
animation: {
'fade-in': 'fadeIn 0.5s ease-out forwards',
'fade-in-up': 'fadeInUp 0.5s ease-out forwards',
'slide-in-right': 'slideInRight 0.3s ease-out forwards',
'scale-in': 'scaleIn 0.2s ease-out forwards',
'shimmer': 'shimmer 2s infinite',
},
keyframes: {
fadeIn: {
'0%': { opacity: '0' },
'100%': { opacity: '1' },
},
fadeInUp: {
'0%': { opacity: '0', transform: 'translateY(20px)' },
'100%': { opacity: '1', transform: 'translateY(0)' },
},
slideInRight: {
'0%': { opacity: '0', transform: 'translateX(20px)' },
'100%': { opacity: '1', transform: 'translateX(0)' },
},
scaleIn: {
'0%': { opacity: '0', transform: 'scale(0.95)' },
'100%': { opacity: '1', transform: 'scale(1)' },
},
shimmer: {
'0%': { backgroundPosition: '-200% 0' },
'100%': { backgroundPosition: '200% 0' },
},
},
},
},
};
Stagger with CSS Custom Properties
css
.stagger-item {
animation: fadeInUp 0.5s ease-out forwards;
animation-delay: calc(var(--index) * 0.1s);
opacity: 0;
}
tsx
{items.map((item, index) => (
<div
key={item.id}
className="stagger-item"
style={{ '--index': index } as React.CSSProperties}
>
{item.content}
</div>
))}
Component Patterns
Loading Spinner
tsx
// components/Spinner.tsx
export function Spinner({ size = 'md' }: { size?: 'sm' | 'md' | 'lg' }) {
const sizes = {
sm: 'w-4 h-4 border-2',
md: 'w-8 h-8 border-3',
lg: 'w-12 h-12 border-4',
};
return (
<div
className={`${sizes[size]} rounded-full border-blue-500 border-t-transparent animate-spin`}
/>
);
}
Skeleton Loading
tsx
// components/Skeleton.tsx
export function Skeleton({
className,
...props
}: React.HTMLAttributes<HTMLDivElement>) {
return (
<div
className={`bg-gray-200 rounded animate-pulse ${className}`}
{...props}
/>
);
}
// Usage
<div className="space-y-2">
<Skeleton className="h-4 w-3/4" />
<Skeleton className="h-4 w-1/2" />
<Skeleton className="h-4 w-5/6" />
</div>
Shimmer Effect
css
.shimmer {
background: linear-gradient(
90deg,
#f0f0f0 0%,
#e0e0e0 50%,
#f0f0f0 100%
);
background-size: 200% 100%;
animation: shimmer 1.5s infinite;
}
Performance Tips
GPU-Accelerated Properties (Animate These)
css
/* Good - GPU accelerated */ transform: translateX(100px); transform: scale(1.1); transform: rotate(45deg); opacity: 0.5; /* Avoid - trigger layout/paint */ width: 100px; height: 100px; top: 10px; left: 10px; margin: 10px; padding: 10px;
Will-Change Hint
css
.animated-element {
will-change: transform, opacity;
}
/* Remove after animation */
.animated-element.done {
will-change: auto;
}
Prefer Transform Over Position
css
/* Bad - triggers layout */
.slide {
left: 0;
transition: left 0.3s;
}
.slide.active {
left: 100px;
}
/* Good - GPU accelerated */
.slide {
transform: translateX(0);
transition: transform 0.3s;
}
.slide.active {
transform: translateX(100px);
}
Reduced Motion Support
css
@media (prefers-reduced-motion: reduce) {
*,
*::before,
*::after {
animation-duration: 0.01ms !important;
animation-iteration-count: 1 !important;
transition-duration: 0.01ms !important;
}
}
/* Or provide alternatives */
@media (prefers-reduced-motion: reduce) {
.animated-element {
animation: none;
opacity: 1;
}
}
Examples
<example> Context: User wants a hover effect on cards user: "Add a subtle lift effect when hovering over cards" assistant: Using CSS transitions for smooth hover: ```css .card { transition: transform 0.2s ease-out, box-shadow 0.2s ease-out; }.card:hover { transform: translateY(-4px); box-shadow: 0 12px 24px rgba(0, 0, 0, 0.15); }
code
Or with Tailwind: ```tsx <div className="transition-all duration-200 ease-out hover:-translate-y-1 hover:shadow-xl"> Card content </div>
Related Skills
- •framer-motion - When animations need JavaScript control
- •spring-physics - For more natural motion
- •scroll-animations - For scroll-triggered CSS animations
Author
Created by Brookside BI as part of React Animation Studio