Cómo construir una cuenta regresiva de fecha con Vanilla JavaScript

En esta guía práctica, aprenda a crear un temporizador de cuenta regresiva de JavaScript estándar, con un hermoso estilo con CSS.

Introducción

Un temporizador de cuenta regresiva es un reloj virtual que inicia (o detiene) la cuenta regresiva desde una fecha específica para marcar el inicio (o finalización) de un evento. Se usan comúnmente en la página de inicio de un sitio web de comercio electrónico, sitios web en construcción, páginas de eventos y una variedad de otros lugares.

Por lo general, se usan para cumpleaños, la cuenta regresiva para el Año Nuevo, promociones e incluso deportes. El objetivo principal de un temporizador de cuenta regresiva es animar a las personas a tomar medidas, antes de que sea demasiado tarde, como comprar artículos o servicios, anticipar y registrarse para un evento, etc.

Esencialmente, estaríamos reservando una fecha determinada por adelantado. Luego, usando JavaScript, podemos deducir la fecha actual de la fecha especificada, que se realiza cada segundo, minuto u hora.

En esta guía práctica, aprenderemos cómo crear un contador de cuenta regresiva, creando un programa reutilizable que se puede usar en una amplia variedad de páginas de destino. Lo construiremos completamente en Vanilla JavaScript y, hacia el final, veremos cómo se podría hacer con bibliotecas de fechas de JavaScript como Moment.js también.

{.icon aria-hidden=“true”}

Nota: El código fuente de la aplicación también se puede encontrar en GitHub.

Cree una cuenta regresiva de fecha con JavaScript

Se recomienda que comprenda cómo crear un temporizador de cuenta regresiva usando solo JavaScript, en lugar de una solución precortada o un complemento, a menos que necesite agregar alguna funcionalidad más específica que es mejor cuidar con una biblioteca en lugar de desde rascar.

Debido a que no tiene dependencias, crear esto con Vanilla JavaScript le permite tener un código liviano: su sitio web no tendrá una carga adicional y no necesitará cargar scripts y hojas de estilo externos. Tendrá un mayor control, lo que significa que podrá diseñar el temporizador para que se comporte y aparezca exactamente como lo desea, en lugar de intentar modificar un complemento a su voluntad.

Comenzando

Establezcamos una fecha objetivo, que actuará como el día del evento para el que estamos creando una cuenta regresiva. También puede crear dinámicamente esta fecha en función de parámetros, como crear una cuenta regresiva para que un usuario verifique su dirección de correo electrónico.

Estableceremos una fecha estática por motivos de brevedad:

1
2
let interval;
const eventDay = new Date('03/03/2022');

{.icon aria-hidden=“true”}

Nota: El constructor Date toma fechas en el formato (MM/DD/YYYY). También tenemos un intervalo en blanco para una asignación posterior.

Configuremos también un par de valores constantes. Por lo general, trabajar con el tiempo (en la escala de segundos) se realiza en milisegundos, y la mayoría de los métodos/comandos aceptan y devuelven valores de milisegundos.

En base a eso, definamos la duración de un segundo, minuto, hora y día, para que podamos usarlos si es necesario para la cuenta regresiva:

1
2
3
4
const second = 1000;
const minute = second * 60;
const hour = minute * 60;
const day = hour * 24;
Crear una función de cuenta regresiva

Ahora, al meollo de la lógica: ¡la función de cuenta regresiva!

1
2
3
const countDownFn = () => {
   // All logic goes in
}

Dependiendo de la frecuencia con la que desee que se actualice el temporizador, cada segundo, minuto u hora, llamará a la función con intervalos apropiados:

1
2
3
everySecond = setInterval(countDownFn, second)
everyMinute = setInterval(countDownFn, minute)
everyHour = setInterval(countDownFn, hour)

Ahora, obtengamos la fecha actual y luego restémosla del eventDay (en el futuro) para saber la diferencia entre ellos. Luego, según esta diferencia, sabremos cuántos días, horas, minutos y segundos quedan:

