Añadiendo icono a nuestro boton de menu

Retomando las entradas sobre nuestro sencillo menu responsive, en este post le agregaremos un pequeño icono al botón de menu. Para ello emplearemos HTML para crear la estructura de nuestro icono, CSS para darle una vista decente y Javascript para una sencilla animación. Trabajaremos sobre el código que vimos en un post anterior, si no lo has visto aquí esta el link . 

Sí hacemos un poco de memoria, recordaremos que teníamos un span con la clase menu-btn, pues el span lo cambiaremos por un div,  con la misma clase, este div será la caja de nuestro botón. Dentro del div con la clase menu-btn colocaremos otro div, con la clase icon que cumplirá la función de contenedor de nuestro icono y un elemento b que contendrá el texto Menu o Return según sea el caso. Tres elementos div con la clase item irán contenidos dentro de nuestro contenedor del icono. Quedando un código más o menos así...


<div class="menu-btn">
  <div class="icon">
    <div class="item"></div>
    <div class="item"></div>
    <div class="item"></div>
  </div>
  <b>Menu</b>
</div>

De lado de nuestro CSS comenzaremos por agregar el atributo flexbox a nuestro elemento contenedor del botón y al contenedor del icono de menu; Para eso, a la regla display: flex; le añadiremos las clases .menu-btn y .menu-btn .icon con un código como este...


.nav, header ,h1,.menu-btn, .menu-btn .icon{
    display: flex;
}

Nota: cuidado con los selectores en el código anterior. Nota que un selector es para la clase .menu-btn y otro para .menu-btn .icon separados por una coma.

Nuestro botón solo tendrá el borde derecho, ya no tendrá los cuatro bordes como anteriormente para ello únicamente cambiaremos la declaracion border: solid .1rem #fff; por border-right: solid .1rem #fff; de nuestro contenedor del botón quedando nuestra regla así...


.menu-btn{
    border-right: solid .1rem #fff;
    padding: .5rem;
    transition: all .3s ease;
    cursor: pointer;
}

Ya que al contenedor de nuestro icono le hemos agregado la propiedad flexbox resta agregar la propiedad flex-direction:column de flexbox para que sus elementos hijos se desplieguen en disposicion de columna (es decir de manera vertical), distribuimos el espacio entre ellos con la propiedad justify-content: space-around y hacemos que de manera horizontal se desplieguen al inicio de su contenedor con align-items: flex-start; y por último establecemos un ancho y un alto.


.menu-btn .icon{
	flex-direction: column;
	justify-content: space-around;
	align-items: flex-start;
	width: .5rem;
	height: 1.3rem;
	
}

Agregamos estilo a los items de nuestro icono con el siguiente código. Nada extra normal, un color de fondo, ancho y alto, redondeamos los bordes para que sean circulares y agregamos la propiedad de transición que nos servirá para la animación.


.menu-btn .icon .item{
	background-color: #fff;
	width: .3rem;
	height: .3rem;
	border-radius: .15rem;
	transition: all .3s ease-in-out;
}

A continuación agregamos la regla con los estilos para el momento en que nuestro icono tenga la clase return, que agregaremos o quitaremos con Javascript, la clase return únicamente tendrá una transformación de translación en el eje X de -.4rem. Veamos el trozo de código.


.menu-btn .icon .item.return{
	transform: translateX(-.4rem) 
}

Del lado del Javascript haremos una pequeña modificación. Anteriormente seleccionábamos el elemento contenedor del botón mediante la clase .menu-btn para después modificar su texto con Menu o Return según fuera el caso, mediante la propiedad innerHTML con la siguiente línea.


this.innerHTML = (this.innerHTML === 'Menu')? '<-return' : 'Menu'

Pues bien, la selección del contenedor del botón de menu sigue igual, pero ahora en vez de modificar el texto directamente del elemento contenedor, ahora seleccionaremos dentro de nuestro contenedor los elementos de etiqueta b, pero como sabemos que solo tenemos uno, lo seleccionaremos con la posición 0 y a él le modificaremos su texto Menu o Return con la siguiente línea...


this.getElementsByTagName('b')[0].innerHTML = (this.getElementsByTagName('b')[0].innerHTML === 'Menu')? 'Return' : 'Menu'

Ahora no resta más que agregar o quitar la clase return al segundo item de nuestro icono, para que cada vez que se haga click en el botón de menu, el segundo item se desplace a la izquierda si este se encuentra en su posición inicial, simulando una flecha apuntando hacía atrás, de lo contrario, si ya tiene la clase que desplaza el item, entonces quitar la clase return y hacer que el item regrese a su posición inicial. Esto lo hacemos con la siguiente línea...


