Jump to content

Animation once the section is in the viewport

Recommended Posts

Site URL: https://viola-iguana-ezk8.squarespace.com

Hi all,


I would like to animate a Counter once the section is in the viewport. I managed to get the animation, but it happens even when the section is not displayed, so by the time the user is scrolling on the page, the counter animation is over.


I am ok with coding, but I am quite new with html and javascript, so I need some help to code it.

Here is my code section highly inspired by this webpage:


Thank you very much for your help.



<div class="wrapper">
    <div class="counter col_fifth">
      <i class="fa fa-drivers-license-o"></i>
      <h2 class="timer count-title count-number" data-to="6" data-speed="4000"></h2>
       <p class="count-text ">Staff Members</p>

    <div class="counter col_fifth">
      <i class="fas fa-microscope"></i>
      <h2 class="timer count-title count-number" data-to="21" data-speed="4000"></h2>
      <p class="count-text ">Microscopes</p>

    <div class="counter col_fifth">
      <i class="fas fa-user-graduate"></i>
      <h2 class="timer count-title count-number" data-to="54" data-speed="4000"></h2>
      <p class="count-text ">Trained Users</p>

    <div class="counter col_fifth">
      <i class="fa fa-eye"></i>
      <h2 class="timer count-title count-number" data-to="27397" data-speed="4000"></h2>
      <p class="count-text ">Hours of Microscope Usage this year</p>
      <div class="counter col_fifth end">
      <i class="fas fa-chalkboard-teacher"></i>
      <h2 class="timer count-title count-number" data-to="3715" data-speed="4000"></h2>
      <p class="count-text ">Hours of Workstation Usage this year</p>


 (function ($) {
  $.fn.countTo = function (options) {
    options = options || {};
    return $(this).each(function () {
      // set options for current element
      var settings = $.extend({}, $.fn.countTo.defaults, {
        from:            $(this).data('from'),
        to:              $(this).data('to'),
        speed:           $(this).data('speed'),
        refreshInterval: $(this).data('refresh-interval'),
        decimals:        $(this).data('decimals')
      }, options);
      // how many times to update the value, and how much to increment the value on each update
      var loops = Math.ceil(settings.speed / settings.refreshInterval),
        increment = (settings.to - settings.from) / loops;
      // references & variables that will change with each update
      var self = this,
        $self = $(this),
        loopCount = 0,
        value = settings.from,
        data = $self.data('countTo') || {};
      $self.data('countTo', data);
      // if an existing interval can be found, clear it first
      if (data.interval) {
      data.interval = setInterval(updateTimer, settings.refreshInterval);
      // initialize the element with the starting value
      function updateTimer() {
        value += increment;
        if (typeof(settings.onUpdate) == 'function') {
          settings.onUpdate.call(self, value);
        if (loopCount >= loops) {
          // remove the interval
          value = settings.to;
          if (typeof(settings.onComplete) == 'function') {
            settings.onComplete.call(self, value);
      function render(value) {
        var formattedValue = settings.formatter.call(self, value, settings);
  $.fn.countTo.defaults = {
    from: 0,               // the number the element should start at
    to: 0,                 // the number the element should end at
    speed: 100,           // how long it should take to count between the target numbers
    refreshInterval: 100,  // how often the element should be updated
    decimals: 0,           // the number of decimal places to show
    formatter: formatter,  // handler for formatting the value before rendering
    onUpdate: null,        // callback method for every time the element is updated
    onComplete: null       // callback method for when the element finishes updating
  function formatter(value, settings) {
    return value.toFixed(settings.decimals);

jQuery(function ($) {
  // custom formatting example
  $('.count-number').data('countToOptions', {
  formatter: function (value, options) {
    return value.toFixed(options.decimals).replace(/\B(?=(?:\d{3})+(?!\d))/g, ',');
  // start all the timers
  function count(options) {
  var $this = $(this);
  options = $.extend({}, options || {}, $this.data('countToOptions') || {});


Link to comment
  • Replies 5
  • Views 2.2k
  • Created
  • Last Reply

Since you are familar with coding I will help you a bit since your site is password protected

replace the line 


$.fn.isInViewport = function() {
    var elementTop = $(this).offset().top;
    var elementBottom = elementTop + $(this).outerHeight();

    var viewportTop = $(window).scrollTop();
    var viewportBottom = viewportTop + $(window).height();

    return elementBottom > viewportTop && elementTop < viewportBottom;

$(window).on('resize scroll', function() {
    if ($('.timer').isInViewport()) {


javascript - Jquery check if element is visible in viewport - Stack Overflow

BeyondSpace - Squarespace Website Developer

🖼️ Lightbox Studio (Enable Pinch/Zoom on lightbox)
🗓️ Delivery Date Picker (Squarespace Date picker form field)
💫 Gallery block 7.1 workaround
🥳 Sparkplugin Customisations Browsers (Browse +100 Spark plugin customisations)
🥳 Elfsight Template Browsers (Browse +1000 Elfsight widget Templates)

If you find my answer useful, let's leave a like or upvote so others with the same issue can find their solution. Thank you!


Link to comment
  • 2 weeks later...


This topic is now archived and is closed to further replies.

  • Create New...

Squarespace Webinars

Free online sessions where you’ll learn the basics and refine your Squarespace skills.

Hire a Designer

Stand out online with the help of an experienced designer or developer.