Learn CSS in 10 DaysDay 9: Transitions and Animations

Day 9: Transitions and Animations

What You Will Learn Today

  • CSS transitions for smooth property changes
  • Timing functions and how they affect motion
  • The transform property
  • @keyframes animations for complex sequences
  • Common animation patterns
  • Performance considerations
  • Accessibility with prefers-reduced-motion

CSS Transitions

A transition smoothly interpolates between two states of a property when it changes.

.button {
    background-color: #3b82f6;
    color: white;
    padding: 12px 24px;
    border: none;
    border-radius: 8px;
    transition: background-color 0.3s ease;
}

.button:hover {
    background-color: #1d4ed8;
}

The transition Property

/* Individual properties */
transition-property: background-color;
transition-duration: 0.3s;
transition-timing-function: ease;
transition-delay: 0s;

/* Shorthand */
transition: background-color 0.3s ease 0s;

/* Multiple properties */
transition: background-color 0.3s ease, transform 0.2s ease;

/* All animatable properties */
transition: all 0.3s ease;

Timing Functions

Value Behavior
ease Slow start, fast middle, slow end (default)
ease-in Slow start
ease-out Slow end
ease-in-out Slow start and end
linear Constant speed
cubic-bezier() Custom curve
flowchart LR
    subgraph Timing["Timing Functions"]
        Ease["ease<br>Natural feel"]
        Linear["linear<br>Constant speed"]
        EIO["ease-in-out<br>Smooth start & end"]
    end
    style Ease fill:#3b82f6,color:#fff
    style Linear fill:#22c55e,color:#fff
    style EIO fill:#f59e0b,color:#fff

The transform Property

transform lets you visually transform elements without affecting the document layout.

/* Translate (move) */
transform: translateX(20px);
transform: translateY(-10px);
transform: translate(20px, -10px);

/* Scale */
transform: scale(1.1);
transform: scale(1.5, 0.5);

/* Rotate */
transform: rotate(45deg);

/* Skew */
transform: skew(10deg);

/* Combine multiple transforms */
transform: translate(20px, 0) scale(1.1) rotate(5deg);
Function Effect Example
translate() Move translate(10px, 20px)
scale() Resize scale(1.2)
rotate() Rotate rotate(45deg)
skew() Skew skew(10deg)

transform-origin

Changes the point around which the transform is applied.

.card {
    transform-origin: top left;
    transform: rotate(5deg);
}

Common Transition Patterns

Hover Lift Effect

.card {
    transition: transform 0.2s ease, box-shadow 0.2s ease;
}

.card:hover {
    transform: translateY(-4px);
    box-shadow: 0 10px 25px rgba(0, 0, 0, 0.15);
}

Button Effect

.btn {
    transition: all 0.2s ease;
}

.btn:hover {
    background-color: #1d4ed8;
    transform: translateY(-2px);
    box-shadow: 0 4px 12px rgba(59, 130, 246, 0.4);
}

.btn:active {
    transform: translateY(0);
    box-shadow: 0 2px 4px rgba(59, 130, 246, 0.3);
}

Fade In

.fade {
    opacity: 0;
    transform: translateY(20px);
    transition: opacity 0.5s ease, transform 0.5s ease;
}

.fade.visible {
    opacity: 1;
    transform: translateY(0);
}

CSS Animations with @keyframes

For animations more complex than a simple A-to-B transition, use @keyframes.

@keyframes fadeIn {
    from {
        opacity: 0;
        transform: translateY(20px);
    }
    to {
        opacity: 1;
        transform: translateY(0);
    }
}

.element {
    animation: fadeIn 0.5s ease forwards;
}

Multiple Keyframes

@keyframes pulse {
    0%   { transform: scale(1); }
    50%  { transform: scale(1.05); }
    100% { transform: scale(1); }
}

.pulse {
    animation: pulse 2s ease-in-out infinite;
}

The animation Property

animation-name: fadeIn;
animation-duration: 0.5s;
animation-timing-function: ease;
animation-delay: 0s;
animation-iteration-count: 1;        /* Use 'infinite' for looping */
animation-direction: normal;          /* 'alternate' for back-and-forth */
animation-fill-mode: forwards;        /* Keeps the final state */

/* Shorthand */
animation: fadeIn 0.5s ease 0s 1 normal forwards;
Property Example Values Description
iteration-count infinite, 3 How many times to repeat
direction normal, alternate, reverse Playback direction
fill-mode forwards, backwards, both State before/after animation

