77

Muñecas Rusas con Animaciones en CSS

17186Puntos

hace 3 años

En esta guía te enseñaré a hacer estas hermosas muñecas rusas con animaciones CSS.

Muñecas rusas con CSS

Definamos nuestros objetivos:

  • Dar click en una muñeca para que se abra.
  • Al abrir una muñeca, mostrar otra muñeca más pequeña.

Los pasos que debemos seguir para lograr nuestro proyecto son:

  1. Crear las cajas de HTML para cada una de las muñecas.
  2. Apilar las cajas una encima de la otra.
  3. Abrir la caja al hacerle click.
  4. Al hacer click en una caja, mostrar la caja interna.
  5. Al mostrar la caja interna, desplazarla en el eje X.
  6. Darle estilos a nuestras muñecas rusas.
  7. ¡Compártenos tu resultado en los comentarios!

⚠️ Recomendación
Evita copiar y pegar el código. Trata de transcribir cada detalle y entender muy bien su funcionamiento. Solo de esta forma podrás convertirte en experta o experto maquetando con CSS.

ʕ•́ᴥ•̀ʔっ ¡Empecemos!

1️⃣ Crear las cajas de HTML para cada una de las muñecas

Lo primero que debemos definir es la cantidad de muñecas que queremos hacer. Para este caso decidí que fueran 4. Sin embargo, este valor lo puedes modificar a tu gusto.

El HTML para cada una de las muñecas estará descrito por 2 etiquetas: <input type="checkbox"> y <label>. Al conectarlas, podremos hacer uno de los trucos de CSS más antiguos pero más útiles, que nos permitirá ocultar el input y activarlo o desactivarlo al hacer click en label.

¿Para qué? Para poder estilizar la etiqueta <label>, darle forma de muñeca rusa y para que a partir de selectores combinadores podamos diseñar/modificar/animar los elementos hermanos (las muñecas internas) dependiendo de si el label está checkeado o no (en nuestro caso, si está checkeada la primera muñeca, podremos decirle a la muñeca interna que se muestre y se desplace).

Para esto tendremos la siguiente estructura de HTML:

<form>
  <input id="doll0"type="checkbox"/>
  <labelfor="doll0"></label>
  
  <input id="doll1"type="checkbox"/>
  <labelfor="doll1"></label>
  
  <input id="doll2"type="checkbox"/>
  <labelfor="doll2"></label>

  <input id="reset"type="reset"/>
  <labelfor="reset"></label>
</form>

Como puedes notar, el último input no es de tipo checkbox, sino que es de tipo reset. Lo que nos va a permitir, como su nombre lo indica, es resetear el estado de las muñecas para volver a comenzar. Esto nos ahorrará usar JavaScript y nos permitirá ver las muñequitas salir una tras otra las veces que queramos sin tener que recargar la página.

Algo adicional es crear dos estructuras para cada muñeca: la parte de arriba y la parte de abajo. Esto lo haremos con dos <div> como puedes ver a continuación:

<inputid="doll0"type="checkbox"/><labelfor="doll0"><div>top</div><div>bottom</div></label>

La idea sería replicar esto mismo para cada una de las muñecas.

2️⃣ Apilar las cajas una encima de la otra.

El anterior HTML nos va a mostrar cada elemento uno debajo del otro. Sin embargo, nosotros necesitamos que se muestre solo la primera muñeca y que las demás estén detrás de ella (en el eje Z), y además de esto, ocultas.

Lo primero que vamos a hacer, es estilizar nuestro contenedor principal <body> para centrar los elementos en la mitad de la pantalla a lo largo del eje Y y añadirle un color de fondo, así:

body {
  width: 100%;
  height: 100vh;
  margin: 0;
  display: flex;
  align-items: center;
  background: #F9C2C5;
}

También, ocultaremos los elementos <input> y agregaremos un margen al formulario para que nos de un poco de espacio, así:

input[type='checkbox'],
input[type='reset'] {
  display: none;
}

form {
  margin: 20px;
}

Hasta el momento, deberíamos ver algo como esto:

Lo segundo que haremos, es hacer que cada muñeca esté una detrás de la otra y ocultas. Para esto, añadiremos el siguiente CSS:

label {
  position: absolute;
  opacity: 0;
}

Sin embargo, la primera muñeca tampoco se nos vería 😅, así que debemos “forzar” a que se vea haciendo uso del concepto de especificidad.

Lo que haremos es añadirle un estilo en línea con una opacidad de 1:

<inputid="doll0"type="checkbox"/><labelfor="doll0"style="opacity: 1"><div>top</div><div">bottom</div></label>

