Countdown Timer

Dynamic countdown timer for sales and promotions with auto-hide when expired.

A fully functional countdown timer with gradient background, responsive design, and automatic hiding when expired. Perfect for flash sales and limited-time offers.
countdown-timer.liquidliquid
{% comment %} Countdown Timer - snippets/countdown-timer.liquid {% endcomment %}
<div class="countdown-timer" data-end-date="{{ section.settings.end_date }}">
  <div class="countdown-timer__content">
    <span class="countdown-timer__label">{{ section.settings.label | default: 'Sale Ends In:' }}</span>
    <div class="countdown-timer__digits">
      <div class="countdown-digit">
        <span class="countdown-digit__value" data-days>00</span>
        <span class="countdown-digit__label">Days</span>
      </div>
      <div class="countdown-separator">:</div>
      <div class="countdown-digit">
        <span class="countdown-digit__value" data-hours>00</span>
        <span class="countdown-digit__label">Hours</span>
      </div>
      <div class="countdown-separator">:</div>
      <div class="countdown-digit">
        <span class="countdown-digit__value" data-minutes>00</span>
        <span class="countdown-digit__label">Mins</span>
      </div>
      <div class="countdown-separator">:</div>
      <div class="countdown-digit">
        <span class="countdown-digit__value" data-seconds>00</span>
        <span class="countdown-digit__label">Secs</span>
      </div>
    </div>
  </div>
</div>

<style>
.countdown-timer {
  background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
  padding: 20px;
  border-radius: 12px;
  text-align: center;
  color: white;
}

.countdown-timer.expired {
  display: none;
}

.countdown-timer__label {
  display: block;
  font-size: 14px;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 1px;
  margin-bottom: 16px;
  opacity: 0.9;
}

.countdown-timer__digits {
  display: flex;
  justify-content: center;
  align-items: center;
  gap: 8px;
}

.countdown-digit {
  display: flex;
  flex-direction: column;
  align-items: center;
  min-width: 60px;
}

.countdown-digit__value {
  font-size: 32px;
  font-weight: 700;
  line-height: 1;
  background: rgba(255, 255, 255, 0.2);
  padding: 12px 16px;
  border-radius: 8px;
  min-width: 60px;
  backdrop-filter: blur(10px);
}

.countdown-digit__label {
  font-size: 11px;
  text-transform: uppercase;
  margin-top: 8px;
  opacity: 0.8;
  font-weight: 600;
}

.countdown-separator {
  font-size: 28px;
  font-weight: 700;
  opacity: 0.6;
  margin: 0 4px;
}

@media (max-width: 640px) {
  .countdown-digit__value {
    font-size: 24px;
    padding: 8px 12px;
    min-width: 50px;
  }
  
  .countdown-digit__label {
    font-size: 9px;
  }
}
</style>

<script>
class CountdownTimer {
  constructor(element) {
    this.element = element;
    this.endDate = new Date(element.dataset.endDate).getTime();
    this.daysEl = element.querySelector('[data-days]');
    this.hoursEl = element.querySelector('[data-hours]');
    this.minutesEl = element.querySelector('[data-minutes]');
    this.secondsEl = element.querySelector('[data-seconds]');
    
    this.start();
  }

  start() {
    this.update();
    this.interval = setInterval(() => this.update(), 1000);
  }

  update() {
    const now = new Date().getTime();
    const distance = this.endDate - now;

    if (distance < 0) {
      clearInterval(this.interval);
      this.element.classList.add('expired');
      return;
    }

    const days = Math.floor(distance / (1000 * 60 * 60 * 24));
    const hours = Math.floor((distance % (1000 * 60 * 60 * 24)) / (1000 * 60 * 60));
    const minutes = Math.floor((distance % (1000 * 60 * 60)) / (1000 * 60));
    const seconds = Math.floor((distance % (1000 * 60)) / 1000);

    this.daysEl.textContent = String(days).padStart(2, '0');
    this.hoursEl.textContent = String(hours).padStart(2, '0');
    this.minutesEl.textContent = String(minutes).padStart(2, '0');
    this.secondsEl.textContent = String(seconds).padStart(2, '0');
  }
}

document.addEventListener('DOMContentLoaded', () => {
  document.querySelectorAll('.countdown-timer').forEach(timer => {
    new CountdownTimer(timer);
  });
});
</script>

Usage

{% render 'countdown-timer' %} - Configure end date in section settings

Installation

Add to snippets/countdown-timer.liquid

Let’s Build Something You’ll Be Proud Of

No fluff. Just thoughtful design and reliable development.

Work with me
Average response time: within 24 hours