Free Animated Number Counter for Squarespace (7.0 & 7.1) - No Plugins Required

Adding simple animated numbers that count up to website

Add Professional Counting Animations to Your Squarespace Website in 5 Minutes

Are you looking to add eye-catching animated number counters to your Squarespace website? Whether you want to showcase your client count, project milestones, success rates, or years of experience, this free animated counter widget is exactly what you need.

Unlike expensive Squarespace plugins or third-party integrations, this solution is completely free, requires no coding knowledge, and works seamlessly with both Squarespace 7.0 and 7.1.


What Is an Animated Number Counter?

An animated number counter is a dynamic visual element that counts from one number to another when visitors scroll to that section of your website. These counters are perfect for:

  • Portfolio websites showcasing completed projects

  • Business websites highlighting client testimonials and success metrics

  • Agency websites displaying years of experience and team size

  • E-commerce stores showing product sales or customer satisfaction rates

  • Service providers demonstrating expertise through statistics


Why Use Animated Counters on Your Squarespace Website?

1. Increase Visitor Engagement

Animated elements naturally draw the eye and keep visitors on your page longer, reducing bounce rates and improving SEO performance.

2. Build Trust & Credibility

Displaying real numbers about your business (clients served, projects completed, success rates) establishes social proof and builds credibility with potential customers.

3. Enhance Your Design

Modern, smooth animations make your Squarespace templates look more professional and polished without requiring custom development.

4. No Plugin Costs

Save money on expensive Squarespace plugins this solution is 100% free and doesn't require any subscriptions or recurring fees.


Features of This Free Squarespace Counter Widget

  • Works with Squarespace 7.0 & 7.1 - Compatible with all versions

  • Auto-Detects Your Template Styles - Automatically matches your fonts and colors

  • Fully Responsive - Looks perfect on desktop, tablet, and mobile devices

  • Scroll-Triggered Animation - Counts only when visitors scroll to the section

  • Repeat Animation Option - Counter restarts every time you scroll back

  • Multiple Format Options - Integers, decimals, compact format (1.2K, 2.5M)

  • Prefix & Suffix Support - Add $, %, +, K, M and more

  • Accessible & SEO-Friendly - Screen reader compatible with proper ARIA labels

  • Zero Dependencies - No external libraries or bloated code

  • Performance Optimized - Uses requestAnimationFrame for smooth 60fps animations


How to Add Animated Counters to Your Squarespace Website

Step 1: Add a Code Block

  1. Log into your Squarespace dashboard

  2. Navigate to the page where you want to add counters

  3. Click the + Add Block button

  4. Search for and select Code Block

Step 2: Copy the Widget Code

Scroll down to the code section below and copy the complete code (HTML, CSS, and JavaScript).

Step 3: Paste and Customize

  1. Paste the code into your Code Block

  2. Customize the numbers, labels, and animations

  3. Save your changes

  4. Preview your page to see the counters in action

That's it! Your animated counters are now live on your Squarespace website.


Customization Options

Change the Numbers

Edit the data-end attribute to change your target number:

<div class="counter-number" data-end="5000">0</div>

Add Prefix or Suffix

Use data-prefix for symbols before the number (like $) or data-suffix for symbols after (%):

<div class="counter-number" data-end="98" data-suffix="%">0</div>

Adjust Animation Speed

Change data-duration (in milliseconds) to make animations faster or slower:

<div class="counter-number" data-duration="3000">0</div>

Enable Repeat Animation

Add data-repeat="true" to make counters animate every time visitors scroll to them:

<div class="counter-number" data-repeat="true">0</div>

Compact Number Format

Use data-format="compact" to display large numbers as 1.2K or 2.5M:

<div class="counter-number" data-end="15000" data-format="compact">0</div>


Perfect Use Cases for Your Squarespace Website

For Business & Corporate Websites

  • Years in business

  • Total clients served

  • Projects completed

  • Team members

  • Office locations

For Portfolio & Creative Sites

  • Design projects

  • Happy clients

  • Awards won

  • Creative hours logged

For E-commerce Stores

  • Products sold

  • Customer satisfaction rate

  • Countries shipped to

  • Five-star reviews

For Service Providers

  • Successful campaigns

  • Client retention rate

  • Industry certifications

  • Combined years of experience


Why Choose SquareSpell for Your Squarespace Needs?

At Squarespell.com, we provide free tools, resources, and expert Squarespace website services to help you create stunning websites without breaking the bank.

Our Services Include:

  • Custom Squarespace Templates - Professional, conversion-optimized designs

  • Squarespace Plugins & Integrations - Free and premium tools to extend functionality

  • Website Design Services - Full-service Squarespace website development

  • Technical Support - Expert help with customization and troubleshooting

  • Free Resources - Code snippets, tutorials, and widgets like this counter

