Statistics are a huge part of your organization’s story and can help you to differentiate from your competitors, influencing your users by providing specific, quantitive data.
Visualizing your data can help enhance user experience, increase user engagement, and better tell your story.
We’ve talked previously about creating charts for better data visualization, but if your data is better shared as impactful numbers, you can do much more than just using a bold, large font. Instead, why not make your data more visually compelling and eye-catching by animating the numbers when they come in view?
In order to make your numbers animate and count up from 0, we’ll utilize the Intersection Observer API to determine when the section comes into view onscreen and then run a function to make the numbers count up.
In the below HTML, we’ll store the value we want to count up to in a data-number
attribute and put 0 inside the span tag with the class statistics–single__data–number
.
This way, when the section is first displayed on the page, only the number 0 will show, and we’ll use some Javascript to count up to the desired number stored in the data-number
attribute.
<section class="statistics">
<div class="statistics–single">
<div class="statistics–single__data">
<span class="statistics–single__data–number" data-number="97">0</span>%
</div>
</div>
<div class="statistics–single">
<div class="statistics–single__data">
$<span class="statistics–single__data–number" data-number="20">0</span> Million
</div>
</div>
<div class="statistics–single">
<div class="statistics–single__data">
<span class="statistics–single__data–number" data-number="87.93">0</span>%
</div>
</div>
</section>
Any words or characters that should be prepended or appended to the number (ie, % or a descriptor of the amount) can be added outside the span
tags.
Let’s use the Intersection Observer API to determine when the section with the statistics comes into view on the user’s screen. First, we’ll define an observer instance.
var observerInstance = new IntersectionObserver(onIntersection, {
root: null, // default is the viewport
rootMargin: '-40% 0% -40% 0%',
threshold: 0 // percentage of target's visible area. Triggers "onIntersection"
});
In this instance, we’ll define the rootMargin
to be -40% 0% -40% 0%
, which means that the callback function onIntersection
is only called when the section is in the middle 20% of the screen.
Next, let’s add the Javascript to tell the observer instance to look for a span
with class statistics–single__data–number
and to run the callback function when it comes into view.
$('span.statistics–single__data–number').each(function(){
document.querySelectorAll('.statistics–single__data–number').forEach(
i => observerInstance.observe( i )
);
});
Finally, we’ll add the onIntersection
callback function that is called when the section comes into view.
function onIntersection(entries, opts){
entries.forEach(entry => {
if (entry.isIntersecting) {
var dataNumber = entry.target.getAttribute('data-number').split('.');
var fractionDigits = 0;
if (dataNumber[1]) {
var fractionDigits = dataNumber[1].length;
}
let startTimestamp = null;
const step = (timestamp) => {
// Formatter for currency
var formatter = new Intl.NumberFormat('en-US', {maximumFractionDigits: fractionDigits})
if (!startTimestamp) startTimestamp = timestamp;
const progress = Math.min((timestamp - startTimestamp) / duration, 1);
obj.innerHTML = formatter.format(progress * (end - start) + start);
if (progress < 1) {
window.requestAnimationFrame(step);
}
};
window.requestAnimationFrame(step);
opts.unobserve(entry.target);
}
});
}
Let’s break down this code.
First, we determine if the user has scrolled to the content by checking if entry.isIntersecting
; when that happens, we grab the data-number
attribute and, using the split
function, create an array of numbers before and after the decimal point. Then, we create a NumberFormat
object using the Intl.NumberFormat
object and pass the length of the numbers after the decimal point to animate only up to certain decimal points.
When then call the Math.min
function to calculate the next value to display for the number, and the innerHTML
of the span
tag is updated with this number. Then the requestAnimationFrame
function is called to keep animating the number until the target value is reached.
From there, we have our statistics – animating and counting up to their final values – all happening when the user scrolls to the appropriate place on the page.
Here’s how it looks when you visit the website for the Maryland Hospital Association:
Displaying statistics on your website can help capture your user’s attention and better tell your organization’s story. If you need help implementing animated statistics on your website or for any other digital marketing needs, reach out to us.