Two Types of Animations
Transitions - Animate property changes (simple, common)
Keyframe Animations - Complex, multi-step animations
CSS Transitions
Transitions animate changes from one state to another.
Basic Syntax
transition: property duration timing-function delay;
Simple Example
.button {
background-color : var ( --color-secondary );
transition : background-color 300 ms ease ;
}
.button:hover {
background-color : var ( --color-secondary-dark );
/* Smoothly animates to dark blue */
}
Transition Properties
Property - What to animate
Duration - How long
Timing Function - Speed curve
Delay - Wait before starting
.element {
transition-property : background-color;
transition-property : all ; /* Animate all changing properties */
transition-property : transform, opacity; /* Multiple */
}
Shorthand Syntax
Single Property
Multiple Properties
All Properties
.element {
transition : background-color 300 ms ease ;
}
Real Examples from the Project
.header__search-button {
background-color : var ( --color-secondary );
transition : background-color var ( --transition-fast );
}
.header__search-button:hover {
background-color : var ( --color-secondary-dark );
}
/* Variables defined in :root */
:root {
--transition-fast : 150 ms ease ;
}
Navigation Link
.header__nav-link {
color : var ( --color-gray-600 );
border-radius : var ( --border-radius-sm );
transition : background-color var ( --transition-fast );
}
.header__nav-link:hover {
background-color : rgba ( 0 , 0 , 0 , 0.05 );
}
Logo Scale on Hover
.header__logo-link {
display : flex ;
align-items : baseline ;
transition : transform var ( --transition-fast );
}
.header__logo-link:hover {
transform : scale ( 1.02 ); /* Slightly larger */
}
.hero__cta {
background-color : var ( --color-secondary );
transition : background-color var ( --transition-fast ),
transform var ( --transition-fast );
}
.hero__cta:hover {
background-color : var ( --color-secondary-dark );
transform : translateY ( -2 px ); /* Lift up slightly */
}
.hero__cta:active {
transform : translateY ( 0 ); /* Push back down when clicked */
}
Product Card
.product-card {
background-color : var ( --color-white );
box-shadow : var ( --shadow-sm );
transition : transform var ( --transition-base ),
box-shadow var ( --transition-base );
}
.product-card:hover {
transform : translateY ( -8 px ); /* Float up */
box-shadow : var ( --shadow-lg ); /* Stronger shadow */
}
Image Zoom on Card Hover
.product-card__image {
transition : transform var ( --transition-base );
}
/* When card is hovered, scale the image inside */
.product-card:hover .product-card__image {
transform : scale ( 1.05 );
}
Benefits Item
.benefits__item {
background-color : var ( --color-gray-100 );
transition : transform var ( --transition-fast ),
box-shadow var ( --transition-fast );
}
.benefits__item:hover {
transform : translateY ( -4 px );
box-shadow : var ( --shadow-md );
}
.footer__link {
color : var ( --color-gray-500 );
transition : color var ( --transition-fast );
}
.footer__link:hover {
color : var ( --color-secondary );
}
Social Link Scale
.footer__social-link {
transition : transform var ( --transition-fast );
}
.footer__social-link:hover {
transform : scale ( 1.2 ); /* 20% larger */
}
Timing Functions Explained
Visual Comparison
ease (default)
linear
ease-in
ease-out
ease-in-out
.element {
transition : transform 500 ms ease ;
/* Slow start, fast middle, slow end */
/* Most natural-feeling */
}
Custom Cubic Bezier
.element {
/* Custom timing curve */
transition : transform 300 ms cubic-bezier ( 0.68 , -0.55 , 0.265 , 1.55 );
/* Creates a bounce effect */
}
Common transforms used in transitions:
Translate (Move)
Scale (Resize)
Rotate
Skew (Slant)
Multiple Transforms
.element {
transform : translateX ( 20 px ); /* Move right 20px */
transform : translateY ( -10 px ); /* Move up 10px */
transform : translate ( 20 px , -10 px ); /* Both */
}
Keyframe Animations
For complex, multi-step animations.
Basic Syntax
/* 1. Define the animation */
@keyframes animation-name {
from {
/* Starting state */
}
to {
/* Ending state */
}
}
/* 2. Apply to element */
.element {
animation : animation-name duration timing-function iteration-count;
}
Percentage Keyframes
@keyframes slide-in {
0% {
transform : translateX ( -100 % );
opacity : 0 ;
}
50% {
opacity : 0.5 ;
}
100% {
transform : translateX ( 0 );
opacity : 1 ;
}
}
Real Animation: Loading Spinner
.products__spinner {
width : 40 px ;
height : 40 px ;
border : 4 px solid var ( --color-gray-200 );
border-top-color : var ( --color-secondary );
border-radius : var ( --border-radius-full );
/* Apply animation */
animation : spin 1 s linear infinite ;
}
/* Define animation */
@keyframes spin {
from {
transform : rotate ( 0 deg );
}
to {
transform : rotate ( 360 deg );
}
}
Use linear timing for spinners so rotation speed is constant.
Animation Properties
animation-name
animation-duration
animation-timing-function
animation-iteration-count
animation-direction
animation-delay
animation-fill-mode
.element {
animation-name : slide-in;
}
Shorthand
.element {
animation : name duration timing-function delay iteration-count direction fill-mode;
/* Example */
animation : slide-in 1 s ease-out 0 s 1 normal forwards ;
/* Common shorthand */
animation : spin 1 s linear infinite ;
}
Common Animation Patterns
Fade In
@keyframes fade-in {
from {
opacity : 0 ;
}
to {
opacity : 1 ;
}
}
.element {
animation : fade-in 500 ms ease-out ;
}
Slide In from Left
@keyframes slide-in-left {
from {
transform : translateX ( -100 % );
opacity : 0 ;
}
to {
transform : translateX ( 0 );
opacity : 1 ;
}
}
.element {
animation : slide-in-left 600 ms ease-out ;
}
Bounce
@keyframes bounce {
0% , 100% {
transform : translateY ( 0 );
}
50% {
transform : translateY ( -20 px );
}
}
.element {
animation : bounce 1 s ease-in-out infinite ;
}
Pulse (Scale)
@keyframes pulse {
0% , 100% {
transform : scale ( 1 );
}
50% {
transform : scale ( 1.05 );
}
}
.element {
animation : pulse 2 s ease-in-out infinite ;
}
Shake
@keyframes shake {
0% , 100% {
transform : translateX ( 0 );
}
25% {
transform : translateX ( -10 px );
}
75% {
transform : translateX ( 10 px );
}
}
.element {
animation : shake 400 ms ease-in-out ;
}
Animate transform and opacity - they’re GPU-accelerated
Use will-change sparingly for complex animations
Avoid animating width, height, top, left - they cause reflows
Don’t animate too many elements at once
GPU-Accelerated Properties
/* FAST - GPU accelerated */
.element {
transform : translateX ( 100 px );
opacity : 0.5 ;
}
/* SLOW - Causes reflow/repaint */
.element {
left : 100 px ; /* Use transform instead */
width : 500 px ; /* Avoid animating */
}
will-change
.element {
/* Tell browser this will animate */
will-change : transform, opacity;
}
.element:hover {
transform : scale ( 1.1 );
}
Don’t overuse will-change - it uses extra memory. Only use for complex animations.
Accessibility: Reduced Motion
Respect users who prefer reduced motion:
/* Normal animations */
.element {
transition : transform 300 ms ease ;
}
/* Disable for users who prefer reduced motion */
@media (prefers-reduced-motion: reduce) {
* ,
* ::before ,
* ::after {
animation-duration : 0.01 ms !important ;
animation-iteration-count : 1 !important ;
transition-duration : 0.01 ms !important ;
scroll-behavior : auto !important ;
}
}
Always include prefers-reduced-motion for better accessibility. Some users get motion sickness from animations.
Animation Best Practices
Keep animations subtle and purposeful
Use appropriate durations (150-300ms for most UI)
Match timing to the action (entering vs exiting)
Use easing for natural feel
Don’t animate on page load unless necessary
Avoid animations that distract from content
Duration Guidelines
Very fast (100-150ms) - Small changes, icons
Fast (150-250ms) - Buttons, links, hovers
Medium (250-400ms) - Modals, dropdowns, cards
Slow (400-600ms) - Page transitions, large movements
Very slow (600ms+) - Special effects, attention-grabbing
Variables for Animations
From the project:
:root {
--transition-fast : 150 ms ease ;
--transition-base : 300 ms ease ;
--transition-slow : 500 ms ease ;
}
/* Use throughout */
.button {
transition : background-color var ( --transition-fast );
}
.card {
transition : transform var ( --transition-base ),
box-shadow var ( --transition-base );
}
Complete Example: Animated Card
.card {
background-color : var ( --color-white );
border-radius : var ( --border-radius-md );
box-shadow : var ( --shadow-sm );
/* Multiple transitions */
transition : transform var ( --transition-base ),
box-shadow var ( --transition-base );
}
.card:hover {
transform : translateY ( -8 px );
box-shadow : var ( --shadow-lg );
}
.card__image {
border-radius : var ( --border-radius-md );
transition : transform var ( --transition-base );
}
.card:hover .card__image {
transform : scale ( 1.05 );
}
.card__button {
background-color : var ( --color-secondary );
transition : background-color var ( --transition-fast ),
transform var ( --transition-fast );
}
.card__button:hover {
background-color : var ( --color-secondary-dark );
transform : translateY ( -2 px );
}
.card__button:active {
transform : translateY ( 0 );
}
Next Steps
Responsive Design Make animations responsive
Variables Use variables in animations