Tutorial WordPress: Hacer una sección de FAQ en dos columnas en desktop y una en móvil

·

·

Introducción

Este tutorial explica paso a paso cómo crear una sección de FAQ (preguntas frecuentes) en WordPress que muestre dos columnas en pantallas de escritorio y una columna en dispositivos móviles. Incluye el marcado HTML recomendado, estilos CSS para la disposición y la interacción (acordeón accesible) y el código PHP para integrarlo como un shortcode o parte de tu tema. Todos los ejemplos de código están preparados para copiar y pegar.

Resumen de la solución

Requisitos previos

1. Marcado HTML recomendado

Usamos una estructura simple con una lista de elementos .faq-item. La pregunta será un elemento interactivo (button) para accesibilidad y la respuesta será un contenedor que puede abrirse/cerrarse. Ejemplo de HTML:

ltsection class=faq-section aria-label=Preguntas frecuentesgt
  ltul class=faq-gridgt
    ltli class=faq-itemgt
      ltbutton class=faq-question aria-expanded=false aria-controls=faq1gt¿Cómo puedo cancelar mi suscripción?lt/buttongt
      ltdiv id=faq1 class=faq-answer hiddengt
        ltpgtPara cancelar, accede a tu cuenta y selecciona ltstronggtCancelar suscripciónlt/stronggt en el panel de facturación.lt/pgt
      lt/divgt
    lt/ligt
    ltli class=faq-itemgt
      ltbutton class=faq-question aria-expanded=false aria-controls=faq2gt¿Ofrecen soporte 24/7?lt/buttongt
      ltdiv id=faq2 class=faq-answer hiddengt
        ltpgtNuestro soporte está disponible de lunes a viernes. Para urgencias, usa el formulario de contacto.lt/pgt
      lt/divgt
    lt/ligt
    lt!-- Más items... --gt
  lt/ulgt
lt/sectiongt

Notas sobre el marcado

2. CSS: dos columnas en desktop y una en móvil

Este CSS crea una cuadrícula responsive y estilos básicos para el acordeón. Ajusta colores, tipografías y valores a tu diseño.

/ Contenedor grid: 2 columnas en escritorio, 1 en móvil /
.faq-grid {
  display: grid
  grid-template-columns: repeat(2, 1fr)
  gap: 1.25rem / espacio entre items /
  list-style: none
  margin: 0
  padding: 0
}

/ Item /
.faq-item {
  border: 1px solid #e0e0e0
  border-radius: 6px
  overflow: hidden
  background: #fff
}

/ Pregunta (botón) /
.faq-question {
  width: 100%
  text-align: left
  padding: 1rem
  background: transparent
  border: none
  cursor: pointer
  font-weight: 600
  font-size: 1rem
  display: flex
  justify-content: space-between
  align-items: center
}

/ Indicador visual (puedes usar ::after para un icono) /
.faq-question::after {
  content:  
  margin-left: 1rem
  transition: transform .25s ease
}

/ Cuando está expandido se rota el indicador /
.faq-question[aria-expanded=true]::after {
  content: -
  transform: rotate(0deg)
}

/ Respuesta (por defecto oculta) /
.faq-answer {
  padding: 0 1rem 1rem 1rem
  line-height: 1.5
}

/ Si está hidden, manténlo oculto mediante display o max-height (mejor para transiciones) /
.faq-answer[hidden] {
  display: none
}

/ <= 767px: una columna /
@media (max-width: 767px) {
  .faq-grid {
    grid-template-columns: 1fr
  }
}

Transiciones y animación (opcional)

Si deseas animar la apertura/cierre, cambia hide/show con max-height y overflow ten en cuenta que requiere medir la altura o usar transitions con max-height suficientemente grande.

/ Alternativa con animación (requiere JS que gestione la altura) /
.faq-answer {
  max-height: 0
  overflow: hidden
  transition: max-height .35s ease
  padding: 0 1rem
}
.faq-item.open .faq-answer {
  max-height: 400px / suficiente para el contenido mejor calcular en JS /
  padding: 1rem
}

3. JavaScript: comportamiento del acordeón y accesibilidad

Este script añade la lógica para abrir/cerrar items, actualizar aria-expanded y permitir navegación con teclado. Lo ideal es encolarlo con wp_enqueue_script (ver sección PHP).