Whether you need help choosing the right Squarespace templates, integrating custom features, or building your entire website from scratch, our team of Squarespace experts is here to help.


Complete Widget Code (Free to Use)

Copy the complete code below and paste it into a Squarespace Code Block:

DEMO:

0
Happy Clients
0
Projects
0
Success Rate
0
Years Experience
<!DOCTYPE html>
<!-- MIT License - Free to use, modify, and distribute -->
<!-- Animated Number Counter Widget for Squarespace 7.0 & 7.1 -->
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<style>
/* Remove Squarespace extra spacing */
html.squarespace-damask .sqs-blockStatus,
.sqs-block .removed-script {
  display: none !important;
}

/* Counter container reset - eliminates top/bottom gaps */
.animated-counter-wrapper {
  margin: 0 !important;
  padding: 0 !important;
  font: inherit;
  color: inherit;
}

/* Horizontal layout with responsive wrapping */
.counter-grid {
  display: flex;
  flex-wrap: wrap;
  gap: var(--counter-gap, 2rem);
  align-items: center;
  justify-content: center;
  font: inherit;
  color: inherit;
  margin: 0;
  padding: 0;
}

/* Individual counter item */
.counter-item {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0.5rem;
  min-width: 120px;
  font: inherit;
  color: inherit;
}

/* Counter number display */
.counter-number {
  font-size: 2.5em;
  font-weight: 700;
  line-height: 1;
  font-family: inherit;
  color: inherit;
  letter-spacing: -0.02em;
}

/* Counter label */
.counter-label {
  font-size: 0.875em;
  font-weight: 400;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  opacity: 0.7;
  font-family: inherit;
  color: inherit;
  text-align: center;
}

/* Optional divider between counters */
.counter-divider {
  width: 1px;
  height: 3rem;
  background: currentColor;
  opacity: 0.15;
  align-self: center;
}

/* Responsive adjustments */
@media (max-width: 768px) {
  .counter-grid {
    gap: var(--counter-gap, 1.5rem);
  }
  
  .counter-number {
    font-size: 2em;
  }
  
  .counter-divider {
    display: none;
  }
}

/* Animation state */
.counter-number[data-animating="true"] {
  transition: opacity 0.3s ease;
}

/* Accessibility: reduced motion support */
@media (prefers-reduced-motion: reduce) {
  .counter-number {
    transition: none !important;
  }
}
</style>
</head>
<body>

<!-- FIXED: Counters now repeat every time you scroll to them -->
<div class="animated-counter-wrapper">
  <div class="counter-grid">
    <div class="counter-item">
      <div class="counter-number" 
           data-start="0" 
           data-end="1250" 
           data-duration="2000"
           data-trigger="scroll"
           data-repeat="true"
           aria-live="polite">0</div>
      <div class="counter-label">Happy Clients</div>
    </div>
    
    <div class="counter-divider"></div>
    
    <div class="counter-item">
      <div class="counter-number" 
           data-start="0" 
           data-end="3500" 
           data-duration="2500"
           data-trigger="scroll"
           data-repeat="true"
           aria-live="polite">0</div>
      <div class="counter-label">Projects</div>
    </div>
    
    <div class="counter-divider"></div>
    
    <div class="counter-item">
      <div class="counter-number" 
           data-start="0" 
           data-end="98" 
           data-duration="1800"
           data-suffix="%"
           data-trigger="scroll"
           data-repeat="true"
           aria-live="polite">0</div>
      <div class="counter-label">Success Rate</div>
    </div>
    
    <div class="counter-divider"></div>
    
    <div class="counter-item">
      <div class="counter-number" 
           data-start="0" 
           data-end="15" 
           data-duration="2200"
           data-suffix="+"
           data-trigger="scroll"
           data-repeat="true"
           aria-live="polite">0</div>
      <div class="counter-label">Years Experience</div>
    </div>
  </div>
</div>

