Counter Up
Complete deployment and configuration reference for mod_lgx_counter_up v3.0.0 — a scroll-triggered animated counter module built on Joomla’s modern namespaced extension API.
On This Page
- Overview
- System Requirements
- Installation
- File Structure
- Counter Items (Subform)
- Basic Settings Tab
- Responsive Control Tab
- Style Settings Tab
- Section Settings Tab
- Section Header
- Advanced Tab
- Layout Order Reference
- Hover Effects Reference
- Template Override
- Custom CSS Field
- Architecture Notes
- CSS Class Reference
- FAQ
01 Overview
Counter Up is a site-side Joomla module (mod_lgx_counter_up) that animates numbers from zero up to their target value the instant they scroll into the visitor’s viewport. The counting engine uses jQuery Waypoints to detect viewport intersection and a custom counter library (custom-counter.min.js) to perform the animation. All per-module styles are injected as scoped CSS declarations tied to the module’s unique ID, so multiple instances on a single page never conflict.
Version 3.0.0 rebuilds the extension on Joomla’s modern extension API: a PSR-4 namespaced class tree under LogicHunt\Module\CounterUp, a DI service provider in services/provider.php, and a typed Dispatcher that extends AbstractModuleDispatcher. This makes the module fully forward-compatible with Joomla 4, 5, and 6.
bottom-in-view; counter runs once and the waypoint destroys itself — no repeated animations on scroll-back.#mod_lgx_counter_up{ID}. Multiple module instances on one page are always isolated.
02 System Requirements
| Component | Minimum | Notes |
|---|---|---|
| Joomla | 4.0 | Compatible with Joomla 4, 5, and 6. Manifest tagged Joomla 6 compatible. |
| PHP | 7.4 | PHP 8.x recommended. Uses namespaces, typed properties, and modern array functions. |
| jQuery | 1.x | Loaded via HTMLHelper::_('jquery.framework'); Joomla handles deduplication automatically. |
| Browser | Any modern | Waypoints uses IntersectionObserver-compatible technique; graceful degradation on older browsers. |
| Install method | — | Standard Joomla Extension Manager upload. Manifest uses method="upgrade" for safe over-install. |
03 Installation
- Download the package. You will have a ZIP file named
mod_lgx_counter_up_v3_0_j6_x.zip. Do not unzip it before uploading. - Open the Extension Manager. In your Joomla administrator, navigate to System → Install → Extensions.
- Upload and install. Use the Upload Package File tab. Select the ZIP file and click Upload & Install. Joomla will process the manifest and copy all files to
/modules/mod_lgx_counter_up/. - Enable the module. Go to Content → Site Modules. Find Counter Up by LogicHunt.com in the list, open it, and set Status to Published.
- Assign a position and pages. Select a module position and use the Menu Assignment tab to control which pages display the module.
- Add counter items. Open the Item Source tab, click Add New Item, and configure each counter’s value, title, icon, and description.
- Save and verify. Click Save & Close, then visit the front end to confirm the animation fires on scroll.
LogicHunt provides a complimentary installation service for customers who prefer hands-off setup. Contact [email protected] with your site credentials and the ZIP file.
Update Server
The manifest registers an update server so Joomla notifies you of new releases automatically:
Updates appear in System → Update → Extensions. Running the updater is safe — method="upgrade" preserves all existing module parameters.
04 File Structure
├── mod_lgx_counter_up.php Entry point — boots module via app service layer
├── mod_lgx_counter_up.xml Manifest — params, namespace, files, update server
├── src/
│ ├── Dispatcher/
│ │ └── Dispatcher.php Extends AbstractModuleDispatcher — prepares all template vars
│ └── Helper/
│ └── LgxCounterUpHelper.php Static helpers: source parser, randomizer, hex2rgba, grid calc
├── services/
│ └── provider.php DI service provider — registers Dispatcher, Helper, Module
├── tmpl/
│ └── default.php Front-end template — renders HTML + inline JS waypoint init
├── fields/
│ ├── extra-field.xml Subform schema — 5 fields per counter item
│ └── lgxcountersubform.php Custom subform field renderer
├── assets/
│ ├── asset.php Asset registration — CSS, JS, scoped inline styles
│ ├── css/
│ │ ├── style.min.css Compiled production stylesheet (loaded on front end)
│ │ ├── flexbox.min.css Flexbox grid utilities
│ │ └── _hover_effect.min.css Six hover effect classes
│ ├── libs/
│ │ ├── counter/
│ │ │ └── custom-counter.min.js Counter animation engine (window.counterUp)
│ │ └── wayp/
│ │ └── jquery.waypoints.min.js Viewport detection library
│ ├── less/ LESS source files for style customisation
│ └── img/
│ └── default.jpg Default section background image
└── language/en-GB/
├── en-GB.mod_lgx_counter_up.ini
└── en-GB.mod_lgx_counter_up.sys.ini
All PHP classes live under LogicHunt\Module\CounterUp, registered at path src/ in the manifest. The entry point boots the module via $app->bootModule('mod_lgx_counter_up', 'Site')->getDispatcher($module, $app)->dispatch() — no direct static calls.
05 Counter Items (Item Source Tab)
Counter items are managed through a native Joomla subform repeater field (lgx_counter_up_repeat_field). The subform supports a minimum of 1 and a maximum of 1,000 items. Click Add New Item to append a row. Each row contains the following fields:
| Field | Type | Description |
|---|---|---|
| Active | Radio (Yes/No) | When set to No, the item is skipped in the front-end loop entirely. Default: Yes. |
| Icon | Media Picker | Selects an image from the Joomla media manager. Rendered as <img> inside .lgx_cu_thumb. Leave blank to suppress the icon element entirely. |
| Count Value | Text | The target number the counter animates toward. Accepts integers (1234), floats (1.234), comma-formatted values (1,234.56), currency strings ($1,234.56), or compound expressions (604,800 seconds in 7 days). The counter engine auto-parses the format. |
| Title | Text | Displayed as an <h3> element inside .lgx_cu_title. Leave blank to suppress the title element. |
| Description | Textarea (raw HTML) | Accepts raw HTML. Rendered inside .lgx_cu_desc. Leave blank to suppress the description element. Filter is set to raw — HTML tags and entities pass through unescaped. |
The Description field uses filter="raw". Any HTML you enter is output verbatim. Sanitise user-submitted content before placing it in this field if your workflow involves non-admin contributors.
06 Basic Settings Tab
Layout Order
Controls the render order of Icon, Number, Title, and Description inside each counter card. The selected value maps directly to a PHP switch statement in tmpl/default.php. See Layout Order Reference for all 11 options.
Counter Configuration
| Parameter | Default | Description |
|---|---|---|
| counter_duration | 2000 | Total animation time in milliseconds. Passed directly to counterUp(counter, { duration: N }). Increase for slower, more dramatic counting; decrease for snappy reveals. |
| counter_delay | 16 | Millisecond interval between each incremental update tick. Passed to counterUp(counter, { delay: N }). Lower values produce smoother animation at the cost of more DOM updates. |
| random | No | When enabled, counter items are shuffled on each page load using PHP’s array_keys + shuffle before rendering. Useful for displaying a rotating subset of statistics. |
Advanced Custom Style
A raw CSS textarea. Content is injected via $document->addStyleDeclaration() after all scoped module styles. See Custom CSS Field.
07 Responsive Control Tab
Sets the number of counter cards displayed per row at each viewport breakpoint. The Dispatcher passes these values to LgxCounterUpHelper::LgxRowItemCount($n), which calculates 100 / n percent and injects it as a scoped flexbox rule targeting .lgx_app_item.
Enter any positive integer. The module calculates flex: 0 0 (100/N)% and max-width: (100/N)% for the .lgx_app_item container. Setting the value to 1 produces a full-width stacked layout on that breakpoint.
Tablet and mobile note: At ≤991 px and ≤767 px breakpoints, background-attachment is automatically reset to initial to prevent fixed-background rendering issues on iOS and Android.
08 Style Settings Tab
Item Behaviour
| Parameter | Default | Description |
|---|---|---|
| item_style | none | Hover/grayscale CSS effect applied as class lgx_app_hover_effect_{value}. See Hover Effects. |
| item_align | center | Text alignment for counter card content: left, center, or right. Also controls icon auto-margin behaviour. |
| item_padding | 5px | CSS padding applied to .lgx_app_item_inner. Accepts any CSS value (e.g. 10px 20px). |
| item_margin | 10px | CSS margin applied to .lgx_app_item_inner. |
Item Border
| Parameter | Default | Description |
|---|---|---|
| item_border_en | No | Enables a border on .lgx_app_item_inner. |
| item_border_width | 2px | Border width (CSS value with unit). |
| item_border_color | #999999 | Border color (hex). |
| item_border_radius | 5px | Border radius (CSS value with unit). |
| item_bg_en | No | Enables a background color on .lgx_app_item_inner. |
| item_bg | #ffffff | Item background color (hex). Visible only when item_bg_en is Yes. |
Number Styling
| Parameter | Default | Description |
|---|---|---|
| number_font_size | 18px | Font size of .lgx_cu_value (accepts any CSS unit). |
| number_color | #333333 | Font color of the counter number. |
| number_font_weight | 400 | CSS font-weight value. |
| number_margin_bottom | 0px | Bottom margin on the number wrapper. |
| number_border_en | No | Adds a border around .lgx_counter_value. |
| number_border_width / color / radius | 2px / #fff / 5px | Border properties for the number element. |
| number_dimension_en | No | Enables fixed width and height on the number container. |
| number_width / number_height | auto | Explicit dimensions for the number container when dimension mode is enabled. |
Icon Styling
| Parameter | Default | Description |
|---|---|---|
| icon_max_width | 128px | Maximum width of .lgx_cu_thumb. |
| icon_max_height | 128px | Maximum height of .lgx_cu_thumb. |
| icon_padding | 15px | Padding inside the icon container. |
| icon_margin_bottom | 0px | Bottom margin of the icon container. |
| icon_border_en | No | Enables border around the icon container. |
| icon_border_width / color / radius | 2px / #888888 / 5px | Icon border properties. |
| icon_bg_en | No | Enables background color behind the icon. |
| icon_bg | #ffffff | Icon background color. |
Title and Description Typography
| Parameter | Default | Description |
|---|---|---|
| title_font_size | 20px | Font size of .lgx_cu_title. |
| title_color | #333333 | Title text color. |
| title_font_weight | 600 | CSS font-weight for title. |
| title_margin_bottom | 0px | Bottom margin of title element. |
| desc_font_size | 16px | Font size of .lgx_cu_desc. |
| desc_color | #444444 | Description text color. |
| desc_font_weight | 400 | CSS font-weight for description. |
| desc_margin_bottom | 0px | Bottom margin of description element. |
09 Section Settings Tab
Controls the outer section wrapper — background imagery, color overlay, and spacing.
Background Image
| Parameter | Default | Description |
|---|---|---|
| bg_img_en | Yes | Enables the background image on the section wrapper. When disabled, no background rule is injected. |
| bg_img | assets/img/default.jpg | Image path selected via Joomla media picker (preview enabled). The module prefixes the site base URL automatically. |
| lgx_bg_attachment | initial | Maps to CSS background-attachment. Options: initial (static) or parallax (fixed scroll effect on desktop). Reverts to initial on mobile/tablet automatically. |
| lgx_bg_size_type | cover | Maps to CSS background-size. Options: cover, auto, contain. |
Background Color Overlay
| Parameter | Default | Description |
|---|---|---|
| bg_color_en | Yes | Applies a semi-transparent color to .lgx_counter_up_inner, layered over the background image. |
| bg_color | #000000 | Hex color for the overlay. Converted to rgba() by LgxCounterUpHelper::lgx_counter_up_hex2rgba(). |
| bg_opacity | 0.2 | Opacity of the color overlay. Range: 0.0–1.0 in 0.1 steps. Values outside this range are clamped to 1.0 by the helper. |
Section Dimensions and Spacing
| Parameter | Default | Description |
|---|---|---|
| section_width | 100% | Width of the outer #mod_lgx_counter_up{ID} wrapper. Accepts any CSS unit. |
| content_width | 100% | Width of .lgx_counter_up_content inner container; auto-centered with margin: 0 auto. |
| margin_top | 0px | Top margin of the section wrapper. |
| margin_bottom | 0px | Bottom margin of the section wrapper. |
| padding_top | 0px | Top padding of .lgx_counter_up_inner. |
| padding_bottom | 0px | Bottom padding of .lgx_counter_up_inner. |
10 Section Header
An optional header block rendered above the counter grid inside .lgx_counter_up_header. Enable it to display a section title (<h2>) and subtitle (<h4>) with full typography control.
| Parameter | Default | Description |
|---|---|---|
| header_en | No | Toggles the header block. When disabled, the entire .lgx_counter_up_header div is not rendered. |
| header_title | Section Title | Primary heading text rendered as <h2 class="lgx_counter_up_title">. |
| header_subtitle | — | Secondary heading text rendered as <h4 class="lgx_counter_up_subtitle">. Leave blank to suppress. |
| header_align | center | Text alignment of the header block: left, center, or right. |
| header_title_font_size | 36px | Font size of the section title. |
| header_title_color | #010101 | Color of the section title. |
| header_title_font_weight | 700 | Font weight of the section title. |
| header_title_margin_bottom | 10px | Bottom margin below the title. |
| header_subtitle_font_size | 16px | Font size of the subtitle. |
| header_subtitle_color | #888888 | Color of the subtitle. |
| header_subtitle_font_weight | 400 | Font weight of the subtitle. |
| header_subtitle_margin_bottom | 10px | Bottom margin below the subtitle. |
11 Advanced Tab
| Parameter | Default | Description |
|---|---|---|
| layout | default | Selects an alternative layout file from tmpl/ or from a template override path. Standard Joomla module layout switcher. |
| moduleclass_sfx | — | CSS suffix appended to the module wrapper class as lgx_counter_up_sfx{value}. Use this to target the module with custom CSS without touching core files. |
| cache | Use Global | Standard Joomla module caching control. Set to No Caching during development or when using Random Display mode. |
| cache_time | 900 | Cache lifetime in seconds (default 15 minutes). |
If random is enabled in the Basic tab, set cache to No Caching. A cached module output will not re-shuffle on subsequent page loads.
12 Layout Order Reference
The Layout Order parameter in the Basic tab controls the render order of four elements: Icon (I), Number/Count (N), Title (T), and Description (D) inside each counter card. Two additional layouts float the icon left or right of the stacked number/title/description block.
Default
The floating layouts (l_i_t_n_d and r_i_t_n_d) wrap the number, title, and description in a .lgx_item_info_wrap div positioned alongside the icon using flexbox direction set by the parent .lgx_item_floating_{floating_style} class.
13 Hover Effects Reference
The Item Style parameter in the Style Settings tab appends a class to each counter card element as lgx_app_hover_effect_{value}. All effects are pure CSS, defined in _hover_effect.min.css.
| Value | Class Applied | Behaviour |
|---|---|---|
| none | lgx_app_hover_effect_none |
No effect. Default. |
| gray_hover | lgx_app_hover_effect_gray_hover |
Card renders in color; transitions to grayscale on hover. |
| gray_remove | lgx_app_hover_effect_gray_remove |
Card renders in grayscale; transitions to full color on hover. |
| gray_always | lgx_app_hover_effect_gray_always |
Card is permanently rendered in grayscale regardless of hover state. |
| box_shadow | lgx_app_hover_effect_box_shadow |
Box shadow appears on hover. |
| box_shadow_always | lgx_app_hover_effect_box_shadow_always |
Box shadow is permanently applied. |
14 Template Override
Counter Up supports two types of Joomla override.
CSS Override (Automatic)
On every page load, asset.php checks for a custom stylesheet at:
If the file exists, it is loaded automatically after the module’s own style.min.css. Create this file in your active template to override any module styles without modifying core files. No configuration required.
Layout Override (Manual)
Copy tmpl/default.php to:
Joomla will use your override instead of the module’s bundled template. Combined with the LESS source files in assets/less/, this gives full control over markup and compiled styles.
If you create additional layout files (e.g. default_compact.php), they appear in the Layout dropdown on the Advanced tab and can be selected per module instance.
15 Custom CSS Field
The Custom Style textarea in the Basic tab injects arbitrary CSS into the document via $document->addStyleDeclaration(). It is injected after all scoped module styles, so it has full cascade priority over any generated rule.
Use module-scoped selectors to avoid affecting other elements:
/* Target the number element of this specific module instance */
#mod_lgx_counter_up123 .lgx_cu_value {
font-family: ‘Georgia’, serif;
letter-spacing: -0.03em;
}
/* Override item card background */
#mod_lgx_counter_up123 .lgx_app_item_inner {
background: linear-gradient(135deg, #1a2130, #0b0e13);
}
The module ID is the number Joomla assigns when you create the module instance. Inspect the rendered HTML and look for id="mod_lgx_counter_up123" — the suffix is your module ID. It also appears in the URL when editing the module in the administrator.
16 Architecture Notes
DI Service Provider
services/provider.php returns an anonymous class implementing ServiceProviderInterface. It registers three service providers against the Joomla DI container:
$container->registerServiceProvider(new ModuleDispatcherFactory(‘\\LogicHunt\\Module\\CounterUp’));
$container->registerServiceProvider(new HelperFactory(‘\\LogicHunt\\Module\\CounterUp\\Site\\Helper’));
$container->registerServiceProvider(new ModuleProvider(‘\\LogicHunt\\Module\\CounterUp’));
Dispatcher Data Flow
Dispatcher::getLayoutData() calls parent::getLayoutData() for base Joomla layout setup, then:
- Reads the subform repeater via
$params->get('lgx_counter_up_repeat_field')and processes it throughLgxCounterUpHelper::LgxCounterUpSource()to produce a normalized$itemsarray. - Optionally shuffles the array via
LgxCounterUpHelper::LgxCounterUpRandomize()ifrandom === 1. - Extracts every backend parameter into typed local variables.
- Calls
requireonassets/asset.phpwhile all variables are in local scope — this registers stylesheets and scripts and injects all scoped CSS declarations. - Returns the populated
$dataarray to the parent dispatcher, which passes it totmpl/default.php.
JavaScript Initialisation
tmpl/default.php outputs an inline <script> block that initialises a Waypoint for every .lgx_counter{module->id} element:
jQuery(document).ready(function($) {
“use strict”;
let lgxCounterUp = window.counterUp[“default”];
let $lgxCounters = $(“.lgx_counter{moduleID}”);
$lgxCounters.each(function(ignore, counter) {
let waypoint = new Waypoint({
element: $(this),
handler: function() {
lgxCounterUp(counter, { duration: 2000, delay: 16 });
this.destroy(); // Fires once only
},
offset: ‘bottom-in-view’,
});
});
});
The this.destroy() call ensures the Waypoint is removed after the counter fires once — scrolling back up and down will not re-trigger the animation.
17 CSS Class Reference
| Class | Element | Description |
|---|---|---|
| .lgx_counter_up_app | <section> |
Outermost wrapper element. |
| #mod_lgx_counter_up{ID} | <div> |
Unique ID wrapper — all scoped CSS targets this selector. |
| .mod_lgx_counter_up | <div> |
Base module class, always present. |
| .lgx_counter_up_sfx{sfx} | <div> |
Module class suffix from the Advanced tab. |
| .lgx_counter_up_inner | <div> |
Inner wrapper — receives padding and background color overlay. |
| .lgx_counter_up_header | <div> |
Section header block — only rendered when header is enabled. |
| .lgx_counter_up_title | <h2> |
Section header primary title. |
| .lgx_counter_up_subtitle | <h4> |
Section header subtitle. |
| .lgx_counter_up_content | <div> |
Counter grid container — carries layout order and floating style classes. |
| .lgx_layout_order_{value} | <div> |
Current layout order slug (e.g. .lgx_layout_order_i_n_t_d). |
| .lgx_item_floating_{style} | <div> |
Floating style class on the content container. |
| .lgx_app_item | <div> |
Individual counter card — receives responsive flex-basis rules. |
| .lgx_app_item_counter | <div> |
Additional type class on every counter card. |
| .lgx_app_hover_effect_{style} | <div> |
Hover/grayscale effect class from Style Settings. |
| .lgx_app_item_inner | <div> |
Inner card wrapper — receives border, padding, margin, background styles. |
| .lgx_cu_thumb | <div> |
Icon image container. |
| .lgx_app_item_img | <img> |
Icon image element. |
| .lgx_counter_value_wrap | <div> |
Wrapper around the counter number span. |
| .lgx_counter_value | <span> |
Counter number element — border and dimension styles applied here. |
| .lgx_cu_value | <span> |
Counter number inner span — font size, color, weight applied here. |
| .lgx_counter{ID} | <span> |
Module-ID-scoped class used by the JavaScript selector to initialise Waypoints. |
| .lgx_cu_title | <h3> |
Counter card title element. |
| .lgx_cu_desc | <div> |
Counter card description element. |
| .lgx_item_info_wrap | <div> |
Present only in left/right floating layouts — wraps number, title, and description alongside the floated icon. |
18 Frequently Asked Questions
The counter animates but only shows 0
Verify the Count Value field contains a recognisable numeric string. If the value contains only non-numeric characters (e.g. a label with no digits), the counter engine has nothing to count toward and stays at zero.
The animation fires on page load, not on scroll
Waypoints triggers on bottom-in-view, meaning the module is likely already visible in the viewport when the page loads. This is expected behaviour — the counter fires immediately if the section is already on screen.
The counter fires twice on the same scroll
This should not occur because this.destroy() is called inside the handler. If you see repeated animation, check whether the module position is being rendered twice by the active template.
Random mode is not working
Disable caching for this module instance. Go to the Advanced tab and set Caching to No Caching. A cached render will not re-shuffle on subsequent requests.
Background parallax effect is not working on mobile
This is intentional. The module automatically resets background-attachment to initial at ≤991 px and ≤767 px breakpoints to prevent fixed-background rendering issues on iOS Safari and Android Chrome.
How do I add a prefix or suffix to the counter number?
Enter the full string including non-numeric characters directly in the Count Value field. For example: $1,234, 99%, or 1,200+. The counter engine automatically detects and animates the numeric portion.
How do I style a specific module instance differently?
Use the Custom Style field in the Basic tab with the module-scoped ID selector (e.g. #mod_lgx_counter_up123 .lgx_cu_value { ... }), or create a file at templates/{your-template}/css/mod_lgx_counter_up.css which is loaded automatically for all instances.
Can I use multiple Counter Up modules on one page?
Yes. Each instance receives a unique module ID from Joomla. All CSS is scoped to #mod_lgx_counter_up{ID} and all JavaScript selectors target .lgx_counter{ID}, so instances are fully isolated from each other.
19 Support
LogicHunt provides direct developer support for all extensions. Response times are typically within one business day.
Submit tickets and track responses.
General enquiries and installation assistance.
Browse the full LogicHunt extension catalogue.
Counter Up is released under the GNU General Public License v3.0. Full source code is included in the package. Copyright 2014–2026 LogicHunt. All rights reserved.