Menú vertical en acordeón con CSS y jquery

menu_acordeonA pesar del buen feedback recibido sobre mi serie de tutoriales de CodeIgniter, los artículos sobre menús animados con CSS y javascript siguen siendo los más populares en este sitio, y parece que son bastante útiles para la gente que está empezando. Por ello hoy me tomo un pequeño respiro de los videotutoriales y voy a enseñaros cómo hacer el clásico menú vertical en acordeón con CSS y jQuery.
El resultado lo puedes ver aquí: Ver demo

HTML

Para el html del menú vamos a emplear la estructura típica de listas anidadas. La última entrada será un enlace directo, sin submenú:

<ul id="menu">
<li><a href="#">Menu 1</a>
	<ul>
		<li><a href="#">Submenu 1</a></li>
		<li><a href="#">Submenu 2</a></li>
		<li><a href="#">Submenu 3</a></li>
		<li><a href="#">Submenu 4</a></li>
	</ul>
</li>
<li><a href="#">Menu 2</a>
	<ul>
		<li><a href="#">Submenu 1</a></li>
		<li><a href="#">Submenu 2</a></li>
		<li><a href="#">Submenu 3</a></li>
		<li><a href="#">Submenu 4</a></li>
	</ul>
</li>
<li><a href="#">Menu 3</a>
	<ul>
		<li><a href="#">Submenu 1</a></li>
		<li><a href="#">Submenu 2</a></li>
		<li><a href="#">Submenu 3</a></li>
		<li><a href="#">Submenu 4</a></li>
	</ul>
</li>
<li><a href="#">Menu sin submenu</a></li>
</ul>

Añadiendo el CSS

Para dar estilo al menú tenemos primero que quitar los estilos por defecto de las listas, eliminar los bullets y márgenes y añadirle display:block para que queden perfectamente alineados los elementos uno debajo de otro. Después tenemos que ocultar con display:none los submenús para que aparezcan todos colapsados por defecto. Vamos a añadir algunas extensiones de CSS3 para mejorar visualmente nuestro menú. Estás extensiones sólo serán visibles en navegadores modernos (Firefox, Chrome y Safari), pero no en Internet Explorer. De esta manera podemos añadir bordes redondeados y sombras al menú y al texto. La propiedad -webkit-transition solo funciona en navegadores basados en webkit (Safari y Chrome), y la utilizaremos para mejor el hover añadiendo un fundido en el color del texto y el background. En los navegadores que no soporten estas propiedades simplemente veremos el menú con esquinas normales, hover típico on-off de CSS y sin sombras.

#menu{
	-moz-border-radius:5px;
	-webkit-border-radius:5px;
	border-radius:5px;
	-webkit-box-shadow:1px 1px 3px #888;
	-moz-box-shadow:1px 1px 3px #888;
}
#menu li{border-bottom:1px solid #FFF;}
#menu ul li, #menu li:last-child{border:none}	
a{
	display:block;
	color:#FFF;
	text-decoration:none;
	font-family:'Helvetica', Arial, sans-serif;
	font-size:13px;
	padding:3px 5px;
	text-shadow:1px 1px 1px #325179;
}
#menu a:hover{
	color:#F9B855;
	-webkit-transition: color 0.2s linear;
}
#menu ul a{background-color:#6594D1;}
#menu ul a:hover{
	background-color:#FFF;
	color:#2961A9;
	text-shadow:none;
	-webkit-transition: color, background-color 0.2s linear;
}
ul{
	display:block;
	background-color:#2961A9;
	margin:0;
	padding:0;
	width:130px;
	list-style:none;
}
#menu ul{background-color:#6594D1;}
#menu li ul {display:none;}

Añadiendo la funcionalidad con jQuery

Ahora vamos a ver lo sencillo que es hacer funcionar nuestro menú vertical. Primero añadimos el evento click a cada enlace del menú. Después comprobamos si el siguiente elemento tras el enlace es un ul, ya que si es así este contendrá un submenú, si no será un elemento de un submenú o bien un elemento principal que no contiene submenú (en nuestro ejemplo, el último enlace). Si contiene un submenú, al hacer click este se expandirá o colapsará (slideToggle()), a la vez que colapsaremos el submenú que esté visible que no sea el actual. La función event.preventDefault() sirve para evitar que cuando hagamos click el navegador siga el enlace del href tras ejecutar nuestra función javascript.