<script>
(function() {
  'use strict';

  // Configuration defaults
  const DEFAULTS = {
    start: 0,
    end: 100,
    duration: 2000,
    format: 'int',
    prefix: '',
    suffix: '',
    autoplay: true,
    trigger: 'scroll',
    easing: 'easeOutCubic'
  };

  // Easing functions
  const easings = {
    linear: t => t,
    easeOutCubic: t => 1 - Math.pow(1 - t, 3),
    easeInOutCubic: t => t < 0.5 ? 4 * t * t * t : 1 - Math.pow(-2 * t + 2, 3) / 2,
    easeOutQuad: t => 1 - (1 - t) * (1 - t)
  };

  // Number formatting utilities
  function formatNumber(value, format, decimals = 1) {
    switch(format) {
      case 'decimal':
        return value.toFixed(decimals);
      case 'compact':
        return compactFormat(value);
      case 'int':
      default:
        return Math.round(value).toLocaleString();
    }
  }

  function compactFormat(num) {
    if (num >= 1000000) {
      return (num / 1000000).toFixed(1) + 'M';
    } else if (num >= 1000) {
      return (num / 1000).toFixed(1) + 'K';
    }
    return num.toLocaleString();
  }

  // Counter animation class
  class AnimatedCounter {
    constructor(element) {
      this.element = element;
      this.config = this.parseConfig();
      this.hasAnimated = false;
      this.animationId = null;
      
      // Set initial value
      this.updateDisplay(this.config.start);
      
      // Initialize based on trigger
      if (this.config.trigger === 'immediate' && this.config.autoplay) {
        this.animate();
      } else if (this.config.trigger === 'scroll') {
        this.setupIntersectionObserver();
      }
    }

    parseConfig() {
      const dataset = this.element.dataset;
      return {
        start: parseFloat(dataset.start || DEFAULTS.start),
        end: parseFloat(dataset.end || DEFAULTS.end),
        duration: parseInt(dataset.duration || DEFAULTS.duration, 10),
        format: dataset.format || DEFAULTS.format,
        prefix: dataset.prefix || DEFAULTS.prefix,
        suffix: dataset.suffix || DEFAULTS.suffix,
        autoplay: dataset.autoplay !== 'false',
        trigger: dataset.trigger || DEFAULTS.trigger,
        easing: dataset.easing || DEFAULTS.easing
      };
    }

    setupIntersectionObserver() {
      const options = {
        threshold: 0.3,
        rootMargin: '0px'
      };

      const repeat = this.element.dataset.repeat === 'true';

      this.observer = new IntersectionObserver((entries) => {
        entries.forEach(entry => {
          if (entry.isIntersecting && this.config.autoplay) {
            // Cancel any ongoing animation
            if (this.animationId) {
              cancelAnimationFrame(this.animationId);
            }
            
            // Reset state for repeat mode or first-time animation
            if (repeat || !this.hasAnimated) {
              this.hasAnimated = false;
              this.element.setAttribute('data-animating', 'false');
              this.updateDisplay(this.config.start);
              
              // Animate with small delay
              setTimeout(() => {
                this.animate();
              }, 100);
            }
            
            // Only disconnect observer if not in repeat mode
            if (!repeat && this.hasAnimated) {
              this.observer.disconnect();
            }
          } else if (!entry.isIntersecting && repeat) {
            // Stop animation when scrolled out of view in repeat mode
            if (this.animationId) {
              cancelAnimationFrame(this.animationId);
            }
            this.hasAnimated = false;
            this.element.setAttribute('data-animating', 'false');
            this.updateDisplay(this.config.start);
          }
        });
      }, options);

      this.observer.observe(this.element);
    }

    animate() {
      const repeat = this.element.dataset.repeat === 'true';
      
      // Only block repeat animations if not in repeat mode
      if (this.hasAnimated && !repeat) return;
      
      this.hasAnimated = true;
      this.element.setAttribute('data-animating', 'true');
      
      const { start, end, duration, easing } = this.config;
      const startTime = performance.now();
      const easingFn = easings[easing] || easings.easeOutCubic;
      
      const step = (currentTime) => {
        const elapsed = currentTime - startTime;
        const progress = Math.min(elapsed / duration, 1);
        const easedProgress = easingFn(progress);
        
        const currentValue = start + (end - start) * easedProgress;
        this.updateDisplay(currentValue);
        
        if (progress < 1) {
          this.animationId = requestAnimationFrame(step);
        } else {
          this.element.setAttribute('data-animating', 'false');
          this.updateDisplay(end); // Ensure final value is exact
        }
      };
      
      this.animationId = requestAnimationFrame(step);
    }

    updateDisplay(value) {
      const { format, prefix, suffix } = this.config;
      const decimals = format === 'decimal' ? (this.config.end.toString().split('.')[1]?.length || 1) : 0;
      const formatted = formatNumber(value, format, decimals);
      this.element.textContent = `${prefix}${formatted}${suffix}`;
    }

    destroy() {
      if (this.observer) {
        this.observer.disconnect();
      }
      if (this.animationId) {
        cancelAnimationFrame(this.animationId);
      }
    }
  }

  // Initialize all counters on the page
  function initCounters() {
    const counterElements = document.querySelectorAll('.counter-number[data-end]');
    const counters = [];
    
    counterElements.forEach(element => {
      if (!element.dataset.initialized) {
        counters.push(new AnimatedCounter(element));
        element.dataset.initialized = 'true';
      }
    });
    
    return counters;
  }

  // Initialize when DOM is ready
  if (document.readyState === 'loading') {
    document.addEventListener('DOMContentLoaded', initCounters);
  } else {
    initCounters();
  }

  // Re-initialize on Squarespace AJAX page loads
  window.addEventListener('mercury:load', initCounters);

})();
</script>

