
Watch Those Numbers Dance: How to Animate Value Changes on Your Website with CSS
As a graphic designer, I’m obsessed with creating websites that feel alive. That doesn’t mean glitter explosions (unless that’s your brand) — it means thoughtful movement. Subtle animations. Micro-interactions that spark joy.
One of my favorite little tricks? Making numbers change dynamically on your site — like a counter that ticks up when it comes into view. Think “Revenue: $1,000,000” climbing up instead of just appearing. It adds a sense of progress, excitement, and life to your data.
And good news — you don’t need heavy JavaScript to get started. Here’s how to animate number changes with CSS and just a sprinkle of JavaScript.
🔢 Why Animate Numbers?
Your brain loves movement — it notices it. When a number ticks up or changes, it’s like a visual cue that says:
“Hey! Something good is happening here.”
This works especially well for:
- Stats on your homepage (like happy customers or total donations)
- Progress bars or goals
- Pricing discounts or countdowns
💻 The Code: CSS + a Touch of JS
Unfortunately, CSS alone can’t animate numbers like $0 → $1,000. But we can style them with CSS and animate the value with a teeny JavaScript function.
Here’s how:
1. HTML: Your Number Wrapper
<div class="stat">
<span class="number" data-target="1000">0</span>+
</div>
2. CSS: Make It Pretty (and Optional Animation Styles)
.stat {
font-size: 2rem;
font-weight: bold;
font-size: 50px;
color: #5700FF;
}
.number {
transition: all 0.3s ease-in-out;
}
3. JavaScript: Animate the Value Change
<script>
document.addEventListener("DOMContentLoaded", () => {
const counters = document.querySelectorAll('.number');
const animateCounter = (counter) => {
const target = +counter.getAttribute('data-target');
const duration = 6000; // total animation time in ms
const frameRate = 60;
const totalFrames = Math.round(duration / (1000 / frameRate));
const increment = target / totalFrames;
let current = 0;
let frame = 0;
const animate = () => {
frame++;
current += increment;
if (frame < totalFrames) {
counter.innerText = Math.ceil(current);
requestAnimationFrame(animate);
} else {
counter.innerText = target;
}
};
animate();
};
const observer = new IntersectionObserver((entries, observer) => {
entries.forEach(entry => {
if (entry.isIntersecting) {
animateCounter(entry.target);
observer.unobserve(entry.target); // Only animate once
}
});
}, {
threshold: 1 // Starts animation when 100% of the number is visible
});
counters.forEach(counter => {
observer.observe(counter);
});
});
</script>
✅ Bonus: This uses Intersection Observer to only animate the number when it scrolls into view — no wasted animations!
Example:
🎨 Designer Tips
- Font choice matters — Use a monospaced or numeric-friendly font if you want that classic “ticker” feel.
- Color contrast — Make your numbers pop (but check accessibility!). Use tools like Able for WCAG contrast checks.
- Don’t overdo it — One or two animated stats per page is magical. A dozen? Feels like a game show.
✨ Final Thoughts
Animating numbers is a small touch that makes a big impression. It’s one of those designer details that says, “We care about experience.” Try it out on your own site or a client project, and watch how something as simple as $0 → $1000 can feel so satisfying.
If you give this a try or want help implementing it in your brand’s style, I’m all ears — and keyboards.