<script type="text/javascript" charset="utf-8">
$(function(){
	$('#menu li a').click(function(event){
		var elem = $(this).next();
		if(elem.is('ul')){
			event.preventDefault();
			$('#menu ul:visible').not(elem).slideUp();
			elem.slideToggle();
		}
	});
});
</script>

Podéis escribir en los comentarios cualquier duda que tengáis e intentaré responderla, así como sugerencias para próximos tutoriales.

Actualización: Ante la cantidad de peticiones de cómo hacer que el menú sea multinivel, decidí convertirlo en un plugin de jQuery y hacer un pequeño tutorial con screencast incluido: Cómo hacer un plugin jQuery – Menú acordeón multinivel

Si te ha gustado este artículo, por favor compártelo:
  • Print
  • Digg
  • del.icio.us
  • Facebook
  • Google Bookmarks
  • email
  • Meneame
  • StumbleUpon
  • Tumblr
  • Twitter

Enlaces

112 comentarios para “Menú vertical en acordeón con CSS y jquery”

  1. Lucas dice:

    Ya lo logré! jejeje

    no si es la solucion optima pero paso a comentarles como lo hice por si a alguien le sirve:

    1) puse id=”primero” en el elemento q quiero desplegar
    2) en el document ready agregue esta linea:
    $(‘#primero’).slideDown();

    3) listo!

    Saludos!

  2. Junior dice:

    Muy bueno man justo lo que buscaba se le agradece mucho ;)

  3. Renee dice:

    Gracias hermanito esto era justamente lo que queria aplicar a mi web… thanks. Apenas estoy empezando con esto de lo css. Sigue publicando más

  4. anRoswell dice:

    amigo excelente te agradesco mucho justo lo q estaba buscando, q tal si el submenu permitiera otro submenu, osea otro nivel????

  5. BAdutllak dice:

    Gracias por el tutorial esta putamente currado, y funciona eexceeleente, pero seria posible añadir un subitem al submenu??y de ser asi como se hace?? porque he probado mil historias y no logro que funcione bien (soy un novato), gracias de antemano y sigue publicando que a la gente como yo le van de p*ta madre estos tutoriales!!

  6. David Rojas dice:

    @BAdutlak y @anRoswell Esta pregunta me la hacen mucho, así que aproveché para hacer convertirlo en un plugin de jquery y hacer un screencast:
    http://www.davidrojas.net/index.php/jquery/screencast-como-hacer-un-plugin-jquery-menu-acordeon-multinivel/

  7. Melisa dice:

    Hola, sabes tu codigo me funciona muy bien pero cuando lo quiero poner dentro de mi página, no me carga estoy trabajando con div y ajax.

  8. Alvaro dice:

    David muy buena la web y los articulos.

    Pregunta: como se hace para elegir como submenu abierto por defecto uno del ultimo nivel, le pongo el ul id=”open” pero no lo toma en el ultimo escalon de submenus. y aparte como se puede hacer para que cargue todo cerrado el acordeon y despues se despliegue solo?

    gracias sos un capo

  9. Alejandro dice:

    Muchisimas gracias por el aporte, lo he puesto en funcionamiento y me ha ahorrado un tiempo valioso

  10. David Rojas dice:

    @Alvaro Para que se abra por defecto en el último escalón habría que modificar el script, por ejemplo en esta parte:

    if(settings.startingOpen){
    $(settings.startingOpen).show();
    }

    habría que decirle que ademas de mostrar el div con id startingOpen, mostrara su padre que está oculto. Sobre lo de que cargue todo cerrado y después se despliegue no sé a que te refieres, supongo a que se despliegue en tiempo de carga. Esto lo puedes hacer manualmente con jQuery colocando un script al final de la página (para asegurarte que se ha cargado), pero no lo veo demasiado útil.

    @Melisa Si no me das más detalles que “no me carga” me temo que no puedo hacer nada. ¿Has mirado qué error te da con Firebug?

  11. Emmanuel dice:

    Hola, este menu es justo lo que buscaba!! es muy bueno!

    Te comento que soy muy nuevo por lo que tuve un problema al cargarlo en mi página. Yo coloqué todas las partes en los lugares que especificas y la parte del HTML la puse dentro del div de menu. El problema es que al hacer click en, por ejemplo menu2 en ves de deplegarse el submenu se pierde el div completo.

    Desde ya, muchas gracias

Deja un comentario

Introduce tu información personal en el formulario, regístrate o identifícate usando twitter con el siguiente botón.

RSS iTunes podcast Twitter

Categorías

Mi Amazon whislist: Regálame un libro!

Archivos