</body>
</html>

Advanced Customization Tips

Change Counter Spacing

.counter-grid { --counter-gap: 3rem; }

Modify Number Size

.counter-number { font-size: 3em; }

Change to Vertical Layout

.counter-grid { flex-direction: column; }

Add Custom Colors

.counter-number { color: #ff6b6b; }

.counter-label { color: #333; }


Upgrade to Premium: Advanced Animated Counters

0
Happy Clients
0
Projects
0
Success Rate
0
Years Experience

Want to take your statistics to the next level? Our Premium Animated Counter Widget includes everything in the free version plus advanced features that make your numbers stand out. You get stunning glassmorphic cards with backdrop blur effects, smooth scroll-triggered animations that engage visitors, auto-repeat functionality, customizable SVG icons to match your brand, elegant hover effects with gradient glows, and prefix/suffix support for adding %, +, or $ symbols. The premium version is lightweight, loads fast, and works perfectly on all devices. Perfect for agencies, portfolios, and businesses that want professional-grade statistics display.

PURCHASE

Troubleshooting Common Issues

Counters Not Animating

  • Check that data-end attribute is set on each counter

  • Clear your Squarespace cache (Settings > Advanced > Clear Cache)

  • Ensure JavaScript is enabled in your browser

Styling Looks Different

The widget inherits your Squarespace template styles automatically. If you want to override them, add custom CSS to the Code Block.

Multiple Counters Interfering

Make sure each counter has unique data-end values and proper HTML structure.

Performance Issues

The widget is highly optimized, but if you have many counters on one page, consider using data-trigger="immediate" on some to stagger animations.


SEO Benefits of Using Animated Counters

Adding animated counters to your Squarespace website can improve your SEO performance in several ways:

  1. Reduced Bounce Rate - Engaging animations keep visitors on your page longer

  2. Increased Dwell Time - Users spend more time reading your statistics

  3. Better User Experience - Modern, professional design improves overall site quality

  4. Social Proof Signals - Statistics help establish authority and trustworthiness

  5. Mobile Optimization - Responsive design improves mobile SEO rankings


Frequently Asked Questions

  • Yes! This widget is 100% free to use on your Squarespace website. No hidden costs, no subscriptions, no attribution required.

  • No. Simply copy and paste the code into a Squarespace Code Block. We provide step-by-step instructions that anyone can follow.

  • No. The widget is lightweight and performance-optimized using modern web APIs. It won't affect your page load speed.

  • Absolutely! You can add as many counters as you need. The widget handles multiple instances automatically.

  • Yes. The counters are fully responsive and work perfectly on all devices, including smartphones and tablets.

  • Yes. The widget automatically matches your Squarespace templates styling, but you can easily override colors, sizes, and layouts with custom CSS.


Need Help with Your Squarespace Website?

If you need assistance implementing this counter widget or want help with other aspects of your Squarespace website, our team at SquareSpell is here to help.

Our Expert Services:

Custom Website Design - Let us build a stunning Squarespace website tailored to your brand

Template Customization - We'll modify existing Squarespace templates to match your vision perfectly

Plugin Integration - Need custom Squarespace plugins or advanced features? We've got you covered

Website Migration - Moving from another platform? We'll handle the entire migration process

Ongoing Support - Monthly maintenance and support packages available

CONTACT US →

Conclusion

Adding animated number counters to your Squarespace website is one of the easiest ways to make your site more engaging and professional. This free widget gives you enterprise-level functionality without requiring expensive Squarespace plugins or developer expertise.

Whether you're showcasing your business statistics, portfolio achievements, or e-commerce success, these animated counters will help you build trust and credibility with your visitors.

Ready to elevate your Squarespace website?

Copy the code above, paste it into your site, and watch your statistics come to life. And if you need help with Squarespace templates, custom development, or professional Squarespace website services, remember that SquareSpell is your trusted partner for all things Squarespace.

Next
Next

The Complete Guide to Adding an Interactive Quiz Plugin to Your Squarespace Website (Lifetime Access, Zero Subscriptions, Professional Results)