FroquizFroquiz
HomeQuizzesSenior ChallengeGet CertifiedBlogAbout
Sign InStart Quiz
Sign InStart Quiz
Froquiz

The most comprehensive quiz platform for software engineers. Test yourself with 10000+ questions and advance your career.

LinkedIn

Platform

  • Start Quizzes
  • Topics
  • Blog
  • My Profile
  • Sign In

About

  • About Us
  • Contact

Legal

  • Privacy Policy
  • Terms of Service

Β© 2026 Froquiz. All rights reserved.Built with passion for technology
Blog & Articles

CSS Animations and Transitions: A Complete Practical Guide

Master CSS transitions and animations. Covers transition properties, timing functions, keyframes, animation properties, performance optimization, reduced motion, and practical UI patterns.

Yusuf SeyitoğluMarch 17, 20260 views8 min read

CSS Animations and Transitions: A Complete Practical Guide

CSS animations are one of the most overlooked performance opportunities in web development. Done right, they run at 60fps on the GPU with zero JavaScript. Done wrong, they stutter, cause layout thrashing, and drain mobile batteries. This guide teaches you to build smooth, accessible animations the right way.

CSS Transitions

Transitions animate a property from one value to another when it changes (usually via a class change or hover):

css
/* Syntax: transition: property duration timing-function delay */ .button { background: #3b82f6; transform: scale(1); transition: background 200ms ease, transform 150ms ease; } .button:hover { background: #2563eb; transform: scale(1.05); } /* Transition all animatable properties */ .card { transition: all 300ms ease-in-out; } /* Multiple transitions with different timings */ .menu { opacity: 0; transform: translateY(-8px); transition: opacity 200ms ease, transform 200ms cubic-bezier(0.16, 1, 0.3, 1); } .menu.open { opacity: 1; transform: translateY(0); }

Timing Functions

css
/* Built-in keywords */ transition-timing-function: ease; /* slow-fast-slow (default) */ transition-timing-function: linear; /* constant speed */ transition-timing-function: ease-in; /* starts slow */ transition-timing-function: ease-out; /* ends slow */ transition-timing-function: ease-in-out; /* slow start and end */ /* Cubic bezier for custom easing */ transition-timing-function: cubic-bezier(0.16, 1, 0.3, 1); /* spring-like */ transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1); /* Material Design */ /* Steps for frame-by-frame */ transition-timing-function: steps(4, end); /* 4-frame animation */

Use tools like cubic-bezier.com to design custom easing curves visually.

CSS Keyframe Animations

Keyframes define multi-step animations that run automatically:

css
/* Define the animation */ @keyframes fade-in { from { opacity: 0; transform: translateY(16px); } to { opacity: 1; transform: translateY(0); } } @keyframes pulse { 0%, 100% { transform: scale(1); } 50% { transform: scale(1.05); } } @keyframes skeleton-shimmer { 0% { background-position: -200% 0; } 100% { background-position: 200% 0; } } /* Apply the animation */ .hero-title { animation-name: fade-in; animation-duration: 600ms; animation-timing-function: cubic-bezier(0.16, 1, 0.3, 1); animation-delay: 100ms; animation-fill-mode: both; /* apply styles before/after */ animation-iteration-count: 1; /* or: infinite */ animation-direction: normal; /* or: reverse, alternate */ } /* Shorthand */ .hero-title { animation: fade-in 600ms cubic-bezier(0.16, 1, 0.3, 1) 100ms both; } /* Multiple animations */ .loader { animation: spin 1s linear infinite, pulse 2s ease-in-out infinite alternate; }

animation-fill-mode

One of the most commonly misunderstood properties:

css
/* none: element returns to pre-animation state after it ends */ /* forwards: element stays at the final keyframe state */ /* backwards: element starts at the first keyframe state (even during delay) */ /* both: combination of forwards and backwards */ .element { animation: fade-in 400ms ease 200ms both; /* "both" means: show opacity:0 during the 200ms delay, and keep opacity:1 after the animation completes */ }

Performance: Only Animate Cheap Properties

The single most important animation rule: only animate transform and opacity.

PropertyCostWhy
transformCheap βœ…GPU-composited, no layout
opacityCheap βœ…GPU-composited, no layout
color, backgroundMediumRepaint only
width, heightExpensive ❌Triggers layout (reflow)
top, leftExpensive ❌Triggers layout
margin, paddingExpensive ❌Triggers layout
css
/* Bad: animates width, triggers layout on every frame */ .panel { width: 0; transition: width 300ms ease; } .panel.open { width: 300px; } /* Good: animate transform, GPU-accelerated */ .panel { transform: scaleX(0); transform-origin: left; transition: transform 300ms ease; } .panel.open { transform: scaleX(1); }

will-change

Hint to the browser to promote an element to its own compositor layer:

css
.animated-element { will-change: transform, opacity; }

Use sparingly β€” every composited layer consumes GPU memory. Only add it to elements that will definitely animate, and remove it after animation ends.