document.addEventListener(DOMContentLoaded, function() {
  var faqButtons = document.querySelectorAll(.faq-question)

  faqButtons.forEach(function(btn) {
    btn.addEventListener(click, function() {
      var expanded = btn.getAttribute(aria-expanded) === true
      var controlledId = btn.getAttribute(aria-controls)
      var controlledEl = document.getElementById(controlledId)

      // Toggle estado
      if (expanded) {
        btn.setAttribute(aria-expanded, false)
        if (controlledEl) {
          controlledEl.setAttribute(hidden, )
        }
        btn.closest(.faq-item)?.classList.remove(open)
      } else {
        btn.setAttribute(aria-expanded, true)
        if (controlledEl) {
          controlledEl.removeAttribute(hidden)
        }
        btn.closest(.faq-item)?.classList.add(open)
      }
    })

    // Soporte teclado: abrir con Enter o Space (button ya lo maneja por defecto)
    // Si deseas añadir navegación entre preguntas, implementa manejadores de flechas.
  })

  // Opcional: cerrar otros al abrir uno (acordeón exclusivo)
  // Si quieres solo uno abierto a la vez:
  function enableExclusiveOpen() {
    faqButtons.forEach(function(btn) {
      btn.addEventListener(click, function() {
        if (btn.getAttribute(aria-expanded) === true) {
          faqButtons.forEach(function(other) {
            if (other !== btn) {
              other.setAttribute(aria-expanded, false)
              var id = other.getAttribute(aria-controls)
              var el = document.getElementById(id)
              if (el) el.setAttribute(hidden, )
              other.closest(.faq-item)?.classList.remove(open)
            }
          })
        }
      })
    })
  }
  // Llamar a enableExclusiveOpen() si se desea ese comportamiento
})

4. Integración en WordPress: shortcode y encolado de assets

Ejemplo de cómo registrar un shortcode [faq_section] que imprime el marcado y encola CSS/JS desde functions.php o un plugin.

/ En functions.php o en un plugin /
function mytheme_enqueue_faq_assets() {
  // Estilos
  wp_enqueue_style(my-faq-style, get_stylesheet_directory_uri() . /assets/css/faq.css, array(), 1.0)

  // Script (coloca en assets/js/faq.js)
  wp_enqueue_script(my-faq-script, get_stylesheet_directory_uri() . /assets/js/faq.js, array(), 1.0, true)
}
add_action(wp_enqueue_scripts, mytheme_enqueue_faq_assets)

function mytheme_faq_shortcode(atts) {
  // Puedes obtener preguntas desde ACF o un CPT. Aquí un ejemplo estático con 2 items.
  ob_start()
  ?>
  ltsection class=faq-section aria-label=Preguntas frecuentesgt
    ltul class=faq-gridgt
      ltli class=faq-itemgt
        ltbutton class=faq-question aria-expanded=false aria-controls=faq1gt¿Cómo puedo cancelar mi suscripción?lt/buttongt
        ltdiv id=faq1 class=faq-answer hiddengt
          ltpgtPara cancelar, accede a tu cuenta y selecciona ltstronggtCancelar suscripciónlt/stronggt en el panel de facturación.lt/pgt
        lt/divgt
      lt/ligt
      ltli class=faq-itemgt
        ltbutton class=faq-question aria-expanded=false aria-controls=faq2gt¿Ofrecen soporte 24/7?lt/buttongt
        ltdiv id=faq2 class=faq-answer hiddengt
          ltpgtNuestro soporte está disponible de lunes a viernes. Para urgencias, usa el formulario de contacto.lt/pgt
        lt/divgt
      lt/ligt
    lt/ulgt
  lt/sectiongt
  lt?php
  return ob_get_clean()
}
add_shortcode(faq_section, mytheme_faq_shortcode)

Ejemplo: obtener FAQs desde un Custom Post Type faq

Si tienes un CPT llamado faq, reemplaza el contenido estático por una consulta WP_Query. Ejemplo de loop:

query = new WP_Query(array(
  post_type => faq,
  posts_per_page => -1,
  orderby => menu_order,
  order => ASC,
))
if (query->have_posts()) {
  echo ltul class=faq-gridgt
  i = 1
  while (query->have_posts()) {
    query->the_post()
    id = faq . i
    echo ltli class=faq-itemgt
    echo ltbutton class=faq-question aria-expanded=false aria-controls= . esc_attr(id) . gt . get_the_title() . lt/buttongt
    echo ltdiv id= . esc_attr(id) .  class=faq-answer hiddengt . apply_filters(the_content, get_the_content()) . lt/divgt
    echo lt/ligt
    i  
  }
  echo lt/ulgt
  wp_reset_postdata()
}

5. Buenas prácticas y accesibilidad

6. Variantes y mejoras

7. Problemas comunes y soluciones

  1. El CSS no se aplica: comprueba que la hoja esté encolada y que no haya reglas más específicas del tema que la estén sobrescribiendo. Usa selectores más específicos o !important con moderación.
  2. JS no funciona: verifica que el script se encole en el footer (último parámetro true) y que no haya errores JS en la consola que detengan la ejecución.
  3. IDs duplicados: si generas IDs dinámicamente desde un loop asegúrate de que cada faq tenga un id único (ej. faq1, faq2...).
  4. Problemas de accesibilidad: prueba con lectores de pantalla y navegación por teclado, asegurando que aria-expanded y hidden estén sincronizados.

Conclusión

Con una estructura semántica simple, CSS Grid para la disposición responsive y un JavaScript ligero para la interacción accesible, puedes implementar una sección de FAQ que muestre dos columnas en escritorio y una en móvil. Integra el código en WordPress mediante un shortcode o plantilla, y adapta los estilos al diseño de tu sitio. Los fragmentos de ejemplo incluidos cubren el marcado, los estilos, el script y la integración PHP listos para usar.



Leave a Reply

Your email address will not be published. Required fields are marked *