Countdown Timer ✅

A simple countdown timer for marketers, to manufacture urgency.

This is a personalized countdown timer that begins counting on each visitor's first visit. The timer persists across page loads and browser sessions using LocalStorage.

Features

  • Custom countdown timer, any duration. timer representation

  • 100% designer-controlled styling, any element arrangement you want

  • Timer-expired state, e.g. hide the timer, show a different element set

  • Animation support- the ability to trigger custom code to handle custom animations as the timer updates

  • Debug support, so you can see what it's tracking and calculating

Demo

Use Cases

Currently this timer is designed for marketing purposes, so the start and end time are user-specific. The primary use case is;

  • Create urgency from first visit to purchase or other conversion action

If it's desired, I'll expand this to other variants, like "count to deadline", which could be used for;

  • Submission deadlines

  • Time-until-launch

Quick Start

  1. Install the Sygnal Components lib from Sygnal Marketplacearrow-up-right

  2. Add the Countdown Timer component to your page

  3. Set the duration prop (e.g., 24h for 24 hours, or 3d 10m for 3 days, 10 minutes)

  4. Slot in HTML elements with countdown-remaining attributes for your countdown presentation. Build and customize this slotted component any way you like in the Webflow designer.

  5. The component automatically updates the text content, based on specific attributes;

Example slot content

Can be any HTML structure; the attributes determine where the component will update text during the countdown.


Properties

duration

Type: Text

Default: "24h"

Group: Settings

The countdown duration as a human-readable string. Supports years, months, days, hours, minutes, and seconds.

Format: Whitespace-separated parts, each with a number and unit character.

Unit
Character
Notes

Years

y

Calculated as 365 days

Months

M

Uppercase, calculated as 30 days

Days

d

Hours

h

Minutes

m

Lowercase

Seconds

s

Examples:

  • 24h — 24 hours

  • 2d 12h — 2 days and 12 hours

  • 1y 6M — 1 year and 6 months

  • 30m 30s — 30 minutes and 30 seconds

  • 1d 2h 30m 15s — 1 day, 2 hours, 30 minutes, 15 seconds

Notes:

  • Invalid parts are ignored

  • Duplicate units use the first occurrence only (e.g., 1h 2h = 1 hour)

  • Anomalous values are calculated correctly (e.g., 36h = 1.5 days)


content

Type: Slot

Group: Content

The slot for your countdown display HTML. Place elements with countdown-remaining attributes inside this slot.


storageKey

Type: Text

Default: "countdown"

Group: Settings

The LocalStorage key prefix for this timer instance. Use different keys to create multiple independent countdown timers on the same site.

Example: If you have two offers with different countdowns:

  • Offer A: storageKey="offer-a-countdown"

  • Offer B: storageKey="offer-b-countdown"


leadingZeros

Type: Boolean

Default: true

Group: Settings

When enabled, single-digit numbers are padded with a leading zero.

Value
leadingZeros: true
leadingZeros: false

5

"05"

"5"

12

"12"

"12"

0

"00"

"0"


debugMode

Type: Boolean

Default: false

Group: Advanced

When enabled, displays a debug panel showing:

  • Storage key in use

  • Parsed duration in milliseconds

  • First visit timestamp

  • End time timestamp

  • Current remaining time

  • Expired status

Useful for testing and troubleshooting. Disable in production.


Slot Attributes

Add these attributes to elements in your slotted content. The component will find and update them automatically.

Time Values

Attribute
Updates With

countdown-remaining="days"

Days remaining (e.g., "05")

countdown-remaining="hours"

Hours remaining (e.g., "23")

countdown-remaining="minutes"

Minutes remaining (e.g., "59")

countdown-remaining="seconds"

Seconds remaining (e.g., "45")

Visibility Controls

Attribute
Behavior

countdown-remaining="active"

Visible while timer is running; hidden when expired

countdown-remaining="expired"

Hidden while timer is running; visible when expired

Example:


JavaScript Events

The component dispatches CustomEvents on the window object for animation integration and custom behaviors.

countdown:update

Fired every second with the complete timer state.

countdown:days

Fired when the days value changes.

countdown:hours

Fired when the hours value changes.

countdown:minutes

Fired when the minutes value changes.

countdown:seconds

Fired when the seconds value changes.

countdown:expired

Fired once when the timer expires.


Animation Example

Here's a complete example showing how to animate SVG progress rings using the countdown events:


How It Works

First Visit Detection

When a visitor first loads a page with the Countdown Timer:

  1. The component checks LocalStorage for existing timer state

  2. If none exists, it records the current timestamp as firstVisit

  3. It calculates endTime as firstVisit + duration

  4. Both values are saved to LocalStorage

Subsequent Visits

On return visits:

  1. The component loads the saved firstVisit and endTime

  2. It compares the current time to endTime

  3. The countdown displays the remaining time (or expired state)

Duration Changes

If you change the duration prop after a timer has started:

  1. The component detects the duration change

  2. It recalculates endTime from the original firstVisit + new duration

  3. The new end time is saved to LocalStorage

This means changing from 24h to 48h extends the timer from the original first visit, not from now.

Expiration

When the countdown reaches zero:

  • All time values display as 00

  • Elements with countdown-remaining="active" are hidden

  • Elements with countdown-remaining="expired" are shown

  • The countdown:expired event fires once

  • The timer stops (no more updates)

  • The expired state persists until LocalStorage is cleared


LocalStorage

The component stores timer state in LocalStorage using the storageKey prop as a prefix.

Key: {storageKey}_state

Value:

Clearing the Timer

To reset a timer (e.g., for testing), clear the LocalStorage entry:

Or for a custom storage key:


Browser Support

  • Works in all modern browsers that support:

  • LocalStorage

  • CustomEvent

  • Shadow DOM (handled by Webflow)

  • LocalStorage unavailable: Timer still works but resets on page refresh


Troubleshooting

Timer shows 00:00:00 immediately

  • Check if the timer has already expired (enable debugMode)

  • Clear LocalStorage and refresh to reset

Slotted elements not updating

  • Verify elements have the correct countdown-remaining attribute

  • Check browser console for errors

  • Ensure the content is slotted into the content slot

Timer resets on every page load

  • LocalStorage may be blocked or unavailable

  • Check browser privacy settings

  • Verify the storageKey is consistent across pages

Animation not triggering

  • Verify event listener is attached to window

  • Check that event name matches exactly (e.g., countdown:update)

  • Use console.log in the event handler to confirm events are firing


Best Practices

  1. Use unique storage keys for different countdown timers to avoid conflicts

  2. Test with debugMode enabled during development, then disable for production

  3. Provide expired content using countdown-remaining="expired" for good UX

  4. Keep duration realistic — extremely long durations (years) may cause precision issues

  5. Consider time zones — the timer uses the visitor's local time via Date.now()

Last updated