1
2
let now = new Date();
let timeSpan = eventDay - now;

{.icon aria-hidden=“true”}

Nota: Es importante colocar la creación de instancias para la hora actual (ahora) dentro de la función de cuenta regresiva, ya que la "hora actual" cambia constantemente. Cuando llamamos a la función para actualizar el temporizador, obtendrá la hora actualizada. En segundo lugar, estamos usando let en lugar de const, ya que el valor cambia cada segundo.

¡Finalmente, agreguemos una verificación de si el día del evento ha llegado o no! Una vez que llega a cero, ya no hay necesidad de contar hacia atrás. Para esto, haremos uso de una declaración if-elseif.

En primer lugar, implementemos la declaración if para verificar si el día del evento establecido por el usuario ya está en el pasado:

1
2
3
4
if (timeSpan <= -today) {
  console.log("Unfortunately we have past the event day");
  clearInterval(interval);
}

Si timeSpan, el resultado de la resta de la fecha y la hora actuales del eventDay es menor o igual que cualquier momento después de hoy: es negativo, o más bien, en el pasado.

Finalmente, verifiquemos si la cuenta regresiva debe terminar:

1
2
3
4
5
else if (timeSpan <= 0) {
  console.log("Today is the event day");
  clearInterval(interval);
  return;
}

La función clearInterval() borra el intervalo, por lo que esta lógica no se vuelve a llamar en cada intervalo (segundo, minuto, etc.).

Finalmente, podemos calcular la cantidad de segundos, minutos, horas y días restantes, si las dos comprobaciones anteriores dan como resultado falso:

1
2
3
4
5
6
7
8
else {
  const days = Math.floor(timeSpan / day)
  const hours = Math.floor((timeSpan % day) / hour)
  const minutes = Math.floor((timeSpan % hour) / minute)
  const seconds = Math.floor((timeSpan % minute) / second)

  console.log(days + ":" + hours + ":" + minutes + ":" + seconds);
}

En lugar de imprimir en la consola, ¡construyamos una página HTML simple para mostrar los resultados!

Página HTML

Construyamos una pequeña página para mostrar los resultados. Querremos tener algún tipo de elemento para, digamos, día, hora, minuto y segundo:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="UTF-8" />
        <meta http-equiv="X-UA-Compatible" content="IE=edge" />
        <meta name="viewport" content="width=device-width, initial-scale=1.0" />
        <title>JS Countdown Timer</title>
    </head>
    <body>
        <div class="date-countdown-container">
            <h2 id="day">0</h2>
            <p>:</p>
            <h2 id="hour">0</h2>
            <p>:</p>
            <h2 id="minute">0</h2>
            <p>:</p>
            <h2 id="second">0</h2>
        </div>
        <script src="./app.js"></script>
    </body>
</html>

El script app.js contiene todo el código, incluido countDownFn(). Ahora, podemos modificar la salida de la función para que no imprima los valores en la consola, sino que modifique los divs día, hora, minuto y segundo:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
let dayField = document.getElementById('day');
let hourField = document.getElementById('hour');
let minuteField = document.getElementById('minute');
let secondField = document.getElementById('second');

// Constants and countDownFn
const countDownFn = () => {...}

// Set results
dayField.innerHTML = days;
hourField.innerHTML = hours;
minuteField.innerHTML = minutes;
secondField.innerHTML = seconds;

¡Esto debería funcionar bien! Sin embargo, no tiene mucho estilo. Avancemos y agreguemos algo de CSS para que sea mucho más agradable de ver.

CSS: estilo del temporizador de cuenta regresiva

¡Agreguemos un poco de estilo al temporizador! Agregaremos una fuente más agradable, cambiaremos el color de fondo, centralizaremos los elementos y los colocaremos en contenedores estilizados con sombras:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
*{
  margin: 0;
  padding: 0;
  box-sizing: border-box;
}

