Master CSS Animations: From Simple Transitions to Advanced SVG Loading Effects
This article provides a comprehensive guide to CSS animation techniques, covering basic transition and animation properties, continuous scrolling, bounce effects, like button bursts, SVG‑based loading and progress bars, typing simulations, frame‑by‑frame sprite animations, and the use of steps() for timing control, all illustrated with practical code examples.
Introduction
Web developers often choose between CSS3 transition / animation, setInterval / setTimeout, and requestAnimationFrame for creating animations. For most cases, CSS3 animation offers the best balance of performance and development efficiency.
Common Animation Properties
The article first lists the most frequently used CSS animation properties and then demonstrates several practical demos.
Continuous Scrolling Demo
By animating the transform: translateY of a container, a seamless vertical scrolling effect is achieved. The keyframe definition and CSS rules are:
@keyframes scroll {
0% { transform: translate(0, 0); }
100% { transform: translate(0, -$height); }
}
.ul {
animation-name: scroll;
animation-duration: 5s;
animation-timing-function: linear;
animation-iteration-count: infinite;
}To keep the scroll continuous, duplicate content is added at the end of the list.
Bounce Effect
The bounce animation splits the motion into multiple stages, adjusting the top property at each keyframe. A custom cubic‑bezier curve smooths the motion, and animation-fill-mode: forwards preserves the final state.
@keyframes animate {
0% { top: -100%; opacity: 0; }
25% { top: 60%; opacity: 1; }
50% { top: 48%; opacity: 1; }
75% { top: 52%; opacity: 1; }
100% { top: 50%; opacity: 1; }
}
.popup {
animation-name: animate;
animation-duration: 0.5s;
animation-timing-function: cubic-bezier(0.21, 0.85, 1, 1);
animation-iteration-count: 1;
animation-fill-mode: forwards;
}Like Button Burst Effect
A combination of two @keyframes animations—one for vertical movement and one for horizontal jitter—creates a lively burst when a user clicks the like button. The animations are applied to a dynamically created .bubble element, which is removed after a short timeout.
@keyframes animation-y {
0% { transform: translate(-50%, 100px) scale(0); }
50% { transform: translate(-50%, -100px) scale(1.5); }
100% { transform: translate(-50%, -300px) scale(1.5); }
}
@keyframes animation-x {
0% { margin-left: 0px; }
25% { margin-left: 25px; }
75% { margin-left: -25px; }
100% { margin-left: 0px; }
}
.bubble {
animation: animation-x 3s -2s linear infinite, animation-y 4s 0s linear 1;
}
function like() {
const likeDom = document.createElement('div');
likeDom.className = 'bubble';
document.body.appendChild(likeDom);
setTimeout(() => { document.body.removeChild(likeDom); }, 4000);
}SVG Loading / Progress Bar
Using an SVG circle with stroke-dasharray and stroke-dashoffset, a circular loading animation is built. The dash array is set to the circle’s circumference (≈157) and the offset is animated from 0 to –157 (or –207 for a full‑cycle progress bar).
@keyframes loading {
0% { stroke-dashoffset: 0; }
100% { stroke-dashoffset: -157; }
}
circle { animation: loading 1s 0s ease-out infinite; }Using steps() for Timing Control
The steps() function defines a stepped timing function for animation-timing-function. It accepts a step count and an optional start or end keyword, allowing precise control over when keyframes are applied.
animation-timing-function: steps(5, start);Typing Effect
By setting the container width to match the total character width and applying steps(N) where N equals the number of characters, a typewriter animation is achieved. Consistent character width is ensured by using the Monaco font.
@keyframes animate-x { 0% { width: 0; } }
p {
width: 125px; /* 13 chars × ~9.6px */
overflow: hidden;
border-right: 1px solid transparent;
animation: animate-x 3s 0s steps(13) 1 forwards, cursor-x 0.4s linear infinite;
}Frame‑by‑Frame Sprite Animation
A 47‑frame sprite sheet is animated by shifting the background-position of a .main element. The steps(47) timing function synchronizes the background movement with the frame count.
@keyframes animate {
0% { background-position: 0 0; }
100% { background-position: 0 100%; }
}
.main {
width: 260px;
height: 200px;
background: url(<em>sprite.png</em>) no-repeat;
background-size: 100%;
animation: animate 2s 1s steps(47) infinite alternate;
}References
W3Schools CSS Reference
MDN "will-change" documentation
Various CodePen demos linked in the original article
Aotu Lab
Aotu Lab, founded in October 2015, is a front-end engineering team serving multi-platform products. The articles in this public account are intended to share and discuss technology, reflecting only the personal views of Aotu Lab members and not the official stance of JD.com Technology.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
