Chapter 15: Transformations, Transitions, and Animation
Movement on a page can feel gentle or jolting depending on how it is shaped. CSS gives you a small toolkit for motion that works across modern browsers with very little code. You can nudge an element, fade a panel, or choreograph a full sequence with keyframes. Used with care, these effects help readers understand change rather than distract them. This chapter explores the building blocks of smooth transitions and small animations that enhance rather than overwhelm.
Smooth transitions
A transition eases a change from one state to another. This could be a button shifting color on hover or a card lifting slightly when focused. Transitions happen automatically when a property changes; you define the duration, the delay and the timing function that shapes the movement. Humans tend to prefer motion that starts gently, accelerates a little, then settles softly. This is why ease-in-out often feels natural in interface work.
Timing functions shape the movement
Timing functions describe the rate of change over time. A linear transition moves at a steady pace. An ease-in transition starts slowly then speeds up. An ease-out starts quickly then slows at the end. Ease-in-out blends both behaviours into a smooth middle curve that often matches the way objects feel in the physical world.
.button {
background: #0066cc;
color: white;
padding: 0.5rem 1rem;
transition: background 0.25s ease-in-out;
}
.button:hover {
background: #004c99;
}
The shift is small, but the timing curve shapes it into something that feels intentional rather than abrupt.
Transitioning multiple properties
When several properties change together, a combined transition keeps them in sync. You can target each property with its own duration and curve or keep a unified timing if the motion should feel like a single action.
.card {
border-radius: 0.5rem;
transform: scale(1);
transition:
transform 0.2s ease-out,
box-shadow 0.2s ease-out;
}
.card:hover {
transform: scale(1.03);
box-shadow: 0 0.5rem 1rem rgba(0,0,0,0.15);
}
Small scale adjustments paired with a soft shadow create the sense of lifting an object slightly off the page.
Simple transforms and motion
Transforms let you shift, rotate, scale or skew an element without affecting the layout around it. These operations are handled by the browser’s compositor and usually feel smooth even on constrained devices. Because transforms do not force reflow, they are ideal for motion that needs to remain responsive.
Moving, scaling and rotating elements
You combine transform functions to create small, expressive moments. These do not require special syntax; the browser composes them into a single transform matrix.
.tile { transition: transform 0.3s ease-in-out; }
.tile:hover {
transform: translateY(-0.25rem) scale(1.02);
}
This tiny lift is enough to signal that an element is interactive while staying modest in motion.
Perspective and 3D transforms
CSS also supports 3D transforms. With perspective and functions such as rotateX() and rotateY(), you can tilt panels or flip cards. These effects require restraint because large rotations can feel abrupt or disorienting unless they serve a clear purpose.
.flip {
transform-style: preserve-3d;
transition: transform 0.6s ease-in-out;
}
.flip:hover {
transform: rotateY(180deg);
}
Use subtle angles for UI work and keep full flips for components that truly benefit from a dramatic reveal.
Animation with keyframes
Transitions only animate between two states. Keyframes open the door to multi-step motion. You define a sequence of frames that vary properties over time; the browser interpolates the steps. Complex effects such as looping pulses, sliding panels or gentle reveals become possible with just a few lines of CSS.
Defining keyframes
A keyframe animation describes how a property changes from the start to the end. Use percentages or keywords like from and to. Any animatable property can appear inside the frames.
@keyframes pulse {
0% { transform: scale(1); }
50% { transform: scale(1.06); }
100% { transform: scale(1); }
}
.pulse {
animation: pulse 1.5s ease-in-out infinite;
}
This creates a slow breathing motion that works well for quiet emphasis without demanding attention.
Controlling playback
The animation shorthand includes duration, delay, timing function, iteration count and direction. For one-off entrances you often keep the count to a single run. For looping shapes such as loading indicators you might choose infinite repetition.
.spinner {
width: 1.5rem;
height: 1.5rem;
border: 0.25rem solid #ccc;
border-top-color: #0066cc;
border-radius: 50%;
animation: spin 0.8s linear infinite;
}
@keyframes spin {
to { transform: rotate(360deg); }
}
The result is light and efficient because only the rotation is being animated.
Making gallery images come alive
A gallery benefits from tiny moments of motion that respond to focus, hover or in-view states. These movements support the content rather than compete with it. A gentle zoom or a tilt can highlight an image and help readers sense that the item is interactive.
A soft zoom that respects layout
Using scale inside a clipping container keeps the movement clean. The image grows slightly within its box without pushing surrounding items.
.gallery figure {
margin: 0;
overflow: hidden;
border-radius: 0.5rem;
}
.gallery img {
display: block;
width: 100%;
height: 100%;
object-fit: cover;
transition: transform 0.35s ease-in-out;
}
.gallery figure:hover img,
.gallery figure:focus-within img {
transform: scale(1.06);
}
This effect looks polished and remains performant because only transforms are animated.
A tilt for personality
A small perspective tilt adds personality, but the angle must remain subtle. Large rotations distract quickly. When used lightly, the movement feels playful yet controlled.
.tilt {
transform: rotateZ(0deg);
transition: transform 0.3s ease-out;
}
.tilt:hover {
transform: rotateZ(2deg);
}
The rotation is small, almost like a photo leaning slightly on a shelf.
Entrance animations that do not overwhelm
If you want images to ease into view, pair opacity with a downward translate. Keep the duration short so the sequence supports scanning rather than slowing it.
@keyframes floatin {
from { opacity: 0; transform: translateY(0.75rem); }
to { opacity: 1; transform: translateY(0); }
}
.gallery figure {
animation: floatin 0.5s ease-out;
}
The image drifts into place with a soft landing. The effect stays quiet even in a large set of photos.