Crear un menú responsive design con css y Vanilla javascript
En este tutorial vamos a crear una barra de navegación que sea responsive en el que el menú de navegación se oculte cuando estemos en pantallas móviles y tablets y se muestre al pulsar un botón.
Para ello lo primero que haremos será crear la estructura html de nuestra barra de navegación:
<i class="fa fa-bars bars-button" aria-hidden="true" id="bars-button"></i>
<div class="navbar">
<div class="contenido">
<nav class="bars">
<ul>
<li><a href="#">Blog</a></li>
<li><a href="#">Categorías</a></li>
<li><a href="#">Sobre mi</a></li>
<li><a href="#">Contacto</a></li>
</ul>
</nav>
<div class="title">
<a href="#">
<h2>NAVBAR</h2>
</a>
</div>
</div>
</div>
La primera línea es el típico botón en el que se muestran tres líneas, también conocido como burger button y que solo se mostrará cuando la pantalla sea menor de 768 píxeles, yo lo he importado de fontawesome pero lo podéis sacar de otras librerías de iconos.
Luego tenemos el div con la clase navbar que contendrá toda nuestra estructura y dentro de el un div con la clase contenido que será de un tamaño máximo de 1024 píxeles y estará centrado.
Dentro de contenido tenemos dos elementos, nuestro menú de navegación en la que he añadido unos enlaces de ejemplo y un div que contendrá el título, estos dos elementos están separados de tal forma que cada uno ocupe una punta del navegador, ahora lo explicaremos cuando comentemos el css.
Si queréis utilizar los estilos de fontawesome podéis añadirlo dentro del head de vuestro archivo html:
<link href="https://stackpath.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css" rel="stylesheet">
Ahora vamos a ponernos con la parte de css. Quitamos los márgenes por defecto y añadimos una fuente de texto.
html, body {
margin: 0;
padding: 0;
font-family: "Roboto", Arial;
}
Para el contenedor principal damos un tamaño de ancho del 100% y un padding de 5 píxeles general para la separación de nuestros elementos.
.navbar {
width: 100%;
padding: 5px;
background-color: #1a1a27;
box-sizing: border-box;
}
El div que contiene nuestros elementos tendrá una una anchura máxima de 1024 píxeles, eso quiere decir que si el tamaño del navegador es inferior se reducirá el tamaño del div. Utilizamos el display flex para organizar los elementos que contiene y justify-content con el atributo space-between que hará que todo el espacio sobrante esté entre nuestros dos elementos. El margin que añadimos centra el div en el centro del contenedor.
.navbar .contenido {
max-width: 1024px;
display:flex;
justify-content: space-between;
margin: 0 auto;
}
Aquí también le damos un display flex y align-items center para centrarlo verticalmente y utilizamos justify-content con space-between para que el espacio sobrante del div se distribuya entre los distintos elementos exceptuando al principio y al final del contendor.
.bars ul {
display: flex;
align-items: center;
list-style: none;
width: 400px;
justify-content: space-between;
padding: 0;
padding-left: 4px;
}
Quitamos la línea que se añade por defecto a los elementos a y añadimos un transition de un segundo para cuando pongan el cursor encima de los enlaces.
.bars ul li a {
text-decoration: none;
color:#a2a3b7;
transition: 1s;
text-transform: uppercase;
}
.bars ul li a:hover {
text-decoration: none;
color:white;
}
Para el título también usamos un display flex y lo centramos verticalmente con align-items.
div.title {
display: flex;
align-items: center;
padding-right: 4px;
}
div.title a {
text-decoration: none;
color: white;
}
div.title h2{
padding: 0;
margin: 0;
}
Este será nuestro botón, por defecto estará oculto, por eso tiene el display a none, la posición será fixed para que siempre aparezca aunque hagas scroll y le hemos puesto un z-index de 99 para evitar que ningún elemento que esté por debajo de esa cifra se quede por encima.
.bars-button {
width: 40px;
height: 40px;
border-radius: 50%;
background-color: rgba(0, 0, 0, .8);
display: none;
position: fixed;
z-index: 99;
left: 7px;
top: 11px;
color: #a2a3b7;
cursor: pointer;
}
Una vez hecho esto vamos a hacer responsive nuestra barra de navegación, para ello creamos un media query.
@media screen and (max-width: 768px) {}
Y ahora vamos ha añadir las siguientes líneas dentro de él. Lo primero es cambiar la dirección de los elementos del contenido, ya que el menú de navegación va a salir del contenido, cambiamos el justify-content a flex-end, esto hará que todos los elementes empiecen desde la derecha, en este caso solo el título.
.navbar .contenido {
justify-content: flex-end;
}
Ahora queremos que nuestro botón sea visible así que cambiamos su display a flex y utilizamos justify-content y align-items a center para que el icono esté centrado tanto vertical como horizontalmente.
.bars-button {
display: flex;
justify-content: center;
align-items: center;
}
Para el elemento que contiene las urls lo posicionaremos como fixed para que se muestre en toda la pantalla, lo ocultaremos con left -100vw en el que su valor significa el tamaño del ancho de la pantalla y utilizaremos el elemento display flex y justify-content para centrar nuestras urls. El elemento transition lo que hará es que cuando pulsemos el botón nuestra barra no aparecerá de golge sino como una transición en este caso de 0.3 segundos.
.bars {
position: fixed;
background: rgba(0, 0, 0, .5);
z-index: 98;
top: 0;
left: -100vw;
width: 100vw;
bottom: 0;
display: flex;
justify-content: center;
transition: .3s;
}
Cuando el elemento que contiene la clase bars también contiene la clase is-active cambiará el posicionamiento de left a 0 para que se muestre en pantalla.
.bars.is-active {
left: 0;
}
Cambiamos la dirección de los elementos para que ahora aparezcan por columnas y los centramos en la pantalla tanto vertical como horizontalmente.
.bars ul {
flex-direction: column;
justify-content: center;
align-items: center;
}
.bars ul li {
padding: 5px;
}
.bars ul li a {
color: #000;
font-weight: 700;
text-decoration: underline;
}
div.title h2 {
padding: 10.5px;
}
Ahora solo faltaría darle funcionalidad a nuestro botón y para ello añadimos el siguiente script en nuestra página.
Con windows.matchMedia obtenemos si la pantalla tiene como máximo un tamaño de 768 píxeles y guardamos en constantes los elementos del botón de la barra de navegación y el propio menú.
const limit_size_screen = window.matchMedia('screen and (max-width: 768px)');
const bars = document.querySelector('.bars');
const barsButton = document.querySelector('#bars-button');
Con la función validation lo que haremos será validar si la pantalla tiene como máximo un ancho de 768 píxeles y si es así cuando hagan click en el botón se ejecutará la función hideShow.
function validation(event) {
if (event.matches) {
barsButton.addEventListener('click', hideShow);
} else {
barsButton.removeEventListener('click', hideShow);
}
}
validation(limit_size_screen);
La función hideshow comprueba si el elemento bars contiene la clase is-active, sino la tiene la añade, lo que hará que se muestre el menú de navegación, si vuelven a pulsar eliminará el elemento y el menú se ocultará.
function hideShow() {
if (bars.classList.contains('is-active')) {
bars.classList.remove('is-active');
} else {
bars.classList.add('is-active');
}
}
Si queréis descargar el proyecto lo podéis obtener en mi página de github.
BONUS
Si queréis ver como funcionaría en vuestro teléfono y de paso comprobar que todo funciona bien os podéis descargar el paquete de node static server, una vez instalado ejecutáis el comando static-server en el directorio donde está vuestro proyecto y os creará un servidor de http. Una vez tenéis esto funcionando solo tenéis que comprobar que vuestro dispositivo móvil y pc están en la misma red, luego obtenéis la dirección ip local de vuestro pc y la ponéis en el navegador de vuestro dispositivo móvil con el puerto que aparece en la consola con el comando static-server y listo, ya podéis acceder a vuestro proyecto desde ahí :)
Espero que este post te ayude y como siempre, te recomiendo seguirme en Twitter para estar al tanto de los nuevo contenido. Ahora también puedes seguirme en Instagram donde estoy subiendo tips, tutoriales en vídeo e información sobre herramientas para developers.
Por último os dejo mi guía para aprender a trabajar con APIs donde explico todo el funcionamiento de una API, el protocolo HTTP y veremos como construir una API con arquitectura REST.
Nos leemos 👋.