Icono del sitio Tursos

Como hacer un Acordeón (accordion) con jQuery y CSS

 

En este tutorial haremos un acordeón vertical usando jQuery con un código bastante minimalista y facil de entender, usaremos CSS para darle decoración y mejorar la experiencia de usuario.

Estructura HTML

Usaremos con una lista de definición o definition list (dl) para manejar la estructura de los contenidos, una vez comprendas el funcionamiento del código podrás adaptarlo a cualquier otra estructura:

<dl>
    <dt>Titulo 1</dt>
    <dd>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Consectetur maxime cupiditate nesciunt molestias itaque vel reiciendis officiis explicabo cum impedit dolorem quod minus beatae architecto necessitatibus sed exercitationem aliquam omnis!</dd>

    <dt>Titulo 2</dt>
    <dd>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Voluptates mollitia quos! Dolor cum vitae aperiam deserunt hic quas quidem qui excepturi minima repudiandae pariatur id sit dignissimos laborum provident velit!</dd>

    <dt>Titulo 3</dt>
    <dd>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Optio voluptatum expedita sunt voluptatibus ratione assumenda quo animi numquam blanditiis asperiores illo laudantium et quae itaque reiciendis nam ducimus officiis officia?</dd>

    <dt>Titulo 4</dt>
    <dd>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Iusto obcaecati numquam nemo quasi omnis accusamus illo distinctio doloribus architecto culpa maiores blanditiis laborum accusantium assumenda vero necessitatibus optio? Ipsa perferendis.</dd>

    <dt>Titulo 5</dt>
    <dd>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Iusto obcaecati numquam nemo quasi omnis accusamus illo distinctio doloribus architecto culpa maiores blanditiis laborum accusantium assumenda vero necessitatibus optio? Ipsa perferendis.</dd>
  </dl>

jQuery

Luego procedemos a incluir a jQuery y ademas creamos un script en el cual ira nuestro código, si deseas puedes manejarlo en un JS aparte, pero para el ejemplo lo haremos todo junto:

<script type="text/javascript" src="http://code.jquery.com/jquery-latest.js"></script>
<script type="text/javascript">

</script>

Lo primero que haremos sera ocultar todos los ‘dd’, pero no los dd que esten posteriores a un dt con clase .activo, esto nos va a permitir dejar un item abierto por defecto, luego procedemos a detectar cuando ‘dt’ sea presionado:

$('dl dd').not('dt.activo + dd').hide(); 
$('dl dt').click(function(){

});

Dentro del evento de click le pondremos una condición:

 $('dl dt').click(function(){
   if ($(this).hasClass('activo')) {
        $(this).removeClass('activo');
        $(this).next().slideUp();
   } else {
        $('dl dt').removeClass('activo');
        $(this).addClass('activo');
        $('dl dd').slideUp();
        $(this).next().slideDown();
   }
});

(Linea 23) Si es que este ‘dt’ que acabamos de cliquear tiene la clase .activo (osea si esta abierto) le quitamos la clase .activo (linea 24) y hacemos que el elemento que le sigue, que vendría a ser el ‘dd’ adyacente (que esta mostrandose), se oculte (linea 25).

En caso contrario (que muy probablemente vendría a ser el estado por defecto) al hacerle clic, lo primero que hará es quitarle .activo a todos los demás ‘dt’ (linea 27), pero le asignamos .activo al que acabamos de cliquear (linea 28), luego ocultamos todos los ‘dd’ (linea 29) y por ultimo mostramos solo el ‘dd’ que le sigue a este ‘dt’ (linea 30), de esta forma solo se muestra uno a la vez.

CSS

Hasta allí lo tendríamos completamente funcional, sin embargo la experiencia no es tan agradable, para mejorar esto usaremos algo de CSS:

*{ font-family: sans-serif; margin: 0;}
dl{ margin: 60px auto; width: 600px; }
dt, dd{ padding: 20px; }
dt{ background: #333333; color: white; border-bottom: 1px solid #141414; border-top: 1px solid #4E4E4E; cursor: pointer; }
dd{ background: #F5F5F5; line-height: 1.6em; }
dt.activo, dt:hover{ background: #424242; }

Va quedado mejor, pero podemos hacer mas aun, le vamos a añadir unas flechitas con la ayuda de la pseudo-clase :after.

dt:before{ content: "▸"; margin-right: 10px; }
dt.activo:before{ content: "▾"; }

Lo que estamos haciendo aqui es que, por defecto antes de todo dt haya una ‘▸’, pero si este dt esta .activo que esta cambie a ‘▾’.

Dejar un item activado por defecto

Si queremos dejar un item abierto por defecto, simplemente le ponemos al dt la clase activo, ya que al cargar la pagina no va a ocultar los dd que esten posteriores a un dt con clase activo:

<dt class="activo">Titulo 3</dt>
<dd>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Optio voluptatum expedita sunt voluptatibus ratione assumenda quo animi numquam blanditiis asperiores illo laudantium et quae itaque reiciendis nam ducimus officiis officia?</dd>

Código Final

<!DOCTYPE HTML>
<html lang="en-US">
<head>
	<meta charset="UTF-8">
	<title></title>
	<style type="text/css">
		*{ font-family: sans-serif; margin: 0;}
		dl{ margin: 60px auto; width: 600px; }
		dt, dd{ padding: 20px; }
		dt{ background: #333333; color: white; border-bottom: 1px solid #141414; border-top: 1px solid #4E4E4E; cursor: pointer; }
		dd{ background: #F5F5F5; line-height: 1.6em; }
		dt.activo, dt:hover{ background: #424242; }

		dt:before{ content: "▸"; margin-right: 10px; }
		dt.activo:before{ content: "▾"; }
	</style>
</head>
<body>
	<dl>
		<dt>Titulo 1</dt>
		<dd>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Consectetur maxime cupiditate nesciunt molestias itaque vel reiciendis officiis explicabo cum impedit dolorem quod minus beatae architecto necessitatibus sed exercitationem aliquam omnis!</dd>

		<dt>Titulo 2</dt>
		<dd>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Voluptates mollitia quos! Dolor cum vitae aperiam deserunt hic quas quidem qui excepturi minima repudiandae pariatur id sit dignissimos laborum provident velit!</dd>

		<dt>Titulo 3</dt>
		<dd>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Optio voluptatum expedita sunt voluptatibus ratione assumenda quo animi numquam blanditiis asperiores illo laudantium et quae itaque reiciendis nam ducimus officiis officia?</dd>

		<dt>Titulo 4</dt>
		<dd>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Iusto obcaecati numquam nemo quasi omnis accusamus illo distinctio doloribus architecto culpa maiores blanditiis laborum accusantium assumenda vero necessitatibus optio? Ipsa perferendis.</dd>

		<dt>Titulo 5</dt>
		<dd>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Iusto obcaecati numquam nemo quasi omnis accusamus illo distinctio doloribus architecto culpa maiores blanditiis laborum accusantium assumenda vero necessitatibus optio? Ipsa perferendis.</dd>
	</dl>
	<script type="text/javascript" src="http://code.jquery.com/jquery-latest.js"></script>
	<script type="text/javascript">
	  $('dl dd').not('dt.activo + dd').hide();
       $('dl dt').click(function(){
          if ($(this).hasClass('activo')) {
               $(this).removeClass('activo');
               $(this).next().slideUp();
          } else {
               $('dl dt').removeClass('activo');
               $(this).addClass('activo');
               $('dl dd').slideUp();
               $(this).next().slideDown();
          }
       });
	</script>
</body>
</html>

Si tienes alguna duda ponla en los comentarios, puedes  descargar el código fuente desde aquí.