Common Animation Patterns

Spinner

@keyframes spin {
    to { transform: rotate(360deg); }
}

.spinner {
    width: 40px;
    height: 40px;
    border: 4px solid #e2e8f0;
    border-top-color: #3b82f6;
    border-radius: 50%;
    animation: spin 0.8s linear infinite;
}

Bounce

@keyframes bounce {
    0%, 100% { transform: translateY(0); }
    50%      { transform: translateY(-20px); }
}

.bounce {
    animation: bounce 1s ease infinite;
}

Slide In

@keyframes slideIn {
    from {
        opacity: 0;
        transform: translateX(-100%);
    }
    to {
        opacity: 1;
        transform: translateX(0);
    }
}

.slide-in {
    animation: slideIn 0.5s ease forwards;
}

Performance Considerations

GPU-Accelerated Properties

Not all CSS properties animate equally well. Some trigger expensive layout recalculations, while others are handled efficiently by the GPU.

/* Fast (GPU-composited) */
transform: translateX(100px);
opacity: 0.5;

/* Slow (triggers layout recalculation) */
left: 100px;
width: 200px;
margin-left: 100px;
Property Performance
transform Fast
opacity Fast
color, background-color Moderate
width, height, margin Slow

Rule of thumb: Animate using transform and opacity whenever possible. Use translate() instead of left/top for moving elements.

will-change

Hints the browser to prepare for an upcoming animation.

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

Caution: Use will-change sparingly. It consumes extra memory, so only apply it to elements you know will animate.


Accessibility: prefers-reduced-motion

Some users experience discomfort or disorientation from motion on screen. The prefers-reduced-motion media query lets you respect their preferences.

@media (prefers-reduced-motion: reduce) {
    * {
        animation-duration: 0.01ms !important;
        animation-iteration-count: 1 !important;
        transition-duration: 0.01ms !important;
    }
}

Important: Always include prefers-reduced-motion support in any project with animations. This is an accessibility requirement, not an optional nicety.


Practice: Interactive Cards

* {
    margin: 0;
    padding: 0;
    box-sizing: border-box;
}

body {
    font-family: system-ui, sans-serif;
    background: #f8fafc;
    padding: 48px 16px;
}

.cards {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
    gap: 24px;
    max-width: 900px;
    margin: 0 auto;
}

.card {
    background: white;
    border-radius: 12px;
    padding: 32px;
    box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);
    transition: transform 0.2s ease, box-shadow 0.2s ease;
}

.card:hover {
    transform: translateY(-8px);
    box-shadow: 0 12px 30px rgba(0, 0, 0, 0.12);
}

.card h3 {
    margin-bottom: 12px;
}

.card p {
    color: #64748b;
    margin-bottom: 16px;
}

.card .btn {
    display: inline-block;
    background: #3b82f6;
    color: white;
    padding: 8px 20px;
    border-radius: 6px;
    text-decoration: none;
    font-weight: 600;
    transition: background-color 0.2s ease, transform 0.1s ease;
}

.card .btn:hover {
    background: #2563eb;
    transform: translateY(-1px);
}

.card .btn:active {
    transform: translateY(0);
}

/* Accessibility */
@media (prefers-reduced-motion: reduce) {
    .card,
    .card .btn {
        transition: none;
    }
}

Summary

Concept Description
transition Smoothly interpolates property changes
transform Visually transforms elements (move, scale, rotate)
@keyframes Defines complex multi-step animations
animation Applies a keyframe animation
will-change Optimization hint for the browser
prefers-reduced-motion Accessibility media query for motion sensitivity

Key Takeaways

  1. Use transform and opacity for performant animations
  2. transition is for simple state changes; @keyframes is for complex sequences
  3. Always support prefers-reduced-motion
  4. Choose GPU-composited properties for smooth 60fps motion

Exercises

Exercise 1: Basics

Create a button that changes color and lifts slightly on hover with a smooth transition.

Exercise 2: Intermediate

Build a loading spinner using @keyframes and the animation property.

Challenge

Implement a fade-in-on-scroll animation using @keyframes and JavaScript's IntersectionObserver. Make sure to respect prefers-reduced-motion.


References


Next up: In Day 10, you will tackle the Final Project -- putting every CSS concept from the past 9 days together to style a complete portfolio site!