Ahorra Seguros
Deberían sacar un curso de puro angular material
Juan José Gómez Aguirre
Muy de acuerdo contigo!
Construir un menú lateral que aparezca y desaparezca con una animación fluida es una de las tareas más comunes en cualquier proyecto web moderno. Aquí se explica paso a paso cómo lograrlo en Angular usando el estado de los componentes, la propiedad CSS transform y clases dinámicas, sin depender de librerías externas.
¿Cómo se estructura el side menu en HTML?
El punto de partida es ubicar el side menu dentro del componente de navegación, justo donde ya existe la sección destinada al menú mobile. La estructura HTML es sencilla: un contenedor con la clase side-menu, un botón de cierre y los mismos enlaces de navegación que ya existen en el navbar [0:20].
html
<div class="side-menu"> <button>Close</button> <a href="#">Link 1</a> <a href="#">Link 2</a> </div>Para que este elemento ocupe toda la pantalla se utiliza position fixed combinado con top: 0, left: 0, bottom: 0 y right: 0. Con background: white, display: flex y flex-direction: column se consigue que el contenido se apile verticalmente [0:42]. Además, justify-content: flex-start asegura que los enlaces queden en la parte superior del panel.
¿Qué papel juega CSS transform en la animación?
La clave para ocultar y mostrar el menú es la propiedad transform con translateX. Cuando el valor es -100%, el panel queda completamente fuera de la pantalla hacia la izquierda. Cuando es 0, ocupa toda la vista [1:20].
css .side-menu { position: fixed; top: 0; left: 0; bottom: 0; right: 0; background: white; display: flex; flex-direction: column; justify-content: flex-start; transform: translateX(-100%); transition: all 0.5s; }
.side-menu.active { transform: translateX(0); }
La propiedad transition: all 0.5s genera la animación suave de medio segundo cada vez que cambia el transform.
¿Cómo controlar la visibilidad con el estado del componente?
Dentro del componente de Angular se declara una variable de estado llamada showMenu (o activeMenu) inicializada en false [2:10]. Un método toggleMenu invierte ese valor con una sintaxis directa:
typescript showMenu = false;
toggleMenu() { this.showMenu = !this.showMenu; }
toggleMenu con el evento (click) para abrir el menú.toggleMenu para cerrarlo.¿Cómo se aplican clases dinámicas en Angular?
Mediante la sintaxis de class binding se conecta el estado con la clase CSS active [2:50]:
html
<div class="side-menu" [class.active]="showMenu">Cuando showMenu es true, Angular añade la clase active y el transform pasa a 0, mostrando el panel. Cuando es false, la clase se remueve y el menú vuelve a -100% con la transición animada. Esta técnica se explica con mayor detalle en el curso de fundamentos de Angular.
¿Por qué aplicar un reset CSS y una fuente personalizada?
Cuando no se usa un framework como Bootstrap, Foundation o Angular Material, los navegadores aplican estilos predeterminados que generan márgenes y tamaños inconsistentes. Un reset CSS elimina esos valores por defecto en elementos como h1, h2, body y html [3:40].
El archivo se organiza dentro de una carpeta styles con el nombre reset.css (o su equivalente en SASS) y se importa desde los estilos globales:
scss @import 'styles/reset';
Para la tipografía, se importa una fuente desde Google Fonts y se aplica a todos los elementos del sitio [4:10]. Esto reemplaza la fuente Times New Roman que viene por defecto y mejora la apariencia general del proyecto.
css
Con estos ajustes el header queda completo: un menú lateral funcional con animación, estilos reseteados y tipografía personalizada. En el siguiente paso se profundiza en la comunicación entre componentes padre e hijo para implementar el carrito de compras. ¿Ya tienes pensado qué animaciones adicionales podrías agregar a tu side menu?
Dejo el enlace donde pueden copiar el reset https://meyerweb.com/eric/tools/css/reset/
html, body, div, span, applet, object, iframe, h1, h2, h3, h4, h5, h6, p, blockquote, pre, a, abbr, acronym, address, big, cite, code, del, dfn, em, img, ins, kbd, q, s, samp, small, strike, strong, sub, sup, tt, var, b, u, i, center, dl, dt, dd, ol, ul, li, fieldset, form, label, legend, table, caption, tbody, tfoot, thead, tr, th, td, article, aside, canvas, details, embed, figure, figcaption, footer, header, hgroup, menu, nav, output, ruby, section, summary, time, mark, audio, video { margin: 0; padding: 0; border: 0; font-size: 100%; font: inherit; vertical-align: baseline; } /* HTML5 display-role reset for older browsers */ article, aside, details, figcaption, figure, footer, header, hgroup, menu, nav, section { display: block; } body { line-height: 1; } ol, ul { list-style: none; } blockquote, q { quotes: none; } blockquote:before, blockquote:after, q:before, q:after { content: ''; content: none; } table { border-collapse: collapse; border-spacing: 0; }
Lolll, en la primera parte donde agregas todas las etiquetas, puedes agregar
*{ margin: 0; padding: 0; border: 0; // y lo demás }
ese asterisco engloba todas las etiquetas
Ahorra Seguros
Deberían sacar un curso de puro angular material
Juan José Gómez Aguirre
Muy de acuerdo contigo!
Alejandro Mejia Escobar
Michelle Elizabeth Pérez Sosa
Creo que es scss no css.
Chema Muñoz
Muchas gracias! Sólo creo que falta 1 línea encima de flex-direction: "display: flex;"
Daniel Alejandro Calderón Virgen
Si quieren ver la app en su celular, lo pueden hacer de la siguiente manera
A mi se me hace más sencillo ver desde ahí la app
Deymer Hernandez
Me gusta mas la sintaxis con [ngClass]
<div class="side-menu" [ngClass]="{active: activeMenu}"> <button (click)="toggleMenu()">Close</button> <ul> <li><a href="">All</a></li> <li><a href="">Clothes</a></li> <li><a href="">Electronics</a></li> </ul> </div>
Javier Fuentes Ríos
No me gusta que el curso se centre tanto en CSS y no en temas afines a Angular, se divaga mucho.
Rodrigo Abdón Quisbert Fernández
Totalmente de acuerdo, considero que es pérdida de tiempo invertir tiempo en los estilos y la verdad me aburrió este curso ya que lo poco y nada de Angular lo pasa con bastante rapidez, no explicando cada concepto y eso que vengo de Fundamentos de Angular.
luis fernando Bello González
Totalmente de acuerdo, aparte de eso, hay capitulos los cuales nos obligan a hacer el css, uno queriendo solo aprender angular...
Sergio Andrés Bolaños Penagos
Israel Elias Manjarrez Quimiz
seria de colocar también aquí los css? y no importarlos en el styles.scss
Carlos Gabriel Tovar Pena
Tuve que hacerlo así, pues no me funcionaba importar con el url desde la hoja de estilos
Edinson Colonia Paez
En esta ruta está la clase, pueden navegar para obtener ncluso los logos utilizados como carrito, menu, etc. https://github.com/platzi/angular-componentes/tree/8-step
David Castro
Uy, gracias amigo.
Poul Lorca
El código en css quedaría de la siguiente forma. Recuerda no dejar espacios entre ".side-menu" y ".active".
.show-mobile .side-menu { position: fixed; top: 0; left: 0; bottom: 0; right: 0; background: white; display: flex; flex-direction: column; justify-content: flex-start; transform: translateX(-100%); transition: all ease-out 0.5s; } .show-mobile .side-menu.active { transform: translateX(0); }
Arturo Baduna
no me gusta este curso esta feo planteado
Edgardo Molina Gonzalez
Faltaría un curso donde se use netamente Material
alberto ayala rodriguez
amigo, bastante nasty la animación del menú, 10/10 👽
Franklin Carlos Huichi Contreras
Nasty es asqueroso pero dices 10/10 :v
Miguel Angel Reyes Moreno
Jonathan Vergara Ruiz
Luis Alejandro Alvarez Cadavid
Hola como estas, estoy siguiendo el curso, y los links del menu desplegable todavia me salen en la parte inferior, y sigo lo que has hecho y no veo cambios en el css o html, sabes si es normal
Jorge Pinzón
No me quedo muy claro la funciòn del reset de los estilos, si alguien puede explicarme un poco? por favor
Luis Humberto Osorio Quiceno
Saludos. Problemas carga de Opciones en menu He revisado linea a linea y el menu de opciones me sigue apareciendo en la parte inferior. Alguna observacion con respecto al navegdor, versiones de codigo o algo asi?
Gracias.
Nicolas Molina
ProfesorHola, no realmente debería funcionarte sin mayor problema, tal vez si nos comportes tu repositorio podemos ver el código, ¿Te parece?
Jorge Giovanny Paz Mazariegos
¿Qué solución hay de esto? Tengo el mismo problema.
Mariela Cristaldo
bueno pensé que no me andaba el data binding pero no era eso. no se porque no me funciona el sidebar :(
Jimmy Buriticá Londoño
Te recomiendo entrar al GitHub de la clase en el siguiente link y revises los archivos del Componente nav.
Israel Elias Manjarrez Quimiz
y que hay de la linea css
box-sizing: border box;
al momento de hablar sobre resetear o inicializar los estilos
Comparto el css de la clase:
.side-menu{ position: fixed; top: 0; left: 0; bottom: 0; right: 0; background-color: white; flex-direction: column; justify-content: flex-start; transform: translateX(-100%); transition: all ease-out .5s; &.active { transform: translateX(0); } }
En lugar de import es recomendable poner las fuentes en el head del HTML, así
<head> <meta charset="utf-8"> <title>YardSaleStore</title> <base href="/"> <meta name="viewport" content="width=device-width, initial-scale=1"> <link rel="icon" type="image/x-icon" href="favicon.ico"> <link rel="preconnect" href="https://fonts.googleapis.com"> <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin> <link href="https://fonts.googleapis.com/css2?family=Quicksand:wght@400;500;700&display=swap" rel="stylesheet"> </head>
Esto con el fin de reducir el tiempo de carga, que está comprobado que se disminuye notoriamente al tratarse de recursos externos, con esta opción, en Google Fonts les aparece para copiarse ese código, y luego solo ponen en el css body { font-family: su fuente, fuente comun; }
Implementando el sideMenu
Hacemos un menu que se muestra y oculta de la siguiente forma:
nav.component.ts:
import { Component } from '@angular/core'; @Component({ selector: 'app-nav', templateUrl: './nav.component.html', styleUrls: ['./nav.component.scss'] }) export class NavComponent { activeMenu: boolean = false; toggleMenu() { this.activeMenu = !this.activeMenu; } }
nav.component.html:
<div class="show-mobile"> <div> <button (click)="toggleMenu()"> <!---- se pone en true -----> <img src="./assets/svg/icon_menu.svg" alt="menu"> </button> <a href=""> <img src="./assets/svg/logo_yard_sale.svg" alt="logo"> </a> <a href=""> <img src="./assets/svg/icon_shopping_cart.svg" alt="logo"> </a> </div> <div class="side-menu" [class.active]="activeMenu"> <!---- se muestra el menu -----> <button (click)="toggleMenu()">Close</button> <!---- se pone en false ----> <ul> <li><a href="">All</a></li> <li><a href="">Clothes</a></li> <li><a href="">Electronics</a></li> </ul> </div> </div>
nav.component.scss:
.side-menu { position: fixed; top: 0; left: 0; bottom: 0; right: 0; background: white; display: flex; flex-direction: column; justify-content: flex-start; transform: translateX(-100%); transition: all ease-out .5s; &.active { transform: translateX(0); } }
Les comparto mi codigo trate de modularizarlo creando un nuevo componente especificamente para el slide-menu y le pase usando @Input() la funcion y el estado para poder abrir y cerrar el menu desde el padre.
app-slide-menu.ts
import { Component, Input } from '@angular/core'; @Component({ selector: 'app-slide-menu', templateUrl: './slide-menu.component.html', styleUrls: ['./slide-menu.component.scss'] }) export class SlideMenuComponent { @Input() showMenu: boolean = false; @Input() handleClose: (() => void) | undefined; }
app-slide-menu.html
<div class="SlideMenu__container" [class.active]="showMenu"> <button (click)="handleClose && handleClose()">close</button> <ul> <li><a href="">All</a></li> <li><a href="">Clothes</a></li> <li><a href="">Electronics</a></li> </ul> </div>
NOtA💡: el el @import() handleClose le estoy pasando la funcion de toggle para abrir y cerrar esta tipado como void por que esta funcion no retorna nada y el undefined es por que a la variable no le asigne nada como tal. Asi que para implementar esto en el html tuve que hacer la condicion de que si existia ejecuta la funcion para que no me diera error => handleClose && handleClose().
app-nav.html
<div class="show-mobile"> <div> <button (click)="handleOpenMenu()"> <img src="./assets/svg/icon_menu.svg" alt="menu"> </button> <a href=""> <img src="./assets/svg/logo_yard_sale.svg" alt="logo"> </a> <a href=""> <img src="./assets/svg/icon_shopping_cart.svg" alt="logo"> </a> </div> <app-slide-menu [handleClose]="handleOpenMenu" [showMenu]="showMenu"></app-slide-menu> </div> <div class="hide-mobile"> <div> <nav> <a class="logo" href=""> <img src="./assets/svg/logo_yard_sale.svg" alt="logo"> </a> <ul> <li><a href="">All</a></li> <li><a href="">Clothes</a></li> <li><a href="">Electronics</a></li> </ul> </nav> <div class="info"> <div class="account">jonathan@jonny.com</div> <div> <a href=""> <img src="./assets/svg/icon_shopping_cart.svg" alt="logo"> </a> </div> </div> </div> </div>
app-nav.ts
import { Component } from '@angular/core'; @Component({ selector: 'app-nav', templateUrl: './nav.component.html', styleUrls: ['./nav.component.scss'] }) export class NavComponent { showMenu: boolean = false handleOpenMenu (){ this.showMenu = !this.showMenu } }