Animated Number Counter Shortcode
Adds a [wpide_counter to="2500" suffix="+"] shortcode that counts up from zero when the number scrolls into view, for statistics and milestones.
Opens WPIDE on
Code
add_action( 'wp_enqueue_scripts', function () {
wp_register_script( 'wpide-counter', false, array(), '1.0', true );
wp_add_inline_script( 'wpide-counter', <<<'JS'
(function () {
var counters = document.querySelectorAll('.wpide-counter[data-to]');
if (!counters.length) { return; }
var reduce = window.matchMedia && window.matchMedia('(prefers-reduced-motion: reduce)').matches;
function format(el, value) {
var decimals = parseInt(el.getAttribute('data-decimals') || '0', 10);
var text = value.toLocaleString(undefined, { minimumFractionDigits: decimals, maximumFractionDigits: decimals });
el.querySelector('.wpide-counter__value').textContent = text;
}
function run(el) {
var from = parseFloat(el.getAttribute('data-from')) || 0;
var to = parseFloat(el.getAttribute('data-to')) || 0;
var duration = parseInt(el.getAttribute('data-duration') || '1600', 10);
if (reduce) { format(el, to); return; }
var start = null;
function step(time) {
if (start === null) { start = time; }
var p = Math.min(1, (time - start) / duration);
var eased = 1 - Math.pow(1 - p, 3);
format(el, from + (to - from) * eased);
if (p < 1) { requestAnimationFrame(step); }
}
requestAnimationFrame(step);
}
if (!('IntersectionObserver' in window)) { counters.forEach(run); return; }
var io = new IntersectionObserver(function (entries) {
entries.forEach(function (entry) {
if (entry.isIntersecting) { io.unobserve(entry.target); run(entry.target); }
});
}, { threshold: 0.4 });
counters.forEach(function (el) { format(el, parseFloat(el.getAttribute('data-from')) || 0); io.observe(el); });
})();
JS
);
} );
add_shortcode( 'wpide_counter', function ( $atts ) {
$atts = shortcode_atts( array( 'from' => 0, 'to' => 100, 'prefix' => '', 'suffix' => '', 'duration' => 1600, 'decimals' => 0 ), $atts, 'wpide_counter' );
wp_enqueue_script( 'wpide-counter' );
$to = (float) $atts['to'];
$decimals = min( 4, absint( $atts['decimals'] ) );
return sprintf(
'<span class="wpide-counter" data-from="%1$s" data-to="%2$s" data-duration="%3$d" data-decimals="%4$d" style="font-variant-numeric:tabular-nums;">%5$s<span class="wpide-counter__value">%6$s</span>%7$s</span>',
esc_attr( (float) $atts['from'] ),
esc_attr( $to ),
absint( $atts['duration'] ),
$decimals,
esc_html( $atts['prefix'] ),
esc_html( number_format_i18n( $to, $decimals ) ),
esc_html( $atts['suffix'] )
);
} );
Notes
Options: from, to, prefix, suffix, duration (ms) and decimals. Visitors who prefer reduced motion see the final number straight away.
How to add this snippet
- Install WPIDE on your WordPress site (it is free) and open Code Snippets.
- Use snippet above adds it from the library in one click. Or copy the code into a new snippet with the same code type.
- It is added inactive: review the code and settings, then switch it on.