body{
  font-family: 'Poppins', sans-serif;
  height: 100vh;
  width: 100%;
  background: rgb(175, 90, 90);
  display: flex;
  justify-content: center;
  align-items: center;
}

.date-countdown-container{
  display: flex;
  align-items: center;
  gap: 30px;
}

.date-countdown-container h2{
  background-color: #ddd;
  padding: 20px;
  border-radius: 10px;
  border: 5px solid #fff;
  -webkit-box-shadow: 8px 0px 0px 0px #DCD0C0, 0px 8px 0px 0px #B1938B, -8px 0px 0px 0px #4E4E56, 0px 0px 0px 8px #DA635D, 5px 5px 15px 5px rgba(0,0,0,0); 
  box-shadow: 8px 0px 0px 0px #DCD0C0, 0px 8px 0px 0px #B1938B, -8px 0px 0px 0px #4E4E56, 0px 0px 0px 8px #DA635D, 5px 5px 15px 5px rgba(0,0,0,0);
}

.date-countdown-container p{
  background-color: #ddd;
  padding: 2px;
  border-radius: 10px;
  border: 2px solid #fff;
  -webkit-box-shadow: 8px 0px 0px 0px #DCD0C0, 0px 8px 0px 0px #B1938B, -8px 0px 0px 0px #4E4E56, 0px 0px 0px 8px #DA635D, 5px 5px 15px 5px rgba(0,0,0,0); 
  box-shadow: 8px 0px 0px 0px #DCD0C0, 0px 8px 0px 0px #B1938B, -8px 0px 0px 0px #4E4E56, 0px 0px 0px 8px #DA635D, 5px 5px 15px 5px rgba(0,0,0,0);
}

Una vez hecho esto, agreguemos la hoja de estilo a <head> del archivo HTML:

1
<link rel="stylesheet" href="style.css"/>

Ejecutando la aplicación

Finalmente, ¡podemos ejecutar la aplicación!

Easy vanilla JS countdown timer implementation

¿Usando Moment.js?

Si ya está usando Moment.js, no hay nada de malo en usarlo para esto también. No es absolutamente necesario tener una dependencia si no la necesita para otra cosa, pero ofrece una útil función diff():

1
2
3
const eventDay = moment("2023-06-03");
const now = moment();
const timeSpan = eventDay.diff(now);

En pocas palabras, estas tres líneas son las principales variables que ayudan en la ejecución de la cuenta regresiva, y son las variables que proporciona o permite que se obtengan del programa, en este caso de Moment.js.

Si tuviera que reemplazar la lógica de manejo de tiempo del código original con esto, contendría:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
let dayField = document.getElementById('day');
let hourField = document.getElementById('hour');
let minuteField = document.getElementById('minute');
let secondField = document.getElementById('second');

let interval;
const eventDay = moment("2023-06-03");
  
// Convert to milisecond
const second = 1000;
const minute = second * 60;
const hour = minute * 60;
const day = hour * 24;
  
const countDownFn = () => {
    const today = moment();
    const timeSpan = eventDay.diff(today);
  
    if (timeSpan <= -today) {
        console.log("Unfortunately we have past the event day");
        clearInterval(interval);
        return;
    } else if (timeSpan <= 0) {
        console.log("Today is the event day");
        clearInterval(interval);
        return;
    } else {
        const days = Math.floor(timeSpan / day);
        const hours = Math.floor((timeSpan % day) / hour);
        const minutes = Math.floor((timeSpan % hour) / minute);
        const seconds = Math.floor((timeSpan % minute) / second);
  
        // Set results
        dayField.innerHTML = days;
        hourField.innerHTML = hours;
        minuteField.innerHTML = minutes;
        secondField.innerHTML = seconds;
    }
};
  
interval = setInterval(countDownFn, second);

Conclusión

En esta guía práctica, aprendimos cómo crear nuestro propio temporizador de cuenta regresiva con solo un breve script de JavaScript y diseñamos una página HTML para mostrar la cuenta regresiva, así como también cómo utilizar Moment.js para realizar aritmética de tiempo.