Como tercer paso, lo que haremos es añadir las clases doll y doll0 (donde 0 indica que es para la primera muñeca, 1 sería la segunda y así sucesivamente) para crear un tamaño a la cajita de la muñeca y posteriormente cambiarle el z-index.

Gracias al orden de nuestro HTML, las muñecas irían: la 4 encima de la 3, la 3 encima de la 2, la 2 encima de la 1. Pero lo que queremos es que se apilen al contrario: que la primera que veamos sea la 1 y que atrás de ella esté la 2, que detrás de la 2 esté la 3 y que detrás de la 3 esté la 4.

Para lo anterior tendríamos el siguiente HTML:

<form>
  <input id="doll0"type="checkbox"/>
  <labelclass="doll doll0"for="doll0"></label>
  
  <input id="doll1"type="checkbox"/>
  <labelclass="doll doll1"for="doll1"></label>
  
  <input id="doll2"type="checkbox"/>
  <labelclass="doll doll2"for="doll2"></label>

  <input id="reset"type="reset"/>
  <labelclass="doll doll3"for="reset"></label>
</form>

Y el siguiente CSS:

.doll {
  width: 100px;
  height: 100px;
}
.doll0 {
  z-index: 4;
}
.doll1 {
  z-index: 3;
}
.doll2 {
  z-index: 2;
}
.doll3 {
  z-index: 1;
}

Con base en lo anterior, deberíamos ver algo como esto:

3️⃣ Abrir la caja al hacerle click.

Ahora debemos añadir unas clases adicionales para los <div> que hacen parte de la estructura de las muñecas:

<input id="doll0" type="checkbox"/>
<label class="doll doll0"for="doll0" style="opacity: 1">
    <div class="doll__body doll--top">top</div>
    <div class="doll__body doll--bottom">bottom</div>
</label>

Añadiremos un CSS con algunos colores random (solo para diferenciar las dos partes de las muñecas) y un alto del 50% del tamaño total del <label>:

.doll__body {
  width: 100%;
  height: 50%;
}
.doll--top {
  background: hotpink;
}
.doll--bottom {
  background: papayawhip;
}

Para darle click a la cajita y que la parte superior se desplace hacia arriba y la parte inferior se desplace hacia abajo, debemos:

  • Usar la pseudoclase :checked para identificar cuando está checkeada cajita.
  • Usar el selector de + para identificar la parte superior o inferior del primer label y desplazarlo.

Lo anterior escrito en CSS para desplazar la parte superior de la cajita clickeada, sería:

input:checked + label .doll--top {...}

Recordemos que nuestra estructura de HTML es:

<input id="doll0" type="checkbox"/>
<label class="doll doll0"for="doll0" style="opacity: 1">
    <div class="doll__body doll--top">top</div>
    <div class="doll__body doll--bottom">bottom</div>
</label>

Con el CSS anterior lo estamos definiendo en último HTML que si el <input id="doll0" type="checkbox"/> está checkeado, entonces el <div class="doll__body doll--top">top</div> hará algo (para nuestro caso, desplazarse).

El + nos va a garantizar que sólo sea ese <div> y no todos los <div> con esa clase doll--top, ya que sólo queremos que la muñequita que está detrás de la clickeada se desplace y no las demás.

Ahora, lo más divertido: crear la animación para desplazar las dos partes de la cajita (una hacia arriba y otra hacia abajo). Para ello usaremos la propiedad animation y los keyframes.

Para la parte superior sería:

input:checked + label.doll--top {
  animation: up 0.3s forwards;
}
@keyframes up {
  from { transform: translateY(0); }
  to { transform: translateY(-100%); }
}

Aquí lo que estamos haciendo es diciéndole que empiece en la posición 0 (from) y se traslade la misma cantidad de píxeles que mide hacia arriba (to) durante 0.3 segundos y se quede en la posición final (forwards).

Para la parte inferior sería:

input:checked + label.doll--bottom {
  animation: down 0.3s forwards;
}
@keyframes down {
  0% { transform: translateY(0); }
  100% { transform: translateY(100%); }
}

Aquí estamos diciéndole que empiece en la posición 0 (from) y se traslade la misma cantidad de píxeles que mide hacia abajo (to) durante 0.3 segundos y se quede en la posición final (forwards).

Con lo anterior, deberíamos ver lo siguiente:

En este punto, te invito a que realices los cursos de animaciones con CSS que hemos diseñado especialmente para ti:

4️⃣ Al hacer click en una caja, mostrar la caja interna.

Para poder mostrar la caja que está inmediatamente detrás de la caja clickeada, lo que debemos hacer es lo siguiente:

