Skip to content

Counter

<quiet-counter> stable since 1.0

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.



Restart
<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.

H M S
<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.



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 .

HR MIN SEC
<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.

CDN Self-hosted

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
string
mode The counter mode. Use countdown to count to a future date and countup to count from a past date. 'countdown'
'countup'
'countdown'
delimiter A visual delimiter to show between units. string ''
minUnit
min-unit
The smallest unit to display in the counter. 'seconds'
'minutes'
'hours'
'days'
'months'
'years'
'seconds'
maxUnit
max-unit
The largest unit to display in the counter. 'seconds'
'minutes'
'hours'
'days'
'months'
'years'
'days'
grouping Whether to group numbers, e.g. with a thousands separator. 'always'
'never'
'auto'
'min2'
'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)
Search this website Toggle dark mode View the code on GitHub Follow @quietui.org on Bluesky Follow @quiet_ui on X

    No results found