A 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.



hola David, te queria preguntar que en vez de un texto en el boton saliera una imagen.
Lo consegui con otro tipo de menu pero con este no.
Gracias.
vale, ya esta hecho.
xD
Quería dejarles para que lo chequearan, un menú horizontal tipo acordeón con sólo CSS. También he desarrollado una versión con el efecto deslizante que utiliza SMIL (HTML+TIME) para IE y “CSS3 transitions” para el resto.
Enlace: http://alejandroaraneda.blogspot.com/
queria hacer otra pregunta.
como se haria para que en lugar de cerrarse el menu clicar sobre otra seccion, se quedaran todas abiertas?
no se si me explico.
@Bral Simplemente quita la línea que pone
$('#menu ul:visible').not(elem).slideUp();. Es fácil de entender, esta línea busca los elementos visibles que sean distintos del que acabas de clickar y lo oculta.si es lo que habia pensado, gracias por confirmalo.
saludos
como se puede hacer para agregras un nivel mas de sub menu y que se desplige sin que se cierre el menu
@augusto Eso lo tengo preparado para otro artículo cuando tenga tiempo, y de paso aprovecharlo para explicar cómo hacer un plugin en jQuery
por favor me podrias espicar ya que lo necesito urgente
please!!!!!
hola
he seguido esta explicacion me parece muy bien, pero no se como relacionar el codigo de la funcion javascript con el html y css, disculpa la pregunta pero estoy aprendiendo, me puedes ayudar con ello.
@alfonso Carga la demo y mira el código fuente, ahí veras donde se tiene que colocar todo.
Hola David, gracias por compartir tus codigos, queria saber si podrias explicarme como agregar un nivel mas de sub-menu, eh estado intentando pero no he logrado obtener el resultado esperado …. gracias
Buenos dias David probando lo del menu no me funciono nose porque es decir lo puse igual que el suyo pero no se me abren las pestañas aver si me pudiera dar alguna sugerencia gracias
Hola, antes que nada te quiero agradecer el post, esta muy bien la explicación y sobre todo el codigo.
El unico detalle es que cambia mucho el layout del menu en IE6… ¿Algún consejo?
@Christian Estoy en ello, en cuanto pueda pondré otro artículo explicándolo, paciencia
@alberto Si no me das más datos… Prueba instalando Firebug y mira en la consola si te da algún error.
@Jon IE6 no soporta por ejemplo el child selector (‘>’) del css, puedes buscar alguna manera creativa de sustituirlo. Contra los bordes redondeados, sombras, etc. no hay nada que hacer (en ninguna versión de IE). Personalmente he dejado de soporta IE6, google oficialmente deja de soportarlo para youtube y google docs este mes, y posteriormente lo hará para gmail. No vale la pena, y gracias a que google abandona su soporte seguramente veremos que en los próximos meses el uso de IE6 tiende a desaparecer rápidamente.
Muy buena tu ayuda David, espero nos puedas ayudar para aumentar un nivel mas, estoy intentando y probando y no me sale espero tu colaboracion. Muchas gracias…
Hola David, muchas gracias ante todo
Mi idea sería hacer esto mismo, pero sin submenus. Que cuando pinchase en el primer nivel se despliegue contenido de texto.
Por ejemplo, una lista de ciudades y que al pinchar en cada una apareciese información sobre la ciudad.
No se si me he explicado… me podrías ayudar??
Gracias
@Mar Funciona exactamente igual. Donde pones un link a submenú, en vez de poner ese enlace pones tu contenido. Por lo tanto por ejemplo dentro de “menú 1″ tendrás una lista con un ul y un solo li con su contenido dentro (pero ningún enlace).