En este artículo vamos a explicar cómo crear un menú horizontal o vertical multinivel con CSS utilizando una lista HTML no ordenada. En el artículo anterior expliqué cómo hacer un menú CSS de 3 niveles utilizando sólo las etiquetas <ul>, <li>, <a> y un identificador CSS. Ahora vamos a profundizar más sobre la creación de menús y añadiremos algunas clases para crear un menú horizontal o vertical multinivel con CSS.
Menú vertical multinivel
Menú horizontal multinivel
Esta vez vamos a utilizar clases CSS para crear diferentes menús en cualquier parte de nuestra web, y no sólo en un lugar como ocurre si lo vinculamos a un identificador ID. La lógica de nuestro menú horizontal o vertical multinivel con CSS es la siguiente.
Menú CSS horizontal o vertical multinivel
Como todo menú, empezaremos con un contenedor general, en este caso etiqueta <nav>, dentro de la cual crearemos una lista de elementos <ul>, <li>, <a> que se podrán anidar en otras listas, y así sucesivamente, creando varios niveles.
A la etiqueta <nav> le aplicaremos un estilo general que afectará a todos sus elementos, al primer elemento <ul> le aplicaremos el tipo de menú que queremos, horizontal o vertical, que heredaran el resto de elementos <li> y, finalmente, añadiremos una clase submenú cada vez que queremos hacer un nuevo menú anidado, que heredará todas las propiedades superiores.
Esta teoría es fácil de entender, sin embargo cuando nos encontramos frente a las reglas CSS y sus distintos posicionamientos empiezan las dificultades.
Código HTML del menú
El código HTML que vamos a utilizar de ejemplo es similar al arctículo anterior, pero esta vez lo he vuelto a copiar dentro de sí mismo para crear hasta 7 niveles de menú.
<nav class="csMenu">
<ul class="mVerti">
<li><a href="#">Inicio</a></li>
<li><a href="#">Servicios</a></li>
<li><a href="#">Buscador</a></li>
<li><a href="#"">F.A.Q.</a></li>
<li><a href=" #">Utilidades ▼</a>
<ul class="subMenu">
<li><a href="#">Noticias</a></li>
<li><a href="#">Favoritos ►</a>
<ul class="subMenu">
<li><a href="#">Favorito 1</a></li>
<li><a href="#">Favorito 2</a>
<ul class="subMenu">
<li><a href="#">Inicio</a></li>
<li><a href="#">Servicios</a></li>
<li><a href="#">Buscador</a></li>
<li><a href="#"">F.A.Q.</a></li>
<li><a href=" #">Utilidades ▼</a>
<ul class="subMenu">
<li><a href="#">Noticias</a></li>
<li><a href="#">Favoritos ►</a>
<ul class="subMenu">
<li><a href="#">Favorito 1</a></li>
<li><a href="#">Favorito 2</a>
<ul class="subMenu">
<li><a href="#">Favorito 3</a></li>
<li><a href="#">Favorito 4</a></li>
</ul>
</li>
</ul>
</li>
<li><a href="#">Promotores</a></li>
<li><a href="#">Geolocalizador</a></li>
</ul>
</li>
<li><a href="#">Registro</a></li>
<li><a href="#">Entrar</a></li>
</ul>
</li>
</ul>
</li>
<li><a href="#">Promotores</a></li>
<li><a href="#">Geolocalizador</a></li>
</ul>
</li>
<li><a href="#">Registro</a></li>
<li><a href="#">Entrar</a></li>
</ul>
</nav>
Como puedes ver la estructura <ul>, <li>, <a> es muy sencilla. Cuando queremos añadir un submenú anidamos una lista <ul>, dentro del elemento <li> superior.
En cuanto al CSS sólo utilizamos tres reglas:
- csMenu: Para definir las características generales del contenedor <nav>
- mVerti o mHoriz: Para definir en el primer elemento <ul> si queremos que el menú sea horizontal o vertical
- subMenu: Los siguientes elementos <ul> anidados serán submenús
La verdad que es vistoso y ciertamente impresionante, porque mientras estaba haciendo mis pruebas he llegado a 11 niveles de menú que incluso se salían de la pantalla.
Aquí quiero advertir de una cosa: Si configuras el menú en vertical y se sale de la pantalla por abajo, se activarán las barras de scroll. En cambio, si lo configuras en horizontal, no se activa el scroll y el menú se vuelve vertical y se queda pegado al lado derecho del monitor. Podría haber seguido investigando y mirar de activar también el scroll horizontal pero, sinceramente, si necesitas un menú tan grande es que algo estás haciendo mal en tu web, no crees ? 😉
Reglas CSS generales del menú
Volvamos al asunto y empecemos por definir las reglas generales que van a afectar a TODO nuestro menú desde la etiqueta <nav>. El código es el siguiente:
/* Clase para el contenedor del menú <nav> */
.csMenu {
margin: 0;
padding: 0;
display: inline-block;
font-size: 16px;
overflow: hidden;
background-color: black;
font-family: Arial, Helvetica, sans-serif;
}
/* Contenedores <ul> */
.csMenu ul {
margin: 0;
padding: 0;
display: block;
list-style: none;
}
/* Enlaces */
.csMenu a {
color: white;
display: block;
padding: 0.6em 0.8em;
text-decoration: none;
}
/* Enlaces hover */
.csMenu a:hover {
background-color: green;
}
Las funciones de estas reglas CSS afectan a TODO nuestro menú de la siguiente forma:
- .csMenu: Al contenedor <nav> le quitamos márgenes y relleno, lo mostramos como un bloque con fondo negro, overflow para mostrar los elementos flotados internos y tuneamos el texto (opcional)
- csMenu ul: Esto afectará a TODOS los elementos <ul>, estén en el nivel que estén, y simplemente eliminamos los estilos por defecto de las listas y los mostramos como un bloque
- csMenu a: Esto afectará a TODOS los elementos <a>, de cualquier nivel, simplemente le ponemos color blanco (sobre negro), un poco de relleno y los mostramos como un bloque
- csMenu a:hover: El efecto hover de TODOS los elementos <a> será cambiar el fondo a verde
Sí, lo sé, soy un poco pesadito con el TODO, pero es que es importante tener presente la herencia cuando trabajamos con hojas de estilos CSS …
Menú horizontal o vertical con CSS
Hasta aquí los elementos comunes que heredará TODO 🙂 el menú, ahora vamos a ver cómo posicionar los elementos en horizontal o vertical, y esto lo conseguimos posicionando los elementos <li>, el código que define nuestro menú horizontal o vertical multinivel con CSS es el siguiente:
/* Distribución horizontal */
.mHoriz li {
float: left;
display: block;
}
/* Distribución vertical */
.mVerti li {
width: 10em;
display: block;
text-align: left;
}
Supongo que un poco sorprendidos verdad ? Tan poco código para un menú multinivel infinito tanto en horizontal como en vertical ???
Pozi !!
Vamos a explicarlo que tiene algún truquillo jeje
- .mHoriz li: La clase .mHoriz la aplicaremos al primer elemento <ul> de nuestro menú para indicar que queremos un posicionamiento de los elementos <li> en horizontal. Esto lo conseguimos simplemente flotándolos a la izquierda y mostrándolos como bloques. No hay más que definir aquí puesto que el menú se irá colocando un texto al lado del otro y este comportamiento ya nos está bién
- .mVerti li: La clase .mVerti la aplicaremos al primer elementos <ul> cuando queramos que los elementos <li> de nuestro menú tengan posicionamiento vertical. El texto lo alineamos a la izquierda y aquí es conveniente dar un ancho al menú para que quede todo homogéneo. De lo contrario puede haber diferentes tamaños en los submenús dependiendo del ancho del texto que contienen. Esto a parte de quedar feo 🙁 nos puede dar problemas al posicionar el resto de submenús uno al lado del otro, en cambio con un tamaño conocido podremos posicionarlos siempre a la misma distancia
El menú CSS multinivel
Llegamos a la parte más interesante e infinita: los submenús !!
/* Submenú infinito */
.subMenu {
position: fixed;
display: none !important;
background-color: green;
box-shadow: 0 0.5em 1em rgba(0, 0, 0, 0.55);
}
/* Submenú infinito hover */
li:hover > .subMenu {
display: block !important;
}
/* Submenú infinito enlaces hover */
.subMenu a:hover {
background-color: black;
}
/* Submenú infinito posicionamiento vertical */
.mVerti .subMenu {
left: 8em;
position: absolute !important;
}
Esta es la parte más importante y la que más tiempo me ha llevado investigar hasta descubrir porqué me daba el siguiente error: A partir del 3 .subMenu (4 nivel de anidamiento) el comportamiento del menú horizontal pasaba a ser vertical 😮 Increíble !! pero al final dí con la siguiente solución:
- .subMenu: Esta clase la asignamos a todos los elementos <ul> que forman un submenú. Esto quiere decir que heredan las propiedades <ul>, <li>, <a> superiores pero, al mismo tiempo, deben comportarse como un submenú. En primer lugar establecemos su posicionamiento en fixed, no me preguntéis porqué, pero con esto funciona el anidamiento horizontal infinito 😉 Como se trata de un submenú, primero debe aparecer «invisible» y, como hereda «visibilidad» de sus reglas superiores, lo marcamos como
display: none !important
. El resto simplemente es asignarle un fondo verde acorde a cuando sea seleccionado y un sombreado chulo - li:hover > .subMenu: El submenú se hará visible cuando su elemento inmediatamente superior <li> sea seleccionado con hover. Una vez más al heredar atributos superiores debemos forzar su visualización con
display: block !important
. - .subMenu a:hover: Ahora debemos cambiar el efecto hover de los enlaces <a>, puesto que ya no es sobre fondo negro, sinó verde, los mostraremos con un fondo negro para mantener el contraste
- .mVerti .subMenu: En los submenús verticales debemos hacer un último ajuste y colocar esta regla al final de todo, de este modo se garantiza su ejecución sobre las anteriores. Debemos devolver el posicionamiento absoluto de forma forzada con !important y, si el ancho de los submenús los hemos hecho de 10em, los mostramos desplazados 8em a la derecha, dejando un margen siempre igual entre submenús
Menú horizontal o vertical multinivel con CSS
Para los que quieren copiar y listos aquí pongo todo el código entero 😉
<!DOCTYPE>
<html>
<head>
<style>
/* Clase para el contenedor del menú <nav> */
.csMenu {
margin: 0;
padding: 0;
display: inline-block;
font-size: 16px;
overflow: hidden;
background-color: black;
font-family: Arial, Helvetica, sans-serif;
}
/* Contenedores <ul> */
.csMenu ul {
margin: 0;
padding: 0;
display: block;
list-style: none;
}
/* Enlaces */
.csMenu a {
color: white;
display: block;
padding: 0.6em 0.8em;
text-decoration: none;
}
/* Enlaces hover */
.csMenu a:hover {
background-color: green;
}
/* Distribución horizontal */
.mHoriz li {
float: left;
display: block;
}
/* Distribución vertical */
.mVerti li {
width: 10em;
display: block;
text-align: left;
}
/* Submenú infinito */
.subMenu {
position: fixed;
display: none !important;
background-color: green;
box-shadow: 0 0.5em 1em rgba(0, 0, 0, 0.55);
}
/* Submenú infinito hover */
li:hover > .subMenu {
display: block !important;
}
/* Submenú infinito enlaces hover */
.subMenu a:hover {
background-color: black;
}
/* Submenú infinito posicionamiento vertical */
.mVerti .subMenu {
left: 8em;
position: absolute !important;
}
</style>
</head>
<body>
<h1>Menú horizontal/vertical multinivel</h1>
<p>Ejemplo de menú horizontal/vertical multinivel</p>
<nav class="csMenu">
<ul class="mVerti">
<li><a href="#">Inicio</a></li>
<li><a href="#">Servicios</a></li>
<li><a href="#">Buscador</a></li>
<li><a href="#"">F.A.Q.</a></li>
<li><a href=" #">Utilidades ▼</a>
<ul class="subMenu">
<li><a href="#">Noticias</a></li>
<li><a href="#">Favoritos ►</a>
<ul class="subMenu">
<li><a href="#">Favorito 1</a></li>
<li><a href="#">Favorito 2</a>
<ul class="subMenu">
<li><a href="#">Inicio</a></li>
<li><a href="#">Servicios</a></li>
<li><a href="#">Buscador</a></li>
<li><a href="#"">F.A.Q.</a></li>
<li><a href=" #">Utilidades ▼</a>
<ul class="subMenu">
<li><a href="#">Noticias</a></li>
<li><a href="#">Favoritos ►</a>
<ul class="subMenu">
<li><a href="#">Favorito 1</a></li>
<li><a href="#">Favorito 2</a>
<ul class="subMenu">
<li><a href="#">Favorito 3</a></li>
<li><a href="#">Favorito 4</a></li>
</ul>
</li>
</ul>
</li>
<li><a href="#">Promotores</a></li>
<li><a href="#">Geolocalizador</a></li>
</ul>
</li>
<li><a href="#">Registro</a></li>
<li><a href="#">Entrar</a></li>
</ul>
</li>
</ul>
</li>
<li><a href="#">Promotores</a></li>
<li><a href="#">Geolocalizador</a></li>
</ul>
</li>
<li><a href="#">Registro</a></li>
<li><a href="#">Entrar</a></li>
</ul>
</nav>
</body>
</html>
Y creo que ya está todo, aunque seguro que alguno pregunta … Y se puede mezclar un submenú horizontal con otro en vertical ? Pues no 🙁
Pero seguramente se pueda hacer modificando algunas reglas CSS, así que ya sabes, dale al coco y si lo haces me lo pasas, que yo ya no investigo más, mis menús se quedan así 🙂
Lo último que falta es hacerlo responsive y que se convierta en un menú ☰ tipo hamburguesa para dispositivos móviles. Lo encontrarás en el siguiente artículo: Menú responsive tipo hamburguesa.
¡ Espero que este artículo sea de vuestro interés !