forminput:nth-child(1):checked + label + input + label {
  opacity: 1;
}

Lo que estamos diciendo aquí es definir que wl <label> que está después del <input> que está después del <label> que está después del primer <input> clickeado del <form> debe tener una opacidad de 1. Siempre se lee de atrás para adelante.

Esto mismo lo debemos replicar para los siguientes <input> y quedaría de la siguiente manera:

forminput:nth-child(3):checked + label + input + label {
  opacity: 1;
}

forminput:nth-child(5):checked + label + input + label {
  opacity: 1;
}

5️⃣ Al mostrar la caja interna, desplazarla en el eje X.

Como ya sabemos cómo mostrar la cajita que está inmediatamente detrás de la caja clickeada, lo que debemos hacer es desplazarla hacia la derecha (como si la estuviéramos sacando). Para eso, agregamos la siguiente animación:

forminput:nth-child(1):checked + label + input + label {
  opacity: 1;
  animation: move1 0.3s forwards;
}
@keyframes move1 {
  from { transform: translateX(0); }
  to { transform: translateX(100px); }
}

Esto es muy similar a la animación que hicimos anteriormente, solo que ahora estamos trasladando la cajita en el eje X (horizontalmente).

Las siguientes cajitas quedarían de la siguiente manera:

forminput:nth-child(3):checked + label + input + label {
  opacity: 1;
  animation: move2 0.3s forwards;
}
@keyframes move2 {
  from { transform: translateX(100px); }
  to { transform: translateX(200px); }
}
forminput:nth-child(5):checked + label + input + label {
  opacity: 1;
  animation: move3 0.3s forwards;
}
@keyframes move3 {
  from { transform: translateX(200px); }
  to { transform: translateX(300px); }
}

Con lo anterior, tendríamos algo como esto:

6️⃣ Darle estilos a nuestras muñecas rusas.

Para dale forma a nuestras cajitas y que parezcan ahora sí muñecas rusas, lo que hice fue buscar una ilustración en Pinterest, recortar las diferentes partes de las muñequitas y añadirlas dentro de los <div> que habíamos creado. También, modifiqué el ancho y alto de las cajitas (las clases doll0, doll1, doll2 y doll3) para que se viera más grande la primera y más pequeña la última. Y, así quedó:

Te comparto mi CodePen con la solución completa.

¡También puedes hacer cada muñeca dibujando con CSS para estilizarla a tu gusto! 😍

7️⃣ ¡Compártenos tu resultado en los comentarios!

¡Este paso es mi favorito! Compártenos en los comentarios y/o en Twitter el resultado final de tus muñecas rusas. 😄

👩‍🏫Toma los cursos de animaciones en CSS

Finalmente, te invito a tomar la trilogía de cursos de maquetación, transformaciones, transiciones y animaciones con CSS:

Estefany
Estefany
teffcode

17186Puntos

hace 3 años

Todas sus entradas
Escribe tu comentario
+ 2
Ordenar por:
8
16263Puntos

Les comparto mi práctica.
Link
La muñeca la hice con CSS.
matrioshka.png

4
17186Puntos
3 años

Wow !!! Qué gran reto hacerlo con CSS 💚👏🏼 Te quedó geniaaal… pensé que era una imagen y todo 😱 Espectaculaaar… 🎉

5
62483Puntos

Buenas tardes les comparto lo que hice gracias a esta nota, en lugar de muñecas hice un cofre de Fortnite de la nueva temporada 7 jejeje y cuando le dan click aparece mi código de creador que aprovecho para pedirles usen si juegan fortnite xD

Enlace del sitio donde lo implemente:
https://stonks.company/stream

Esta es la imagen que hice
3
211919Puntos
3 años

Jejejeje
Muy buena implementación 👏

4
17186Puntos
3 años

Hahaha qué hermosoooo !!! Me encantó !!! 👏🏼💚

2
3 años

Está bueno, una observación sobre tu página, te sugiero que los videos o imágenes los guardes en un servidor externo porque demora al iniciar tu página, referente a la animación te quedó bien :3

1
62483Puntos
3 años

Gracias por la observación Leones, eso empezó a hacer justamente pensé en lo mismo, ahora me siento mas seguro de mi decisión :3

5
2356Puntos

Muy interesante, yo lo hice con dragones, desde el mas grande hasta el mas pequeño.
Tomare dichos cursos para aprender mas. Gracias!

4
62483Puntos
3 años

Estaría genial poder verlo con dragones, compártelo 😄

2
17186Puntos
3 años

Wow !!! Feliz de verlooo Angeeeel 😍