Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

The simplest way to add an animated number in WordPress is to use the counter tool that matches your editor: Elementor’s native Counter widget, the Counting Number Block in Gutenberg, or CountUp.js when you need custom data and behavior. Each route can retain a real static value for accessibility and search engines while animating only the visual change.

Choose the right implementation

Route Works with Setup Control Best use
Elementor Counter widget Elementor Lowest Standard number, prefix, suffix, separator, and duration controls A quick counter on an Elementor page
Counting Number Block Gutenberg (Block Editor) Low; install a plugin Count direction, viewport trigger, formatting, prefixes, and suffixes A no-code counter in a block-based page
CountUp.js Any theme or builder Highest Custom timing, easing, formatting, data sources, and visibility logic A bespoke design or dynamically supplied values

This is a feature-based recommendation, not a comparative performance benchmark. Elementor is quickest on Elementor sites, the block plugin is quickest in Gutenberg, and CountUp.js offers the most implementation control.

# Preview Product Price
1 WordPress 3.0 jQuery WordPress 3.0 jQuery $50.99

Method 1: Add a counter with Elementor

Elementor describes its Counter widget as an element that displays a numeric value that can increase or decrease. Use it when the page is already built with Elementor.

  1. Open the page in Elementor.
  2. Search the widget panel for Counter and drag it into the section or container where the statistic should appear.
  3. In the widget’s content controls, enter the Starting Number and Ending Number.
  4. Add the counter’s title, then configure a Prefix (such as “$”) or Suffix (such as “%” or “+”).
  5. Choose the number separator and set the animation Duration. Elementor documents duration in milliseconds, so use a value such as 2000 for two seconds.
  6. Style the number and title, preview the page at desktop and mobile widths, and publish or update the page.

For several statistics, duplicate the widget inside a row or container and give each counter its own ending value, label, and formatting. Check the completed page with JavaScript disabled or delayed: the ending value should still be understandable rather than leaving an empty statistic.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Method 2: Create a counter in Gutenberg without JavaScript

The WordPress.org Counting Number Block plugin provides a block-editor route. Its listing records version 1.1.0, released June 30, 2024.

  1. In WordPress administration, go to Plugins > Add New Plugin.
  2. Search for Counting Number Block, verify the plugin name and author shown in the directory, and select Install Now.
  3. Select Activate.
  4. Open a post or page in the Site Editor or Block Editor and insert the Counting Number Block.
  5. Set the starting and ending values, then choose whether the number counts up or down.
  6. Configure the prefix, suffix, decimal or grouping formatting, and whether the animation runs once or when the block enters the viewport.
  7. Save or publish, then test the block on the front end.

The block keeps the actual value available to screen readers, and its documented reduced-motion behavior suppresses the animated effect for users who request less motion. Confirm the static value, formatting, and final state in your chosen theme because typography and layout are theme-dependent.

Method 3: Use CountUp.js for custom control

CountUp.js is a dependency-free, MIT-licensed JavaScript class that animates a numerical value by counting to it. It is useful when the number comes from an API, custom fields, WooCommerce data, or another script, or when the design needs timing and easing that a widget does not expose.

1. Add a meaningful target element

Put the final value in the markup so it exists before JavaScript runs. The element’s text is also a sensible fallback if the script fails.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
<span class="stat-number" data-count="12500">12,500</span>
<span class="stat-label">customers served</span>

2. Load the library and initializer correctly

For a theme or plugin, load both files with wp_enqueue_script() from the wp_enqueue_scripts hook, declare dependencies, and use a defer strategy when appropriate. WordPress identifies enqueueing as the recommended way to link JavaScript to a generated page; do not hardcode script tags into theme templates.

A small, page-specific experiment can go in Elementor’s HTML widget, with CSS inside <style> tags and JavaScript inside <script> tags. Elementor Custom Code offers placement, priority, and display-condition controls, but it does not accept PHP.

3. Initialize the counter