Practical Animation Patterns

Skeleton Loading

css
.skeleton { background: linear-gradient( 90deg, #f0f0f0 25%, #e0e0e0 50%, #f0f0f0 75% ); background-size: 200% 100%; animation: skeleton-shimmer 1.5s infinite; border-radius: 4px; } @keyframes skeleton-shimmer { 0% { background-position: 200% 0; } 100% { background-position: -200% 0; } }

Toast / Notification

css
@keyframes slide-in-right { from { transform: translateX(110%); opacity: 0; } to { transform: translateX(0); opacity: 1; } } @keyframes slide-out-right { from { transform: translateX(0); opacity: 1; } to { transform: translateX(110%); opacity: 0; } } .toast { animation: slide-in-right 300ms cubic-bezier(0.16, 1, 0.3, 1) both; } .toast.dismissing { animation: slide-out-right 200ms ease-in both; }

Staggered List Animation

css
@keyframes list-item-in { from { opacity: 0; transform: translateY(8px); } to { opacity: 1; transform: translateY(0); } } .list-item { animation: list-item-in 400ms ease both; } /* Stagger with CSS custom property */ .list-item:nth-child(1) { animation-delay: calc(1 * 50ms); } .list-item:nth-child(2) { animation-delay: calc(2 * 50ms); } .list-item:nth-child(3) { animation-delay: calc(3 * 50ms); } /* Or with JS: element.style.setProperty('--index', index) */ .list-item { animation-delay: calc(var(--index, 0) * 50ms); }

Smooth Height Transition

Height transitions are tricky because height: auto cannot be transitioned. Use max-height or the modern interpolate-size approach:

css
/* Workaround: max-height */ .accordion-content { max-height: 0; overflow: hidden; transition: max-height 300ms ease; } .accordion-content.open { max-height: 500px; /* large enough for content */ } /* Modern: interpolate-size (Chrome 129+) */ :root { interpolate-size: allow-keywords; } .accordion-content { height: 0; overflow: hidden; transition: height 300ms ease; } .accordion-content.open { height: auto; /* animates to actual content height */ }

Accessibility: prefers-reduced-motion

Always respect users who have requested reduced motion (epilepsy, vestibular disorders):

css
/* Animations enabled by default */ .card { transition: transform 300ms ease, box-shadow 300ms ease; } .card:hover { transform: translateY(-4px); box-shadow: 0 8px 24px rgba(0,0,0,0.15); } @keyframes spin { to { transform: rotate(360deg); } } .spinner { animation: spin 1s linear infinite; } /* Disable or simplify for users who prefer reduced motion */ @media (prefers-reduced-motion: reduce) { * { animation-duration: 0.01ms !important; animation-iteration-count: 1 !important; transition-duration: 0.01ms !important; } .spinner { animation: none; /* Show a static indicator instead */ } }

Common Interview Questions

Q: Why should you avoid animating layout properties like width and height?

Animating layout-triggering properties (width, height, top, left, margin, padding) forces the browser to recalculate the layout (reflow) and repaint on every animation frame. This is CPU-intensive and frequently causes dropped frames. transform and opacity bypass layout and paint entirely β€” they are handled by the GPU compositor, enabling smooth 60fps animations.

Q: What is the difference between CSS transitions and CSS animations?

Transitions animate a property between two states in response to a trigger (hover, class change) β€” they require a start state and an end state. Animations use keyframes to define multiple intermediate states and can run automatically, loop, reverse, and delay without any trigger. Transitions are simpler for two-state changes; animations are more powerful for complex, multi-step, or auto-playing effects.

Q: What does animation-fill-mode: both do?

both combines forwards and backwards. backwards applies the initial keyframe values during the animation delay period (so the element starts in its animated start state immediately, before the animation begins). forwards keeps the final keyframe values after the animation completes (so the element does not snap back to its original state). Together they ensure the animation feels seamless from the first frame to the last.

Practice on Froquiz

CSS and frontend knowledge is tested in frontend and full-stack developer interviews. Test your CSS knowledge on Froquiz β€” covering layout, animations, and modern CSS features.

Summary

  • Transitions animate between two states on a trigger; keyframe animations define multi-step sequences
  • Only animate transform and opacity for GPU-composited, layout-free 60fps animations
  • animation-fill-mode: both prevents snapping before and after an animation
  • Use cubic-bezier for natural-feeling easing β€” avoid linear for UI animations
  • will-change: transform promotes to compositor layer β€” use sparingly
  • Always add @media (prefers-reduced-motion: reduce) to disable or simplify animations
  • Stagger animations with animation-delay and CSS custom properties for polished list entrances

About Author

Yusuf Seyitoğlu

Author β†’

Other Posts

  • Python Testing with pytest: Fixtures, Parametrize, Mocking and Best PracticesMar 17
  • TanStack Query (React Query): Server State Management Done RightMar 17
  • Software Architecture Patterns: MVC, Clean Architecture, Hexagonal and Event-DrivenMar 17
All Blogs