Counter
<quiet-counter>
Displays a counter that can count up or down to a specified date.
<quiet-counter label="Feeding schedule" max-unit="hours" delimiter=":" style="font-size: 2.5rem;" id="counter__overview" ></quiet-counter> <script> const counter = document.getElementById('counter__overview'); // Two hours from now counter.date = new Date(Date.now() + 2 * 60 * 60 * 1000); </script>
If you pass a string to the date attribute, always use the
ISO 8601 format. Otherwise, ambiguous dates such as 01/02/2000 can be parsed as January 2 or February 1 depending on the
client's locale.
Examples Jump to heading
Providing dates Jump to heading
You must provide the date when the counter starts or ends. You can pass an ISO 8601-formatted date string,
e.g. via
Date.toISOString()
to the date attribute.
<quiet-counter date="2028-04-02T00:00:00.000Z"></quiet-counter>
Alternatively, you can set the date property to a
Date
object using JavaScript.
const counter = document.querySelector('quiet-counter'); // Quick way to calculate seven days from now counter.date = new Date(Date.now() + 7 * 24 * 60 * 60 * 1000);
Adding a label Jump to heading
Use the label attribute to give the counter an accessible label. This won't be displayed on the
screen, but it will be announced by assistive devices.
<quiet-counter label="Rest timer" date="2025-04-05 09:00:00" max-unit="hours" id="counter__label" ></quiet-counter> <script> const counter = document.getElementById('counter__label'); // 45 minutes from now counter.date = new Date(Date.now() + 45 * 60 * 1000); </script>
Counting up Jump to heading
When using mode="countup", you can set any past date as the starting point. This is
useful for tracking time since an event, uptime, or age of something.
<quiet-counter label="Days since first commit" mode="countup" date="2024-02-02T12:39:00-05:00" max-unit="days" ></quiet-counter>
If date is omitted, counting starts from the current date and time.
<div id="counter__countup"> <quiet-counter label="Session duration" mode="countup" max-unit="hours" ></quiet-counter> <br><br> <quiet-button>Restart</quiet-button> </div> <script> const container = document.getElementById('counter__countup'); const counter = container.querySelector('quiet-counter'); const button = container.querySelector('quiet-button'); button.addEventListener('click', () => { counter.date = new Date(); }); </script>
Min and max units Jump to heading
Use the min-unit and max-unit attributes to control the smallest and largest units
that will be displayed. Remaining time will be rolled over to the highest visible unit, e.g. two days will
show as 48 hours when max-unit="hours".
<quiet-counter label="Play session" date="2025-04-05 09:00:00" min-unit="minutes" max-unit="hours" id="counter__min-max" ></quiet-counter> <script> const counter = document.getElementById('counter__min-max'); // 3 hours and 30 minutes from now counter.date = new Date(Date.now() + 3 * 60 * 60 * 1000 + 30 * 60 * 1000); </script>
Changing the size Jump to heading
Counters are sized relative to the current font size. To change the size, set the
font-size property on the counter or an ancestor element.
<quiet-counter label="Appointment" date="2025-04-03 14:20:00" max-unit="minutes" style="font-size: 3rem;" id="counter__size" ></quiet-counter> <script> const counter = document.getElementById('counter__size'); // 20 minutes from now counter.date = new Date(Date.now() + 20 * 60 * 1000); </script>
Changing unit labels Jump to heading
The default unit labels are localized using
Intl.DisplayNames. To show custom labels, provide your own using the appropriate slots.
<quiet-counter label="Delivery estimate" date="2025-04-03 14:40:00" max-unit="hours" id="counter__unit-labels" > <span slot="hours">H</span> <span slot="minutes">M</span> <span slot="seconds">S</span> </quiet-counter> <script> const counter = document.getElementById('counter__unit-labels'); // 1 hour and 15 minutes from now counter.date = new Date(Date.now() + 1 * 60 * 60 * 1000 + 15 * 60 * 1000); </script>
Setting a delimiter Jump to heading
Use the delimiter attribute to add a character such as : between each unit.
<quiet-counter label="Litter box reminder" date="2025-04-04 12:40:00" max-unit="hours" delimiter=":" id="counter__delimiter" ></quiet-counter> <script> const counter = document.getElementById('counter__delimiter'); // 30 minutes from now counter.date = new Date(Date.now() + 30 * 60 * 1000); </script>
Starting and resuming Jump to heading
Use the start() and stop() methods to control the counter. When calling
start(), the counter will restart based on the existing date, which may not be
desirable. To resume the counter from the time currently shown, call start({ resume: true }).
In this case, the date property will be adjusted to account for the pause.
<div id="counter__starting"> <quiet-counter label="Treat time" date="2025-04-04 12:40:00" max-unit="hours" ></quiet-counter> <br><br> <quiet-button toggle="off">Pause</quiet-button> </div> <script> const container = document.getElementById('counter__starting'); const counter = container.querySelector('quiet-counter'); const button = container.querySelector('quiet-button'); // 25 minutes from now counter.date = new Date(Date.now() + 25 * 60 * 1000); button.addEventListener('click', () => { if (button.toggle === 'on') { counter.stop(); } else { counter.start({ resume: true }); } }); </script>
Localizing values Jump to heading
You can set the lang attribute on the counter to localize the value. Use
grouping and valueFormatter for additional control over formatting.
<quiet-counter lang="de" label="Trainingseinheit" date="2025-04-04 12:40:00" max-unit="hours" id="counter__localizing" ></quiet-counter> <script> const counter = document.getElementById('counter__localizing'); // 4 hours from now counter.date = new Date(Date.now() + 4 * 60 * 60 * 1000); </script>
Styling counter Jump to heading
Counters come with a simple, minimal appearance. Feel free to customize them with your own styles. This one is inspired by Rocket Blaster.
<quiet-counter label="It's the final countdown 🎶" date="2025-04-03 14:40:00" max-unit="hours" delimiter=":" id="counter__styling" > <span slot="hours">HR</span> <span slot="minutes">MIN</span> <span slot="seconds">SEC</span> </quiet-counter> <script> const counter = document.getElementById('counter__styling'); // 1 hour from now counter.date = new Date(Date.now() + 2 * 60 * 60 * 1000); </script> <style> #counter__styling { font-family: Orbitron, sans-serif; font-size: 3rem; font-weight: 900; letter-spacing: 0.125em; color: white; text-shadow: 0 -2px 0 #0001; border-radius: 3rem; background-image: linear-gradient( 135deg, #1a1a2e 0%, #16213e 50%, #0f3460 100% ); padding: 2rem; &::part(unit) { width: 2ch; } &::part(label) { font-size: 1.25rem; font-weight: 400; color: #4cc9f0; text-shadow: none; } &::part(delimiter) { color: #f52385; margin-inline: -0.25em; opacity: 0.8; } @media screen and (max-width: 768px) { font-size: 2rem; } } </style>
API Jump to heading
Importing Jump to heading
The autoloader is the recommended way to import components but, if you prefer to do it manually, the following code snippets will be helpful.
To manually import <quiet-counter> from the CDN, use the following code.
import 'https://cdn.quietui.org/v2.0.0/components/counter/counter.js';
To manually import <quiet-counter> from a self-hosted distribution, use the following
code. Remember to replace /path/to/quiet with the appropriate local path.
import '/path/to/quiet/components/counter/counter.js';
Slots Jump to heading
Counter supports the following slots. Learn more about using slots
| Name | Description |
|---|---|
seconds
|
A custom label to show for seconds. |
minutes
|
A custom label to show for minutes. |
hours
|
A custom label to show for hours. |
days
|
A custom label to show for days. |
months
|
A custom label to show for months. |
years
|
A custom label to show for years. |
Properties Jump to heading
Counter has the following properties that can be set with corresponding attributes. In many cases, the attribute's name is the same as the property's name. If an attribute is different, it will be displayed after the property. Learn more about attributes and properties
| Property / Attribute | Description | Reflects | Type | Default |
|---|---|---|---|---|
label
|
An accessible label for the counter. This won't be visible, but it will be read to assistive devices so you should always include one. |
|
string
|
''
|
date
|
The date to count to or from based on the selected mode. If an attribute is passed, the
date should be an
ISO 8601 string. If set as a property, a Date object can be used instead.
|
|
Date
|
|
mode
|
The counter mode. Use countdown to count to a future date and countup to
count from a past date.
|
|
'countdown'
|
'countdown'
|
delimiter
|
A visual delimiter to show between units. |
|
string
|
''
|
minUnit
min-unit
|
The smallest unit to display in the counter. |
|
'seconds'
|
'seconds'
|
maxUnit
max-unit
|
The largest unit to display in the counter. |
|
'seconds'
|
'days'
|
grouping
|
Whether to group numbers, e.g. with a thousands separator. |
|
'always'
|
'auto'
|
valueFormatter
|
A custom formatting function to apply to the number. When set, decimal-places and
grouping will be ignored. Property only.
|
|
(value: number) => string
|
Methods Jump to heading
Counter supports the following methods. You can obtain a reference to the element and call them like functions in JavaScript. Learn more about methods
| Name | Description | Arguments |
|---|---|---|
start() |
Starts or resumes the counter after validating dates. |
options: { resume?: boolean }
|
stop() |
Stops the counter and records the time it was stopped. |
Events Jump to heading
Counter dispatches the following custom events. You can listen to them the same way was native events. Learn more about custom events
| Name | Description |
|---|---|
quiet-finished |
Dispatched when counting down and the counter finishes. |
quiet-tick |
Dispatched every time the visible counter changes. For example, if the counter displays seconds,
this will be once every second; if min-unit is minutes, it will be once every minute;
and so on.
|
CSS parts Jump to heading
Counter exposes internal elements that can be styled with CSS using the selectors shown below. Learn more about CSS parts
| Name | Description | CSS selector |
|---|---|---|
unit |
The container that holds each unit, including its values and labels. |
::part(unit)
|
value |
The value of each unit. |
::part(value)
|
label |
The label of each unit. |
::part(label)
|
delimiter |
The delimiters between units. |
::part(delimiter)
|
Custom States Jump to heading
Counter has the following custom states. You can target them with CSS using the selectors shown below. Learn more about custom states
| Name | Description | CSS selector |
|---|---|---|
active |
Applied when the counter is actively counting. |
:state(active)
|