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.liquidLet’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
