100 DAYS CSS CHALLENGE: Day #2
Tags: javascript, css, html, challenge
Published: 2024-03-08 01:40:23

**Hola Mundo**.

El ejercicio del día #2 requirió utilizar animaciones. Las cuales no estoy muy familiarizado. El objetivo de este reto es entender y comprender el mundo que es el CSS.

## Day 2
[100 DAYS CSS CHALLENGE DAY 2](https://100dayscss.com/days/2/).
![Reto día dos](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/c2n0ubwz772hry4jgadv.png)

### Código base del reto
**HTML**
```html
<div class="frame">
  <div class="center">
		<p>Happy coding :)</p>
  </div>
</div>
```
**CSS**
```css
// delete the following line if no text is used
// edit the line if you wanna use other fonts
@import url(https://fonts.googleapis.com/css?family=Open+Sans:700,300);

// use only the available space inside the 400x400 frame
.frame {
  position: absolute;
  top: 50%;
  left: 50%;
  width: 400px;
  height: 400px;
  margin-top: -200px;
  margin-left: -200px;
  border-radius: 2px;
	box-shadow: 4px 8px 16px 0 rgba(0,0,0,0.1);
	overflow: hidden;
  background: #fff;
  color: #333;
	font-family: 'Open Sans', Helvetica, sans-serif;
	-webkit-font-smoothing: antialiased;
	-moz-osx-font-smoothing: grayscale;
}

.center {
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%,-50%);
}

```
### 1. Identificar los elementos del reto

![Elementos identificados](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/trbsc0es690juerxbc28.png)

El elemento cuenta con 4 contenedores. 

El contenedor principal sirve para contener 3 contenedores con estilo de líneas.

De igual manera se pueden identificar alrededor de 6 animaciones, 2 animaciones por línea

![Después de la transformación](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ddzzc2wk41vjjd70bdn8.png)

Al momento de darle clic, el primero y última línea se desplazan al centro, después de llegar rotan para quedar en diagonal y formar una **X**. La línea de en medio se encoge mientras cambia su opacidad.

Una vez toma la forma de **X** Al darle clic pasa a su forma original de la manera inversa.

### 2. Maquetación de los elementos

Para el contenedor principal cree un div al cual le asigne un, **Id** para posteriormente acceder a él mediante JS, la clase **btn** para aplicar estilos. A sí como él role **button** que sería el papel que plantea el reto un botón de menú de hamburguesa

Para las líneas les asigné dos clases, una de ellas la comparten esta contaría y la segunda para identificar a cada uno por separado.

```html
<div id="btn-1" class="btn" role="button">
  <div class="line line-1"></div>
  <div class="line line-2"></div>
  <div class="line line-3"></div> 
</div>
```

### 3. Estilos básicos.
Para el diseño del contenedor principal. Opte por hacer uso de display flex para facilitar el acomodo de los elementos

Dejo un recurso rápido del uso de [flexbox](https://cssreference.io/flexbox/)
```css
btn {
  display: flex;
  flex-direction: column;
  justify-content: space-between;
  width: 80px;
  height: 52px;
}

.btn .line {
  background: white;
  width: 80px;
  height: 8px;
  border-radius: 3px;
  box-shadow: 0 0 13px 0 rgba(0, 0, 0, 0.3);
}
.btn:hover {
  cursor: pointer;
}
```

Resultado de la aplicación de estilos
![Resultado de los estilos](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/byujd6xx15ot4ioqpjhm.png)

### 4. Animación de entrada

La animación de entrada de la línea 1 y línea 3 se dividen en dos. 
1. Desplazamiento al centro.
2. Rotación diagonal.

Mientras que la línea 3 escala su tamaño mientras baja su opacidad.

Para realizar esto haré uso de [keyframes](https://developer.mozilla.org/en-US/docs/Web/CSS/@keyframes)

De manera resumida, los keyframes nos permite definir estilos de css por frame para la creación de animaciones.

**Animación de la línea 1 y 3**
Para este caso definí el 70% y 100%. El 0% sería la posición inicial.
- **70%** Traslada en el eje y 21 píxeles.
- **100%** Rota la línea -45 grados y termina de acomodar la linea para centrarla.

En el caso del translate que agregue en el 100% lo hice a ojo mirando que la X que se forma se mirara céntrica.

Para la línea 3 el translareY es negativo, ya que va de abajo hacia arriba.

```css
/* Linea 1 */
@keyframes moveTopToCenter {
  70% {
    transform: translateY(21px);
  }
  100% {
    transform: rotate(-45deg) translateY(17px) translateX(-14px);
  }
}

/* Linea 3 */
@keyframes moveBottomToCenter {
  70% {
    transform: translateY(-21px);
  }
  100% {
    transform: rotate(45deg) translateY(-14px) translateX(-15px);
  }
}
```

**Animación de la línea 3**

Para esta línea fue un scale de 1 a 0, agregando opacidad de 0.7 al 50% para evitar que se visualiza muy transparente a la mitad de la animación para al 100% ser de 0

```css
@keyframes reduce {
  0% {
    transform: scale(1);
  }
  50% {
    transform: scale(0.7);
    opacity: 0.7;
  }
  100% {
    transform: scale(0);
    opacity: 0;
  }
}
```

Para el manejo de tiempo de animación, cree otra clase llamada animated. La cual uso para aplicarle a todas la misma duración.


```css
.animated {
  animation-duration: 1s;
  animation-fill-mode: both;
}
```

> La idea de hacerlo de est amanera la aprendi de una libreria usada para la creacion de animaciones [Animate CSS](https://animate.style/)

Resultado después de la aplicación de los estilos

![Forma 100%](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/wzjgisfxipgiii84qp61.png)

Para regresarlas a la forma anterior, aplique lo mismo pero a la inversa.

```css
/* Linea 1 */
@keyframes leaveTopToCenter {
  0% {
    transform: rotate(-45deg) translateY(17px) translateX(-14px);
  }
  30% {
    transform: rotate(0deg) translateY(21px) translateX(0px);
  }
  100% {
    transform: translateY(0);
  }
}

/* Linea 3 */
@keyframes leaveBottomToCenter {
  0% {
    transform: rotate(45deg) translateY(-14px) translateX(-15px);
  }
  30% {
    transform: rotate(0deg) translateY(-21px) translateX(0px);
  }
  100% {
    transform: translateY(0);
  }
}
/* Linea 2 */
@keyframes expand {
  0% {
    transform: scale(0);
    opacity: 0;
  }
  100% {
    transform: scale(1);
    opacity: 1;
  }
}
```
### 5. JS para controlar la animación
Esta fue mi propuesta para el código donde al momento de darle clic  al botón agrega las clases respectivas apara la transformación.
```js

 const btn1 = document.getElementById("btn-1");
 const lines = document.getElementsByClassName("line");

// Funcion para eliminar y agregar clases a elemetnos html
 const classHelper = (elementHtml, classAdd, classRemove) => {
   elementHtml.classList.add(classAdd);
   elementHtml.classList.remove(classRemove);
 };

// Funcion qencargada de disparar la animacion
 const dispatchAnimation = () => {
   const [line1, line2, line3] = lines;
  
   if (line1.classList.contains("moveTopToCenter")) {
      classHelper(line1, "leaveTopToCenter", "moveTopToCenter");
      classHelper(line2, "expand", "reduce");
      classHelper(line3, "leaveBottomToCenter", "moveBottomToCenter");

       classHelper(line2, "d-block", "d-none");
        } else {
       classHelper(line1, "moveTopToCenter", "leaveTopToCenter");
       classHelper(line2, "reduce", "expand");
       classHelper(line3, "moveBottomToCenter", "leaveBottomToCenter");
        // Al momento de terminar la animacion principal aplico estilos
        // Para ocultar el linea 2

        setTimeout(() => {
          classHelper(line2, "d-none", "d-block");
        }, 500);
      }
 };

 btn1.addEventListener("click", () => {
   const clasess = btn1.classList;
   
   // Clase que utiliso para saber si actualmente se encuentra en transicion
   if (clasess.contains("is-animating")) return;
   
   // Agrego la clase de que se esta animando
   btn1.classList.add("is-animating");
   
   // Mando a llamar la funcion para aplicar al animacion
   dispatchAnimation();
   
   // Elimino la clase de que se esta animando.
   setTimeout(() => {
      btn1.classList.remove("is-animating");
     }, 700);
  });
```
### Resultado final

{% codepen https://codepen.io/dylanson25/pen/ZEZQOOV %}

Revisando la manera en que lo realiza la página de 100 días de CSS, a sí como videos de YouTube realizando el mismo ejercicio, encontré puntos de mejora en mi código para hacerlo más legible y óptimo.

Háganme saber en los comentarios si quieren un post analizando los cambios que se pueden aplicar y otras formas de realizar este reto del día dos.