Pages
Get full access on request after purchase
Buy
custom code

Instructions

global code

Count-up numbers on scroll (GSAP-powered)

This template includes a small global script that animates any element marked with the count-up attribute. When the element scrolls into view, its number counts up from 0 to the value already written in the element, while the text unblurs for a subtle reveal.

The animation is powered by GSAP + ScrollTrigger. The script does not change layouts or styles - it only updates the element’s text content and blur filter during the animation.
How it works (high level)
The script finds every element on the page with the attribute [count-up]. It reads the element’s current text (example: 2,450+ or 98%) and extracts: the numeric value (2450, 98), the suffix (+, %, k, etc.). When the element enters the viewport, it runs once: blur animates from blur(6px) to blur(0px), the number counts up from 0 to the target valueDuring the count-up, the text is updated live and formatted with commas.
How to use it
1. Select a text element that should animate (usually a stat).
2. Add a custom attribute:

Name: count-up
Value: leave empty (or set to true - both are fine)

3. Set the element’s text to your final value, for example:
• 1200
• 2,450+
• 98%
• 12k

4. Publish and scroll to the section - it will animate once when it comes into view.
Where the code lives
The script is added once, globally:
Project Settings → Custom Code
• Place it in the Before  (Footer code) section

Because it’s global, it works on every page and section that uses [count-up]. You do not need to paste it per page.
<script>
gsap.registerPlugin(ScrollTrigger);

document.querySelectorAll("[count-up]").forEach(function(el) {
  var raw = el.textContent.trim();
  var target = parseFloat(raw);
  var suffix = raw.replace(/[\d,\.]/g, "");
  var counter = { val: 0 };

  var tl = gsap.timeline({
    scrollTrigger: {
      trigger: el,
      start: "top 80%",
      once: true
    }
  });

  tl.fromTo(el,
    { filter: "blur(6px)" },
    { filter: "blur(0px)", duration: 2.25, ease: "power2.out" },
    0
  );

  tl.to(counter, {
    val: target,
    duration: 2,
    ease: "power2.out",
    onUpdate: function() {
      el.textContent = Math.round(counter.val).toLocaleString() + suffix;
    }
  }, 0);
});
</script>
Formatting rules (important)
1. Use plain numbers, optionally with a suffix:
• ✅ 2500 2,500 2,500+ 98% 12k
• ✅ commas are fine - the script re-formats the number anyway

2. Avoid currency symbols in front of the number:
• Prefer 2500€ over €2500 (prefix symbols may be treated as suffix and look wrong)

3. Decimals are not supported by default:
• 4.9 will animate, but it will be rounded during counting (it ends as 5)
If you don’t want the blur effect (optional)
Remove the blur animation part:
• Delete (or comment out) the tl.fromTo(el, { filter: ... }, { filter: ... }) block.
• The count-up will still work.
If you don’t want count-up on an element (optional)
• Remove the count-up attribute from that element, or
• Change the element to static text without the attribute.
Important notes
• This runs once per element (once: true) to avoid looping on scroll
• This script requires GSAP + ScrollTrigger to be loaded on the site
• Keep the stat text simple - the script extracts numbers and treats everything else as a suffix.