Un navbar responsive es una barra de navegación que se adapta correctamente a diferentes tamaños de pantalla.
En pantallas grandes, los enlaces pueden mostrarse de forma horizontal. En dispositivos móviles, los enlaces pueden ocultarse y mostrarse mediante un botón de tipo hamburguesa.
En esta guía veremos cómo crear un navbar moderno, adaptable y con animaciones usando HTML, CSS y un poco de JavaScript.
Qué vamos a crear
El objetivo es construir una barra de navegación que funcione de la siguiente manera:
- En pantallas grandes muestra el logo y los enlaces del menú.
- En pantallas pequeñas oculta los enlaces.
- Muestra un botón de menú hamburguesa en móviles.
- Al hacer clic en el botón, el menú se despliega con animación.
- El icono cambia de hamburguesa a una X.
- Los enlaces aparecen uno por uno con efecto escalonado.
- Al hacer clic en un enlace, el menú se cierra automáticamente.
Archivos necesarios
Para este proyecto podemos trabajar con tres archivos:
index.htmlestilo.cssscript.js
El archivo HTML tendrá la estructura del navbar, el CSS se encargará del diseño y las animaciones, y JavaScript agregará la funcionalidad del menú desplegable.
Estructura HTML del navbar
Lo primero será crear la estructura básica dentro del archivo index.html.
Usaremos la etiqueta header para representar la cabecera principal de la página. Dentro colocaremos una etiqueta nav, que representa la barra de navegación.
<header>
<nav>
<div class="nav_container">
<a href="#" class="logo">Mi Sitio</a>
<button class="menu_btn" id="menu_btn" aria-expanded="false">☰</button>
<ul class="nav_links" id="nav_links">
<li><a href="#inicio">Inicio</a></li>
<li><a href="#servicios">Servicios</a></li>
<li><a href="#portafolio">Portafolio</a></li>
<li><a href="#contacto">Contacto</a></li>
</ul>
</div>
</nav>
</header>
En esta estructura tenemos un logo, un botón para móviles y una lista de enlaces.
Por qué usar header y nav
La etiqueta header ayuda a definir la cabecera de la página.
La etiqueta nav indica que dentro de ese bloque se encuentra la navegación principal del sitio.
Usar etiquetas semánticas mejora la organización del código y ayuda a que la estructura sea más clara.
Logo del sitio
El logo se crea con una etiqueta a.
<a href="#" class="logo">Mi Sitio</a>
En este caso usamos href="#" porque el enlace no apunta a una página específica. También agregamos la clase logo para darle estilo con CSS.
Botón de menú hamburguesa
El botón del menú será visible en pantallas pequeñas.
<button class="menu_btn" id="menu_btn" aria-expanded="false">☰</button>
La clase menu_btn servirá para aplicar estilos y el ID menu_btn permitirá seleccionar el botón desde JavaScript.
El atributo aria-expanded ayuda a mejorar la accesibilidad, indicando si el menú está abierto o cerrado.
Lista de enlaces
Los enlaces del menú se colocan dentro de una lista ul.
<ul class="nav_links" id="nav_links">
<li><a href="#inicio">Inicio</a></li>
<li><a href="#servicios">Servicios</a></li>
<li><a href="#portafolio">Portafolio</a></li>
<li><a href="#contacto">Contacto</a></li>
</ul>
Cada enlace apunta a una sección del sitio usando un identificador con numeral.
CSS base del proyecto
Ahora pasamos al archivo estilo.css.
Primero aplicamos un reseteo básico para eliminar márgenes y rellenos por defecto.
* {
margin: 0;
padding: 0;
box-sizing: border-box;
font-family: Arial, Helvetica, sans-serif;
}
Esto ayuda a que el diseño se vea más consistente en diferentes navegadores.
Estilos del nav
Ahora damos estilo a la etiqueta nav.
nav {
background-color: #000;
padding: 1rem 2rem;
box-shadow: 0 2px 10px rgba(0, 0, 0, .3);
}
Con esto agregamos un fondo oscuro, espacio interno y una sombra ligera.
Contenedor del navbar
El contenedor principal se organiza con Flexbox.
.nav_container {
max-width: 1000px;
margin: 0 auto;
display: flex;
align-items: center;
justify-content: space-between;
}
Con justify-content: space-between colocamos el logo a un lado y los enlaces al otro.
Estilos del logo
El logo tendrá texto blanco, negrita y un tamaño mayor.
.logo {
color: #fff;
font-weight: bold;
font-size: 1.5rem;
text-decoration: none;
}
Estilos de los enlaces
La lista de enlaces se muestra en horizontal usando Flexbox.
.nav_links {
display: flex;
gap: 2rem;
list-style: none;
transition: all .3s ease;
}
.nav_links a {
color: #fff;
text-decoration: none;
font-weight: 500;
transition: all .3s ease;
}
Con gap agregamos separación entre los enlaces y con list-style: none quitamos los puntos de la lista.
Efecto hover en los enlaces
Podemos agregar un pequeño efecto al pasar el mouse sobre los enlaces.
.nav_links a:hover {
opacity: .75;
transform: translateY(-2px);
}
Este efecto hace que el enlace se vea un poco más transparente y se eleve ligeramente.
Estilos del botón de menú
El botón del menú será visible solo en pantallas pequeñas. Primero le damos estilo general.
.menu_btn {
display: none;
background: none;
border: none;
color: #fff;
font-size: 2rem;
cursor: pointer;
}
Usamos display: none para ocultarlo en pantallas grandes.
Crear el diseño responsive
Para adaptar el navbar a pantallas pequeñas usamos una media query.
En este caso, aplicaremos cambios cuando el ancho de la pantalla sea menor o igual a 768px.
@media (max-width: 768px) {
.menu_btn {
display: block;
}
}
Cuando la pantalla sea pequeña, el botón de menú se mostrará.
Menú desplegable en móviles
Dentro de la misma media query, modificamos la lista de enlaces.
@media (max-width: 768px) {
.menu_btn {
display: block;
}
.nav_links {
position: fixed;
top: 70px;
left: 0;
width: 100%;
background-color: #000;
flex-direction: column;
align-items: center;
padding: 2rem 0;
clip-path: circle(0% at 100% 0);
pointer-events: none;
}
.nav_links.active {
clip-path: circle(150% at 100% 0);
pointer-events: auto;
}
}
Con position: fixed colocamos el menú debajo del navbar. Con clip-path creamos un efecto de apertura circular.
Cuando el menú tiene la clase active, el círculo se expande y el menú queda visible.
Animación de los elementos del menú
Para que los enlaces aparezcan con una animación suave, primero los ocultamos.
@media (max-width: 768px) {
.nav_links li {
opacity: 0;
transform: translateY(20px);
transition: all .3s ease;
}
.nav_links.active li {
opacity: 1;
transform: translateY(0);
}
}
Cuando el menú está activo, los elementos vuelven a su posición original y se muestran.
Efecto escalonado con transition-delay
Para que los enlaces aparezcan uno detrás de otro, agregamos retrasos individuales.
@media (max-width: 768px) {
.nav_links.active li:nth-child(1) {
transition-delay: .1s;
}
.nav_links.active li:nth-child(2) {
transition-delay: .2s;
}
.nav_links.active li:nth-child(3) {
transition-delay: .3s;
}
.nav_links.active li:nth-child(4) {
transition-delay: .4s;
}
}
Así cada enlace inicia su animación con una pequeña diferencia de tiempo.
CSS completo del navbar
* {
margin: 0;
padding: 0;
box-sizing: border-box;
font-family: Arial, Helvetica, sans-serif;
}
nav {
background-color: #000;
padding: 1rem 2rem;
box-shadow: 0 2px 10px rgba(0, 0, 0, .3);
}
.nav_container {
max-width: 1000px;
margin: 0 auto;
display: flex;
align-items: center;
justify-content: space-between;
}
.logo {
color: #fff;
font-weight: bold;
font-size: 1.5rem;
text-decoration: none;
}
.nav_links {
display: flex;
gap: 2rem;
list-style: none;
transition: all .3s ease;
}
.nav_links a {
color: #fff;
text-decoration: none;
font-weight: 500;
transition: all .3s ease;
}
.nav_links a:hover {
opacity: .75;
transform: translateY(-2px);
}
.menu_btn {
display: none;
background: none;
border: none;
color: #fff;
font-size: 2rem;
cursor: pointer;
}
@media (max-width: 768px) {
.menu_btn {
display: block;
}
.nav_links {
position: fixed;
top: 70px;
left: 0;
width: 100%;
background-color: #000;
flex-direction: column;
align-items: center;
padding: 2rem 0;
clip-path: circle(0% at 100% 0);
pointer-events: none;
}
.nav_links.active {
clip-path: circle(150% at 100% 0);
pointer-events: auto;
}
.nav_links li {
opacity: 0;
transform: translateY(20px);
transition: all .3s ease;
}
.nav_links.active li {
opacity: 1;
transform: translateY(0);
}
.nav_links.active li:nth-child(1) {
transition-delay: .1s;
}
.nav_links.active li:nth-child(2) {
transition-delay: .2s;
}
.nav_links.active li:nth-child(3) {
transition-delay: .3s;
}
.nav_links.active li:nth-child(4) {
transition-delay: .4s;
}
}
Agregar funcionalidad con JavaScript
Ahora falta hacer que el botón abra y cierre el menú.
Para eso usamos JavaScript y seleccionamos los elementos que vamos a manipular.
const menuBtn = document.getElementById("menu_btn");
const navLinks = document.getElementById("nav_links");
Con estas constantes tenemos acceso al botón y a la lista de enlaces.
Abrir y cerrar el menú
Agregamos un evento click al botón.
menuBtn.addEventListener("click", () => {
navLinks.classList.toggle("active");
});
Cada vez que el usuario haga clic, se alternará la clase active. Si la clase existe, el menú se muestra. Si no existe, se oculta.
Cambiar el icono del botón
También podemos cambiar el icono de hamburguesa a una X cuando el menú esté abierto.
menuBtn.addEventListener("click", () => {
navLinks.classList.toggle("active");
if (navLinks.classList.contains("active")) {
menuBtn.textContent = "✕";
menuBtn.setAttribute("aria-expanded", "true");
} else {
menuBtn.textContent = "☰";
menuBtn.setAttribute("aria-expanded", "false");
}
});
Además de cambiar el icono, actualizamos el atributo aria-expanded para mejorar la accesibilidad.
Cerrar el menú al hacer clic en un enlace
En móviles, es útil que el menú se cierre automáticamente cuando el usuario selecciona una opción.
Primero seleccionamos todos los enlaces dentro del menú.
const links = document.querySelectorAll("#nav_links a");
Luego recorremos cada enlace con forEach y agregamos un evento click.
links.forEach((link) => {
link.addEventListener("click", () => {
navLinks.classList.remove("active");
menuBtn.textContent = "☰";
menuBtn.setAttribute("aria-expanded", "false");
});
});
Así, cuando el usuario toca un enlace, el menú se oculta y el botón vuelve al icono de hamburguesa.
JavaScript completo
const menuBtn = document.getElementById("menu_btn");
const navLinks = document.getElementById("nav_links");
const links = document.querySelectorAll("#nav_links a");
menuBtn.addEventListener("click", () => {
navLinks.classList.toggle("active");
if (navLinks.classList.contains("active")) {
menuBtn.textContent = "✕";
menuBtn.setAttribute("aria-expanded", "true");
} else {
menuBtn.textContent = "☰";
menuBtn.setAttribute("aria-expanded", "false");
}
});
links.forEach((link) => {
link.addEventListener("click", () => {
navLinks.classList.remove("active");
menuBtn.textContent = "☰";
menuBtn.setAttribute("aria-expanded", "false");
});
});
Cómo probar el navbar responsive
Para comprobar que todo funciona, abre el proyecto en el navegador.
En pantalla grande deberías ver el logo a la izquierda y los enlaces a la derecha.
Luego reduce el ancho del navegador. Cuando llegue al tamaño configurado en la media query, los enlaces se ocultarán y aparecerá el botón de hamburguesa.
Al hacer clic en el botón, el menú se desplegará con animación. El icono cambiará a una X y los enlaces aparecerán uno por uno.
Si haces clic en un enlace, el menú se cerrará automáticamente.
Resumen del proceso
- Crear la estructura HTML con
header,nav, logo, botón y enlaces. - Aplicar estilos básicos con CSS.
- Organizar el navbar con Flexbox.
- Ocultar el botón hamburguesa en pantallas grandes.
- Usar una media query para pantallas pequeñas.
- Crear el menú desplegable con
clip-path. - Agregar animación a los enlaces.
- Usar JavaScript para abrir y cerrar el menú.
- Cambiar el icono del botón según el estado.
- Cerrar el menú al hacer clic en un enlace.
Conclusión
Crear un navbar responsive con HTML, CSS y JavaScript es una práctica muy útil para cualquier proyecto web.
Con HTML construimos la estructura, con CSS damos estilo, adaptamos el diseño a móviles y agregamos animaciones. Finalmente, con JavaScript controlamos la apertura, el cierre y el cambio de icono del menú.
Este tipo de menú es ideal para portafolios, páginas personales, sitios de servicios, landing pages y cualquier sitio web que necesite una navegación moderna y adaptable.



