¡Te doy la bienvenida a un nuevo reto de CSS! Esta vez vamos a hacer un Toggle Button para cambiar de Light Mode a Dark Mode usando animaciones de CSS y JavaScript.
Compártenos el resultado final en los comentarios y/o en Twitter con el hashtag #RetosPlatziCSS. 😉
Antes de comenzar, los cursos de Platzi que te recomiendo para realizar este reto son los siguientes:
Para este reto te propongo que realices los siguientes 4 pasos:
💡 Recomendación: Evita copiar y pegar el código. Trata de transcribir cada detalle y entender muy bien su funcionamiento (sin afán, tómate tu tiempo). Solo de esta forma podrás convertirte en un(a) experto(a) en maquetación con CSS.
ʕ•́ᴥ•̀ʔっ ¡Empecemos!
Lo primero que tenemos que tener en cuenta es que nuestro botón en realidad será un input de tipo checkbox que nos permitirá hacer el switch entre el modo claro y el modo oscuro. También tendremos un label que estilizaremos a nuestro gusto.
En primera instancia, pensemos que la base fundamental de nuestro toggle button para el modo claro debe verse de la siguiente manera:
Y para el modo oscuro debe verse de esta otra forma:
Teniendo en cuenta lo anterior, esta es la paleta de colores que en nuestro CSS se vería de la siguiente forma:
:root {
--light-0: #f8f9fa;
--light-1: #e9ecef;
--light-2: #dee2e6;
--dark-0: #495057;
--dark-1: #343a40;
--dark-2: #212529;
}
Ahora debemos escribir el HTML que nos permitirá tener el input
, el label
y el div
para la bolita del centro:
<input id="toggle-button" type="checkbox">
<labelfor="toggle-button">
<div class="sun-moon"></div>
</label>
Teniendo nuestro HTML podemos escribir los estilos para nuestro body
, tanto para el modo claro como para el modo oscuro.
A nuestro body le quitaremos la margen por defecto (margin: 0
) y le añadiremos
background: var(--light-0)
).display: grid
y place-items: center
).height: 100vh
).transition: background 0.3s ease
).body {
background: var(--light-0);
display: grid;
height: 100vh;
margin: 0;
place-items: center;
transition: background 0.3s ease;
}
A nuestro body también le añadiremos una clase llamada dark
que nos permitirá cambiar el background a partir de JavaScript más adelante:
body.dark {
background: var(--dark-2);
}
Con nuestro body listo comenzamos a estilizar nuestro label para el modo claro. Debemos añadir una posición relativa (position: relative
) para que nuestro input se pueda ocultar detrás de él (con position: absolute
), también añadimos un background para el modo claro (background: var(--light-2)
), un borde redondeado (border-radius: 20px
), una manita en el cursor que indique que podemos hacer click allí (cursor: pointer
), un alto (height: 38px
) y un ancho (width: 68px
):
input {
position: absolute;
}
label {
background: var(--light-2);
border-radius: 20px;
cursor: pointer;
height: 38px;
position: relative;
width: 68px;
}
Y para el modo oscuro del label debemos decirle al input que cuando esté checkeado (#toggle-button:checked
) cambie el background de su hermano (+ label
):
#toggle-button:checked + label {
background: var(--dark-0);
}
Ahora podemos crear los estilos para la bolita del centro. Yo voy a añadir un color de fondo (background: var(--light-1)
), un ancho (width: 30px
) y un alto (height: 30px
) con las mismas dimensiones, un redondeado para hacer la forma de un círculo (border-radius: 50%
), un margen para que no quede tan cerca a los bordes del label (margin: 4px
) y finalmente una transición a la transformación (que hará que se desplace de izquierda a derecha) para cuando hagamos el switch entre el modo claro y oscuro y no se vea tan tosco (transition: transform 0.3s ease
):
label.sun-moon {
background: var(--light-1);
border-radius: 50%;
height: 30px;
margin: 4px;
transition: transform 0.3s ease;
width: 30px;
}
Para el modo oscuro de la bolita debemos decirle al input que cuando esté checkeado (#toggle-button:checked
) cambie el background (background: var(--dark-1)
) y le añada una transformación (transform: translateX(30px)
) del hijo de su hermano (+ label .sun-moon
):
#toggle-button:checked + label.sun-moon {
background: var(--dark-1);
transform: translateX(30px);
}
Una vez que tenemos los estilos de nuestro toggle button, debemos decirle desde JavaScript que añada la clase dark
al body una vez nuestro input este checkeado para obtener el siguiente efecto:
Para eso debemos acceder al DOM de la siguiente forma:
const toggleButton = document.getElementById('toggle-button')
Luego le decimos que escuche cuando se haga un cambio en el toggle buttton (es decir, cada vez que se le haga click):
toggleButton.addEventListener('change', () => {
// Ahorita ponemos código aquí :)
})
Finalmente, cada que suceda ese cambio le agregamos la clase dark
solo cuando esté activo el input:
toggleButton.addEventListener('change', () => {
document.body.classList.toggle('dark')
})
En este paso quiero que seas muy libre y añadas el estilo que más te guste. Para eso, aquí te comparto varios ejemplos de la comunidad de CodePen para que te inspires:
En mi caso, quise agregar unos GIF’s de fondo, así:
Para lograrlo añadí dos colores más (--green
y --blue
):
:root {
--light-0: #f8f9fa;
--light-1: #e9ecef;
--light-2: #dee2e6;
--dark-0: #495057;
--dark-1: #343a40;
--dark-2: #212529;
--green: #c3c82c;
--blue: #2939ff;
}
También hice modificaciones a los backgrounds quitándoles los colores planos y añadiendo los GIFs:
label {
align-items: center;
background: var(--light-2);
background: url('https://i.ibb.co/ZWmbGbj/etmfdr.gif');
background-position: bottom;
background-size: cover;
border-radius: 35px;
box-shadow: 019px38pxrgba(0,0,0,0.30), 015px12pxrgba(0,0,0,0.22);
cursor: pointer;
display: flex;
height: 60px;
position: relative;
width: 110px;
}
#toggle-button:checked + label {
background: var(--dark-0);
background: url('https://i.pinimg.com/originals/94/ff/74/94ff7463a1574221ba6d4ada2c997e0b.gif');
background-position: center;
background-size: cover;
}
label.sun-moon {
background: radial-gradient(var(--green), transparent);
border-radius: 50%;
height: 30px;
margin: 4px;
transition: transform 0.3s ease;
width: 30px;
}
#toggle-button:checked + label.sun-moon {
background: radial-gradient(var(--blue), transparent);
transform: translateX(72px);
}
¡Este paso es mi favorito! Compártenos en los comentarios y/o en Twitter con el hashtag #RetosPlatziCSS el resultado final de tu toggle de light a dark mode. 😄
Aquí te comparto mi codepen, mi repositorio de GitHub y el deploy con el resultado final.
¡Cuéntanos qué otro tipo de retos te gustaría encontrar en esta sección!
#NuncaParesDeAprender
wow!!! acabo de terminar uno y ya hay otro, excelente!! 🤗
Esoooo !!! ✨ 🚀 🌚
reto cumplido! muchas, excelente tuto bien explicado, muchas gracias.
WOOOOOOOW !!! 🤩 Espectacular es POCO !!! Muchas felicitaciones, te quedó increíble… Fan #1 de este resultadooo 💚
Me encantó el tutorial, aquí están mis resultados:)
Más que espectacular !!! 🤩 Increíble resultado… TOP !!! 💚 Muchas felicitacionesss 👏🏼
Se ve súper padre, justo estaba buscando algo relacionado al dark mode, el único detalle es que aún no tengo conocimiento sobre las arrow functions 😦 ¿Algún curso para ello?
El curso de ES6 tiene una clase sobre arrow functions, y usualmente en React siempre se ocupan, asi que podrias ver los cursos de React.
Clases del Curso de ECMAScript 6+
Espectacular!!! Voy a intentar integrar el dark mode a mi porafolio para darle un toque mas profesional. Gracias!!!
Esooo 💚💚💚💚
Esto está genial. Aunque todavía no tengo casi conocimientos de animaciones en CSS (pero me estoy haciendo todos los newbie challenges de frontendmentor ^^), voy a guardar este post para resolverlo en un par de semanas cuando tenga los conocimientos…
Gracias por esta oportunidad Teff!
Eso está genial !!! Ya hiciste los cursos que tenemos aquí en Platzi sobre animaciones ? Te los súper recomiendooo 🥰 Mira:
Curso de Transformaciones y Transiciones en CSS: https://platzi.com/cursos/transformaciones-transiciones-css/
Curso de Animaciones con CSS: https://platzi.com/cursos/animaciones-css/
Curso Práctico de Maquetación y Animaciones con CSS: https://platzi.com/cursos/animaciones-css-practico/
Not yet, pero calculo en 2 semanas estar ahí 😄. Fantástico! Voy a empezar con el de Transformaciones y Transiciones, quiero hacer que un hover pinte de color una imagen oscura en blur con baja opacidad y aparezca un texto, como flotando…
De hecho me acabas de dar una idea.
A darle! Gracias por todo Teff! You rock!
Me encanta !!! De unaaa 💪🏼 Me muestras cuando lo hagassss… suena espectacular 🤩
Y, siempre es con el mayor de los gustos 💚
Me acabas de salvar la vida para un proyecto que ahora mismo estoy llevado acabo! Muchas gracias!
Que bien Rodrigo 😄
Espero nos compartas tu resultado.
Yujuuuu 🤩💚