Lightweight, accessible statistics display for marketing pages and landing sections
Stats is RSL's lightweight statistics component - perfect for landing pages, marketing sections, and anywhere you need clean, impactful metric displays without dashboard complexity.
Include both stats.css and stats.js in your project. The JavaScript auto-initializes any element with the .rsl-stat class and enables count-up animations.
RSL offers two components for displaying metrics. Choose based on your use case:
| Feature | Stats | KPI Cards |
|---|---|---|
| Best for | Landing pages, marketing | Dashboards, analytics |
| Complexity | Lightweight | Feature-rich |
| Trend indicators | ||
| Sparklines | ||
| Progress bars | ||
| Count-up animation | ||
| FilterBus support | ||
| Multiple layouts | (5 variants) | (3 sizes) |
| Clickable/linkable |
Stats are fully configurable via data attributes - no JavaScript required for basic usage.
| Attribute | Type | Description |
|---|---|---|
data-value |
Number/String | The main numeric value to display (e.g., "10000", "99.9") |
data-label |
String | Description text below the value |
data-prefix |
String | Text/symbol before the value (e.g., "$", "#") |
data-suffix |
String | Text/symbol after the value (e.g., "%", "+", "M") |
data-icon |
String | FontAwesome icon class (e.g., "fa-users") |
| Attribute | Type | Options | Description |
|---|---|---|---|
data-variant |
String | default, compact, inline, featured, card | Layout style variant |
data-size |
String | xs, sm, md (default), lg, xl | Size scale for the stat |
data-color-scheme |
String | primary, success, warning, danger, info | Color theme for the stat |
data-align |
String | left, center (default), right | Text alignment within the stat |
| Attribute | Type | Default | Description |
|---|---|---|---|
data-animate |
Boolean | false | Enable count-up animation (scroll-triggered) |
data-duration |
Number | 2000 | Animation duration in milliseconds |
data-easing |
String | easeOutQuart | Easing function: linear, easeOutQuad, easeOutCubic, easeOutQuart, easeOutExpo |
data-decimals |
Number | 0 | Number of decimal places to display |
data-separator |
String | , | Thousands separator character |
| Attribute | Type | Description |
|---|---|---|
data-clickable |
Boolean | Make the stat clickable with hover effects |
data-href |
String | URL to navigate on click (requires data-clickable) |
| Attribute | Type | Description |
|---|---|---|
data-variant |
String | Applied to all child stats |
data-gap |
String | CSS gap value between stats (e.g., "2rem") |
data-dividers |
Boolean | Show divider lines between stats |
Stats offers 5 distinct layout variants for different contexts:
Clean, centered layout - perfect for most use cases.
Condensed layout for space-constrained areas.
Badge-like display for inline placement.
Hero-style for highlighting key metrics.
Elevated card style with shadows.
For programmatic control, use the RSL.Stats namespace.
| Method | Parameters | Description |
|---|---|---|
RSL.Stats.init() |
None | Initialize all stats on the page |
RSL.Stats.create(element, config) |
HTMLElement, Object | Create a single stat instance |
RSL.Stats.createGroup(container, config) |
HTMLElement, Object | Create a group of stats |
RSL.Stats.update(element, config) |
HTMLElement, Object | Update stat with new configuration |
RSL.Stats.destroy(element) |
HTMLElement | Destroy a stat instance |
RSL.Stats.refresh(element) |
HTMLElement | Re-render a stat from data attributes |
RSL.Stats.getConfig(element) |
HTMLElement | Get current configuration object |
RSL.Stats.formatNumber(num, opts) |
Number, Object | Format a number with separators and decimals |
// Create a stat programmatically
const container = document.getElementById('my-stat');
RSL.Stats.create(container, {
value: 10000,
label: 'Happy Customers',
suffix: '+',
icon: 'fa-users',
colorScheme: 'primary',
animate: true,
duration: 2500
});
// Update a stat dynamically
RSL.Stats.update(container, {
value: 15000,
label: 'Even Happier Customers'
});
// Format a number
RSL.Stats.formatNumber(1234567, {
separator: ',',
decimals: 0
}); // Returns "1,234,567"
Stats integrates with RSL's JSON Layout API V2 for declarative page building.
{
content: {
type: "stat",
value: 10000,
label: "Happy Customers",
suffix: "+",
icon: "fa-users",
colorScheme: "primary",
animate: true
}
}
{
content: {
type: "stats",
variant: "default",
gap: "2rem",
items: [
{ value: 10000, label: "Customers", suffix: "+", icon: "fa-users" },
{ value: 99.9, label: "Uptime", suffix: "%", icon: "fa-server" },
{ value: 24, label: "Support", suffix: "/7", icon: "fa-headset" }
]
}
}
See More: Browse all JSON API V2 Stats examples →
Stats can subscribe to RSL's FilterBus for visibility filtering based on external filter controls. This is ideal for dashboard scenarios where filter buttons control which stats are displayed.
data-filter-subscribe="key" to listen to a FilterBus channeldata-filter-value="value" to specify which filter value this stat matchesdata-filter-value always show (e.g., "Total" metrics)<!-- Filter publishes to FilterBus -->
<div data-rsl-filter data-filter-key="region">
<button data-filter-value="All">All Regions</button>
<button data-filter-value="North">North</button>
<button data-filter-value="South">South</button>
</div>
<!-- Stats subscribe to FilterBus -->
<div class="rsl-stats">
<!-- Always visible (no filter-value) -->
<div class="rsl-stat"
data-value="2847"
data-label="Total Customers"
data-filter-subscribe="region">
</div>
<!-- Shows only when region="North" -->
<div class="rsl-stat"
data-value="847"
data-label="North Customers"
data-filter-subscribe="region"
data-filter-value="North">
</div>
<!-- Shows only when region="South" -->
<div class="rsl-stat"
data-value="623"
data-label="South Customers"
data-filter-subscribe="region"
data-filter-value="South">
</div>
</div>
| Attribute | Type | Description |
|---|---|---|
data-filter-subscribe |
String | FilterBus key to subscribe to (e.g., "region", "category") |
data-filter-value |
String | Filter value(s) this stat matches. Component shows when filter equals this value. Supports comma-separated values for multi-match (e.g., "North,South"). Stats without this attribute always show. |
Watch how Stats can show/hide based on filter selections. This live demo shows Filter + Smart Table + KPI Cards + Stats + Charts all working together.
View Live Dashboard DemoStats is built with accessibility as a core feature:
aria-label (e.g., "Happy Customers: 10,000+")aria-hidden="true", values are announced properlyprefers-reduced-motionaria-live="polite"Stats meets WCAG 2.1 Level AA requirements including proper focus management, keyboard operability, and screen reader compatibility.
Stats dispatches custom events for integration with your application:
| Event | Detail | Description |
|---|---|---|
rsl-stat-init |
{ element, config } |
Fired when a stat is initialized |
rsl-stat-update |
{ element, config } |
Fired when a stat is updated |
rsl-stat-animated |
{ element, value } |
Fired when count-up animation completes |
rsl-stat-click |
{ element, config } |
Fired when a clickable stat is activated |
rsl-stat-filterbus |
{ element, visible, state } |
Fired when FilterBus updates visibility |
View examples.html for comprehensive demos
Test features in playground.html
Browse all RSL components