Skip to content

Instantly share code, notes, and snippets.

@peternatewood
Last active November 29, 2023 15:55
Show Gist options
  • Save peternatewood/f69f8c12b36e20601930a54970201286 to your computer and use it in GitHub Desktop.
Save peternatewood/f69f8c12b36e20601930a54970201286 to your computer and use it in GitHub Desktop.
A simple, efficient countdown clock. No jQuery required.
<style type="text/css">
.countdown-container {
display: flex;
align-items: flex-start; /* Use flex-end if the digit titles go above the digits */
justify-content: space-between;
width: 480px;
}
.countdown-container.hide-separators .countdown-separator { display: none }
.countdown-digit-container { width: 22% }
.countdown-separator { width: 4% }
.countdown-digits,
.countdown-separator,
.countdown-digit-title {
text-align: center;
margin: 0;
}
.countdown-digits,
.countdown-separator {
font: 48px/1.2 Arial, Helvetica, sans-serif;
}
.countdown-digit-title {
font: 24px/1.5 Arial, Helvetica, sans-serif;
}
</style>
<div class="countdown-container">
<div class="countdown-digit-container">
<div class="countdown-days countdown-digits">00</div>
<h6 class="countdown-digit-title">Days</h6>
</div>
<div class="countdown-separator">:</div>
<div class="countdown-digit-container">
<div class="countdown-hours countdown-digits">00</div>
<h6 class="countdown-digit-title">Hrs</h6>
</div>
<div class="countdown-separator">:</div>
<div class="countdown-digit-container">
<div class="countdown-minutes countdown-digits">00</div>
<h6 class="countdown-digit-title">Mins</h6>
</div>
<div class="countdown-separator">:</div>
<div class="countdown-digit-container">
<div class="countdown-seconds countdown-digits">00</div>
<h6 class="countdown-digit-title">Sec</h6>
</div>
</div>
<script type="text/javascript">
(function() {
var CONFIG = {
ENABLE_DAYS: true,
ENABLE_HOURS: true,
ENABLE_MINUTES: true,
ENABLE_SECONDS: true,
// Set the digit element ids here
DAYS_SELECTOR: ".countdown-days",
HOURS_SELECTOR: ".countdown-hours",
MINUTES_SELECTOR: ".countdown-minutes",
SECONDS_SELECTOR: ".countdown-seconds",
// This format is valid in all browsers, and ensures there's no
// confusion about the month and day
DEADLINE: Date.parse("17 May 2024 11:59 PM")
};
// Calculate the time to the deadline with a minimum value of 0
var now = Date.now();
var timeToDeadline = Math.max(0, CONFIG.DEADLINE - now);
/*
We could compare each number against the related element's html, but
number-to-number comparison is faster, and by being simpler is more
reliable. So, we keep track of what each number was during the previous
iteration.
*/
var days, hours, minutes, seconds;
var lastDays, lastHours, lastMinutes, lastSeconds;
var lastTimestamp = 0;
function updateHTMLElements() {
// Set these to the id of whatever element should contain the digits
var daysElements = document.querySelectorAll(CONFIG.DAYS_SELECTOR);
var hoursElements = document.querySelectorAll(CONFIG.HOURS_SELECTOR);
var minutesElements = document.querySelectorAll(CONFIG.MINUTES_SELECTOR);
var secondsElements = document.querySelectorAll(CONFIG.SECONDS_SELECTOR);
// Updating the DOM is the most intensive part of this, so we only do it
// if the digit has changed
if (CONFIG.ENABLE_DAYS && lastDays !== days) {
lastDays = days;
daysElements.forEach(element => element.innerHTML = (days < 10 ? "0" : "") + days);
}
if (CONFIG.ENABLE_HOURS && lastHours !== hours) {
lastHours = hours;
hoursElements.forEach(element => element.innerHTML = (hours < 10 ? "0" : "") + hours);
}
if (CONFIG.ENABLE_MINUTES && lastMinutes !== minutes) {
lastMinutes = minutes;
minutesElements.forEach(element => element.innerHTML = (minutes < 10 ? "0" : "") + minutes);
}
if (CONFIG.ENABLE_SECONDS && lastSeconds !== seconds) {
lastSeconds = seconds;
secondsElements.forEach(element => element.innerHTML = (seconds < 10 ? "0" : "") + seconds);
}
}
function updateCountdown(timestamp) {
var milliseconds = parseInt(timestamp - lastTimestamp);
timeToDeadline = Math.max(0, timeToDeadline - milliseconds);
lastTimestamp = timestamp;
/*
For each unit of time, we only want to modulo (%) the number if the
next larger unit is enabled.
E.G. 2 Hours : 30 Minutes, not 2 Hours : 120 Minutes
*/
if (CONFIG.ENABLE_DAYS) {
days = parseInt(timeToDeadline / 86400000);
}
if (CONFIG.ENABLE_HOURS) {
hours = parseInt(timeToDeadline / 3600000);
if (CONFIG.ENABLE_DAYS) {
hours = hours % 24;
}
}
if (CONFIG.ENABLE_MINUTES) {
minutes = parseInt(timeToDeadline / 60000)
if (CONFIG.ENABLE_HOURS) {
minutes = minutes % 60;
}
}
if (CONFIG.ENABLE_SECONDS) {
seconds = parseInt(timeToDeadline / 1000)
if (CONFIG.ENABLE_MINUTES) {
seconds = seconds % 60;
}
}
updateHTMLElements();
// Stop updating once we reach the deadline
if (timeToDeadline > 0) {
window.requestAnimationFrame(updateCountdown);
}
}
window.requestAnimationFrame(updateCountdown);
})();
</script>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment