4

¿Cómo hacer lista de preguntas y respuestas (preguntas frecuentes, FAQ) con HTML, CSS y JS?

Hola hoy quiero explicarte como hacer una lista como la de la imágen, puedes verla en funcionamiento aquí. Partiremos de una estructura HTML básica como la siguiente:

<!DOCTYPE html><html><head><metacharset="utf-8"><metahttp-equiv="X-UA-Compatible"content="IE=edge"><title>Preguntas frecuentes</title><metaname="viewport"content="width=device-width, initial-scale=1"><!-- Estilos --><linkrel="stylesheet"type="text/css"media="screen"href="styles.css"></head><body><!-- La lista de preguntas irá aquí --><!-- JQuery --><scriptsrc="https://code.jquery.com/jquery-3.3.1.min.js"integrity="sha256-FgpCb/KJQlLNfOu91ta32o/NMZxltwRo8QtmkMRdAu8="crossorigin="anonymous"></script><!-- Script para controlar la lista de preguntas --><scriptsrc="script.js"></script><!-- FontAwesome --><linkrel="stylesheet"href="https://use.fontawesome.com/releases/v5.5.0/css/all.css"integrity="sha384-B4dIYHKNBt8Bc12p+WXckhzcICo0wtJAoU8YZTY5qE0Id1GSseTk6S+L3BlXeVIU"crossorigin="anonymous"></body></html>

Como ves, voy a usar JQuery, también he linkeado una hoja de estilos llamada “styles.css” y un script llamado “script.js”. Estos archivos aún están vacíos. Por último tengo el link de Font Awesome para usar algunos iconos.

Agregaré una etiqueta <div> con la clase “fondo” debajo de la apertura del <body>, la usaré para dar un color de fondo a la pantalla y centrar los elementos.

<div class="fondo"></div>

Agrego los estilos en el archivo “styles.css”:

*{
  margin: 0;
  padding: 0;
}
.fondo{
  /* Gradiente del fondo */background: rgba(12,176,255,1);
  background: -moz-linear-gradient(-45deg, rgba(12,176,255,1) 0%, rgba(104,205,253,1) 100%);
  background: -webkit-gradient(left top, right bottom, color-stop(0%, rgba(12,176,255,1)), color-stop(100%, rgba(104,205,253,1)));
  background: -webkit-linear-gradient(-45deg, rgba(12,176,255,1) 0%, rgba(104,205,253,1) 100%);
  background: -o-linear-gradient(-45deg, rgba(12,176,255,1) 0%, rgba(104,205,253,1) 100%);
  background: -ms-linear-gradient(-45deg, rgba(12,176,255,1) 0%, rgba(104,205,253,1) 100%);
  background: linear-gradient(135deg, rgba(12,176,255,1) 0%, rgba(104,205,253,1) 100%);
  filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#0cb0ff', endColorstr='#68cdfd', GradientType=1 );

  display: flex;
  align-items: center;
  justify-content: center;
  min-height: 100vh;
}

A la clase “fondo” le he puesto un gradiente que generé con esta página y algunos estilos para centrar los elementos.

Es hora de agregar las preguntas y respuestas, la estructura que usaré es la siguiente:

<ul class="lista">
  <!-- Pregunta 1 --><liclass="pregunta"data-resp_id="resp_1"><span></span><iclass="ico_resp fas fa-angle-down"></i></li><liclass="respuesta"id="resp_1"><spanid="sp_resp_1"></span></li><!-- Pregunta 2 --><liclass="pregunta"data-resp_id="resp_2"><span></span><iclass="ico_resp fas fa-angle-down"></i></li><liclass="respuesta"id="resp_2"><spanid="sp_resp_2"></span></li></ul>

Empiezo con una etiqueta <ul> con la clase “lista”, todas las preguntas irán aquí adentro. Luego, cada pregunta está compuesta por un <li>, con la clase “pregunta” y, seguido a este, otro <li> con la clase “respuesta”. Dentro del <li> con la clase “pregunta” hay un <span>, aquí es donde se escribe la pregunta, y un <i> que es un icono. Por último el <li> con la clase “respuesta” posee un <span>, ahí es donde va la respuesta. Los ids, el “data-resp_id” y la clase “ico_resp” que tienen los <i> los usaré más adelante cuando empiece a editar el sript. Un ejemplo de una pregunta completa se vería así:

<liclass="pregunta" data-resp_id="resp_1">
  <span>¿Dequé se alimentan los koalas?</span>
  <i class="ico_resp fas fa-angle-down"></i>
</li>
<liclass="respuesta" id="resp_1">
  <span id="sp_resp_1">Los koalas son animales herbívoros que tienen una dieta poco variada. Se alimentan de hojas de eucalipto.</span>
</li>

Ahora los estilos:

.lista{
  background: white;
  max-width: 50%;
  margin: auto;
  border-radius: 10px;
  list-style: none;
  font-size: 19px;
  font-family: Arial, Helvetica, sans-serif;
}
.pregunta{
  padding: 9px;
  border-bottom: 1px solid lightgrey;
  cursor: pointer;
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding-right: 15px;
}
.preguntai{
  font-size: 21px;
  transition: .3s;
}
.preguntaspan{
  transition: .3s;
}
.pregunta:hoverspan{
  margin-left: 15px;
}
.pregunta:last-child{
  border: none;
}
.respuesta{
  text-align: justify;
  background: #f3f3f3;
  height: 0;
  overflow: hidden;
  transition: .5s;
  padding: 014px;
}
/* Estilos para una pregunta seleccionada */.resp_act{
  padding-top: 2px;
  padding-bottom: 7px;
  border-bottom: 1px solid lightgrey;
}
.ico_resp_act{
  transform: rotate(180deg);
}

Los estilos “.resp_act” y “.ico_resp_act” los agregaremos cuando el usuario haga click en alguna pregunta.
Con esto termino el archivo de estilos. Ahora el script, es muy sencillo:

// Cuando se hace click en una pregunta
$('.pregunta').on('click', function () {
  // Si la pregunta en la que se hizo click NO está abierta.if (!$('#' + $(this).data('resp_id')).hasClass('resp_act')) {
    // Cierro la que esté abierta, si es que hay alguna
    $('.ico_resp').removeClass('ico_resp_act');
    $('.resp_act').css('height', 0);
    $('.resp_act').removeClass('resp_act');
    // Abro la pregunta en la que se hizo click
    $('#' + $(this).data('resp_id')).css('height', $('#sp_' + $(this).data('resp_id')).height() + 'px');
    $('#' + $(this).data('resp_id')).addClass('resp_act');
    $('i', this).addClass('ico_resp_act');
  // Si no, si la pregunta ya está abierla
  } else {
    // La cierro
    $('.ico_resp').removeClass('ico_resp_act');
    $('.resp_act').css('height', 0);
    $('.resp_act').removeClass('resp_act');
  }
});

Eso es todo, puedes acceder al código completo en GitHub o ver un ejemplo de uso en este proyecto que estoy desarrollando. Espero que te haya sido de utilidad, nos vemos!

Escribe tu comentario
+ 2
1
68Puntos

Excelente, pero quisiera saber si es posible agregar una tabla a esta sección como respuesta ya que veo solamente texto

1
3Puntos

Hola, muy util tu codigo!
Estoy tratando de agregarlo a mi sitio web, pero no me funciona. Lo copie tal cual para probar, pero no estaria llamando a la funcion js, sabes por donde puede venir el problema?

Gracias
Enrique