this.querySelectorAll('.icon .item')[1].classList.toggle('return')

Quedando nuestro código Javascript de la siguiente manera...


<script>
var menu = document.querySelector('.menu-container')
document.querySelector('.menu-btn').addEventListener('click', function(){
  this.getElementsByTagName('b')[0].innerHTML = (this.getElementsByTagName('b')[0].innerHTML === 'Menu')? 'Return' : 'Menu'
  this.querySelectorAll('.icon .item')[1].classList.toggle('return')
  this.classList.toggle('anim-btn')
  menu.classList.toggle('show')
})
</script>

Así hicimos una pequeña animación para nuestro icono de menu. Nada espectacular, pero tampoco tan plano. Sí de algo sirve, el código completo aquí esta.
El HTML...


<!DOCTYPE html>
<html lang="es">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <link href="https://fonts.googleapis.com/css?family=Lato:300,400" rel="stylesheet">
	<link rel="stylesheet" href="style.css" />
    <title>Menu Responsivo</title>
</head>
<body>
    <header>
        <div class="logo">
            <img src="logo.svg" alt="Page Logo">
        </div>
        <div class="menu">
            <div class="menu-btn">
            	<div class="icon">
            		<div class="item"></div>
            		<div class="item"></div>
            		<div class="item"></div>
            	</div>
            	<b>Menu</b>
            </div>
            <div class="menu-container">
                <ul class="nav">
                    <li class="nav-item"><a href="#" class="nav-link">Inicio</a></li>
                    <li class="nav-item"><a href="#" class="nav-link">Acerca de</a></li>
                    <li class="nav-item"><a href="#" class="nav-link">Servicios</a></li>
                    <li class="nav-item"><a href="#" class="nav-link">Contacto</a></li>
                </ul>
            </div>
        </div>
    </header>
    <h1>Menu Responsivo</h1>
</body>
<script>
    var menu = document.querySelector('.menu-container')
    document.querySelector('.menu-btn').addEventListener('click', function(){
        //this.innerHTML = (this.innerHTML === 'Menu')? 'Return' : 'Menu'
				this.getElementsByTagName('b')[0].innerHTML = (this.getElementsByTagName('b')[0].innerHTML === 'Menu')? 'Return' : 'Menu'
				this.querySelectorAll('.icon .item')[1].classList.toggle('return')
        this.classList.toggle('anim-btn')
        menu.classList.toggle('show')
    })
</script>
</html>

El CSS...


*, *:after, *:before{
    padding: 0;
    margin: 0;
}

html,body{
    font-size: 16px;
    font-family: 'lato';
    background-color: #fff;
}

.nav, header ,h1,.menu-btn, .menu-btn .icon{
    display: flex;
}
.menu-btn, .nav-link{
    color: white;
}

header, .menu-container{
    background-color: #ea5106;
}

.menu-btn{
    border-right: solid .1rem #fff;
		border-left: none;
    padding: .5rem;
    transition: all .3s ease;
    cursor: pointer;
}
.menu-btn.anim-btn{
    padding: .4rem;
}
/*Iconos menu*/
.menu-btn .icon{
	flex-direction: column;
	justify-content: space-around;
	align-items: flex-start;
	width: .5rem;
	height: 1.3rem;
	
}
.menu-btn .icon .item{
	background-color: #fff;
	width: .3rem;
	height: .3rem;
	border-radius: .15rem;
	transition: all .3s ease-in-out;
}
.menu-btn .icon .item.return{
	/*width: .9rem;*/
	transform: translateX(-.4rem) 
}
/*--------------------*/
header, h1, .nav{
    align-items: center;
    justify-content: center;
}

header{
    justify-content: space-around;
}

.logo img{
    width: 80px;
}

.nav{
    flex-direction: column;
}

.nav-item{
    list-style: none;
    padding: 1rem;
}

.nav-link{
    text-decoration: none;
    font-size: 1.2rem;
}

.menu-container{
    position: absolute;
    left: -100%;
    width: 10%;
    height: 80vh;
    top: 80px;
    padding-top: 2rem;
    transition: all .7s ease-in-out;
}

.menu-container.show{
    left: 0;
    width: 100%;
}

h1{
    height: 70vh;
}

@media (min-width:768px){
    .menu-btn{
        display: none;
    }
    
    .menu-container{
        position: inherit;
        width: inherit;
        height: inherit;
        padding-top: 0;
    }
    
    .nav{
        flex-direction: row;
    }
    
    .nav-link{
        font-size: 1.2rem;
        font-weight: 400;
    }
}