Introducción
Este tutorial muestra, con todo lujo de detalles, cómo diseñar un bloque de testimonios apilados para WordPress utilizando CSS moderno. El objetivo es conseguir un bloque visual, accesible y fácilmente integrable en Gutenberg o en cualquier plantilla, con tarjetas de testimonios que aparecen apiladas con ligero solapamiento y comportamiento responsivo y animado.
Visión general y objetivos
- Aspecto: tarjetas apiladas con sombra, borde redondeado y solapamiento ordenado.
- Interacción: al pasar el ratón o al enfocarse, la tarjeta frontal se eleva y queda más visible.
- Accesibilidad: marcado semántico, soporte para navegación por teclado y contraste adecuado.
- Integración: snippets para registrar el bloque y añadir estilos desde un plugin o tema.
Requisitos previos
- WordPress 5.8 (o cualquier versión con editor de bloques moderno).
- Conocimiento básico de CSS, HTML y registrar/encolar assets en WordPress.
- Opcional: experiencia creando bloques con registerBlockType o bloques renderizados en servidor.
Estructura HTML recomendada
Usa un marcado semántico sencillo: una lista de testimonios o una serie de article con blockquote y cite. A continuación se muestra una estructura típica que puedes usar como plantilla dentro del bloque (este bloque es sólo ejemplo de contenido el HTML real va dentro del editor o se genera dinámicamente desde PHP/JS).
Excelentes resultados con el servicio. La atención fue cercana y profesional. El equipo cumplió los plazos y decidió soluciones efectivas para nosotros. Recomendado al 100%. Comunicación clara y resultados visibles en semanas.
CSS base: diseño apilado y visual
La idea es usar variables CSS para facilitar la personalización y emplear transformaciones con z-index para crear el efecto de apilamiento. Aquí un CSS completo y comentado que sirve como punto de partida.
:root{
--testi-bg: #ffffff
--testi-accent: #0a84ff
--testi-text: #222222
--testi-muted: #6b6b6b
--testi-radius: 12px
--testi-shadow: 0 8px 24px rgba(18, 18, 18, 0.12)
--testi-gap: 18px / espacio vertical entre elementos apilados /
--testi-max-width: 720px
}
/ Contenedor principal /
.stacked-testimonials{
max-width: var(--testi-max-width)
margin: 0 auto
padding: calc(var(--testi-gap) 1.25) 1rem
position: relative
/ evita que elementos flotantes overflow: visible /
}
/ Reset básico de artículos para controlar posicionamiento /
.stacked-testimonials .testimonial{
background: var(--testi-bg)
color: var(--testi-text)
border-radius: var(--testi-radius)
box-shadow: var(--testi-shadow)
padding: 1.25rem 1.25rem
border: 1px solid rgba(10,10,10,0.04)
transition: transform 320ms cubic-bezier(.2,.9,.25,1), box-shadow 320ms
position: relative
/ cada tarjeta ocupa el mismo ancho /
width: 100%
/ para el orden visual /
transform-origin: center top
}
/ Estilo del contenido interior /
.stacked-testimonials .testimonial__quote{
font-size: 1rem
line-height: 1.5
margin: 0 0 0.75rem 0
}
/ Metadatos /
.stacked-testimonials .testimonial__meta{
display: flex
flex-direction: column
gap: 0.2rem
color: var(--testi-muted)
font-size: 0.9rem
}
/ Efecto de apilamiento: desplazamientos y z-index /
.stacked-testimonials .testimonial:nth-child(1){
z-index: 30
transform: translateY(0) scale(1)
}
.stacked-testimonials .testimonial:nth-child(2){
z-index: 20
transform: translateY(var(--testi-gap)) scale(.985)
opacity: 0.98
}
.stacked-testimonials .testimonial:nth-child(3){
z-index: 10
transform: translateY(calc(var(--testi-gap) 2)) scale(.97)
opacity: 0.95
}
/ Si hay más elementos, se pueden añadir más reglas o usar una regla genérica con nth-child(n) /
/ Al pasar el ratón o focus, elevamos la tarjeta y traemos al frente /
.stacked-testimonials .testimonial:hover,
.stacked-testimonials .testimonial:focus{
transform: translateY(0) scale(1.006)
z-index: 60 !important
box-shadow: 0 18px 36px rgba(18,18,18,0.18)
}
/ En dispositivos pequeños mostramos la lista sin solapar (mejor legibilidad) /
@media (max-width: 640px){
.stacked-testimonials .testimonial{
transform: none !important
margin-bottom: 1rem
}
.stacked-testimonials{
padding: 1rem
}
}
/ Opcional: pequeñas rotaciones para estilo más apilado /
.stacked-testimonials .testimonial:nth-child(2){
transform: translateY(var(--testi-gap)) rotate(-0.6deg) scale(.986)
}
.stacked-testimonials .testimonial:nth-child(3){
transform: translateY(calc(var(--testi-gap) 2)) rotate(0.6deg) scale(.974)
}
Comportamiento responsivo y variantes
Para pantallas pequeñas es preferible eliminar el solapamiento y mostrar las tarjetas en columna normal. Para pantallas muy grandes puedes aumentar los offsets o incluso mostrar 2 columnas con apilamiento en cada columna.
/ Dos columnas en pantallas grandes, manteniendo apilamiento por columna /
@media (min-width: 1100px){
.stacked-testimonials{
display: grid
grid-template-columns: 1fr 1fr
gap: 2rem
}
/ controla la lógica de apilamiento por columna si el HTML lo organiza así /
}
Animaciones y microinteracciones
Las animaciones deben ser sutiles. Hemos usado transiciones en transform y box-shadow. Para mejorar la percepción de profundidad puedes añadir un pequeño delay progresivo para cada tarjeta.
.stacked-testimonials .testimonial{
transition: transform 360ms cubic-bezier(.2,.9,.25,1), box-shadow 360ms
}
.stacked-testimonials .testimonial:nth-child(1){
transition-delay: 0ms
}
.stacked-testimonials .testimonial:nth-child(2){
transition-delay: 30ms
}
.stacked-testimonials .testimonial:nth-child(3){
transition-delay: 60ms
}
Accesibilidad y consideraciones semánticas
- Usa article y blockquote para marcar contenido de testimonios.
- Incluye tabindex=0 si las tarjetas deben ser enfocables con el teclado. Alternativamente, haz que los elementos interactivos dentro sean focusables.
- Proporciona aria-label o texto alternativo que identifique al autor cuando sea necesario.
- Asegúrate del contraste de color entre texto y fondo (WCAG AA como mínimo).
- Evita animaciones que provoquen mareo si incluyes animaciones, respeta la preferencia del usuario con prefers-reduced-motion.
@media (prefers-reduced-motion: reduce){
.stacked-testimonials .testimonial{
transition: none
transform: none !important
}
}
Integración con Gutenberg — ejemplo de registro de bloque (PHP)
A continuación un ejemplo básico de cómo registrar un bloque que carga estilos front-end y editor. Ajusta rutas y nombres según tu plugin/tema.
st-styles,
style => st-styles,
// render_callback => st_render_testimonials // si quieres render server-side
) )
}
add_action( init, st_register_block )
?>
Renderizado server-side (opcional)
Si prefieres generar el HTML desde PHP (útil para contenido dinámico o integrado con CPTs), puedes usar un render_callback.
foreach ( items as item ) {
quote = esc_html( item[quote] )
author = esc_html( item[author] )
role = isset(item[role]) ? esc_html(item[role]) :
printf(
%s
,
author,
quote,
author,
role
)
}
echo
Leave a Reply