document.addEventListener('DOMContentLoaded', function () {
  const target = document.querySelector('.stat-number');
  if (!target || typeof CountUp === 'undefined') return;

  const endValue = Number(target.dataset.count);
  const counter = new CountUp(target, endValue, {
    duration: 2,
    separator: ',',
    decimalPlaces: 0,
    enableScrollSpy: true,
    scrollSpyOnce: true
  });

  if (!counter.error) counter.start();
});

CountUp.js supports duration, easing, decimal and grouping formats, and an auto-animation option based on IntersectionObserver, which starts the effect when the element becomes visible. Match the option names to the CountUp.js version you load, and check counter.error when diagnosing initialization failures.

Accessibility and reduced-motion requirements

Keep the real value in the HTML

Do not make the statistic depend entirely on rapidly changing text. A meaningful value in the original markup gives search engines and assistive technology a usable result before JavaScript loads. Avoid using the changing counter as an aria-live announcement; announcing every intermediate number can overwhelm screen-reader users.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Honor the operating-system motion preference

WordPress accessibility guidance advises being mindful of vestibular disorders and placing animation and transition rules behind @media not (prefers-reduced-motion). For custom code, skip the animation when the preference is enabled:

const reduceMotion = window.matchMedia('(prefers-reduced-motion: reduce)').matches;
if (reduceMotion) {
  target.textContent = target.dataset.count;
} else {
  counter.start();
}

The Counting Number Block documents disabling its animated effect in reduced-motion mode. With Elementor, provide a static, readable number and verify the widget’s behavior in your current version rather than assuming every animation setting is automatically accessible.

Test realistic content

  • Use prefixes, suffixes, decimal points, and grouping separators together.
  • Test short and very long numbers so the layout does not shift or overflow.
  • Check the value before JavaScript loads, during the animation, and after it finishes.
  • Use keyboard navigation and a screen reader to confirm that the statistic has a useful label.
  • Test with reduced motion enabled and with JavaScript blocked or delayed.
Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Support on Ko-Fi

WordPress script-loading pattern for a theme or plugin

Use an enqueue function instead of inserting a script tag directly into a template:

add_action('wp_enqueue_scripts', function () {
    wp_enqueue_script(
        'countup',
        plugins_url('assets/countUp.umd.js', __FILE__),
        array(),
        '2.9.0',
        array('strategy' => 'defer', 'in_footer' => true)
    );

    wp_enqueue_script(
        'site-counters',
        plugins_url('assets/counters.js', __FILE__),
        array('countup'),
        '1.0.0',
        array('strategy' => 'defer', 'in_footer' => true)
    );
});

Adjust the file paths and versions to the files actually installed in your project. Declaring CountUp as a dependency ensures the initializer runs after the library is available.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Troubleshoot a counter that does not work

The number is blank

  • Inspect the front-end HTML and confirm that the target element contains a fallback value.
  • Open the browser console and check for a missing library, selector mismatch, or JavaScript syntax error.
  • Confirm that the initializer runs after the DOM exists and after CountUp.js has loaded.

The counter never starts on scroll

  • Make sure the target is not hidden by a parent with display: none when the observer is created.
  • Check that the element enters the viewport and that the selected “once” or repeat behavior matches your intent.
  • Test an ordinary start without viewport detection to isolate an observer or layout issue.

Formatting or layout is wrong

  • Check whether the prefix or suffix is part of the value or a separate field.
  • Verify decimal and grouping separators for the intended locale.
  • Reserve enough width for the largest value to prevent nearby content from jumping.

Which approach should you use?

Use Elementor’s Counter widget when the page is built in Elementor and standard controls are sufficient. Use Counting Number Block when you work in Gutenberg and want a no-code block with documented viewport and reduced-motion behavior. Choose CountUp.js when values arrive from code or the animation needs custom easing, formatting, or visibility logic. In every case, publish a readable static value first and treat the animation as progressive enhancement.

Quick Recap

Bestseller No. 1

Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.