Tutorial WordPress: Crear tarjetas con bordes animados usando conic-gradient

·

·

Introducción y objetivo

Este tutorial muestra, con todo lujo de detalles, cómo crear tarjetas (cards) con bordes animados usando conic-gradient y técnicas modernas de CSS. Verás varias implementaciones: una versión estática, una versión animada continuamente, una versión que se activa al pasar el ratón, y cómo integrar el código en WordPress (Custom CSS, functions.php). También se incluyen consideraciones de accesibilidad, rendimiento y soluciones a problemas comunes.

Concepto básico: ¿por qué conic-gradient para bordes?

conic-gradient genera un degradado en forma circular alrededor de un centro. Si lo colocamos en un pseudo-elemento que se sitúa detrás o delante del contenido y lo enmascaramos o recortamos correctamente, podemos mostrar únicamente una franja exterior que actúe como borde. Al animar el pseudo-elemento (por ejemplo rotándolo), el degradado parece desplazarse alrededor de la tarjeta, creando un borde animado muy atractivo sin imágenes ni SVG extras.

Ventajas de esta técnica

HTML básico de la tarjeta

Usa esta estructura mínima dentro de un bloque HTML o en el editor de bloques (Bloque HTML o Bloque de Código). El contenido de la tarjeta se puede ajustar libremente.

ltdiv class=cg-cardgt
  ltdiv class=cg-card__contentgt
    lth3gtTítulo de la tarjetalt/h3gt
    ltpgtTexto descriptivo, botón o enlaces.lt/pgt
  lt/divgt
lt/divgt

CSS: tarjeta con borde animado continuo (versión base)

Explicación breve antes del código: creamos un pseudo-elemento ::before que ocupa todo el contenedor, con un conic-gradient como fondo. Para mostrar solo el borde usamos padding en el elemento principal y aplicamos background-clip / mask o recortamos con inset en el pseudo-elemento. A continuación un ejemplo completo y comentado.

/ Variables para fácil personalización /
.cg-card {
  --border-size: 4px            / grosor del borde /
  --radius: 12px               / radio de la tarjeta /
  --gap-color: #0f1720         / color interior / fondo de la tarjeta /
  --speed: 4s                  / duración de la animación /
  --colors: #ff0080 0deg, #ff8c00 120deg, #40e0d0 240deg / paradas: color   ángulo opcional /

  position: relative
  padding: 1rem                / espaciado interior para el contenido /
  border-radius: var(--radius)
  background: var(--gap-color) / fondo interno visible entre borde y contenido /
  overflow: hidden
  isolation: isolate           / crea un nuevo contexto de apilado /
}

/ Contenido de la tarjeta (dentro del borde) /
.cg-card__content {
  position: relative
  z-index: 2                   / por encima del pseudo-elemento /
  color: #fff
}

/ Pseudo-elemento que dibuja el borde con conic-gradient /
.cg-card::before {
  content: 
  position: absolute
  inset: calc(-1  var(--border-size)) / dejamos espacio para el borde fuera del elemento real /
  z-index: 1
  border-radius: calc(var(--radius)   var(--border-size))
  background: conic-gradient(from 0deg, var(--colors))
  -webkit-mask: 
    linear-gradient(#fff, #fff) content-box, 
    linear-gradient(#000, #000)
  -webkit-mask-composite: xor  / para WebKit, recortar centro (ver fallback más abajo) /
  mask-composite: exclude      / para navegadores con soporte moderno /
  padding: var(--border-size)   / define el ancho visible del borde /
  pointer-events: none
  animation: cg-rotate var(--speed) linear infinite
}

/ Alternativa con máscara usando mask con SVG o con mask shorthand (mejor compatibilidad considerar polyfills) /
@keyframes cg-rotate {
  to { transform: rotate(1turn) }
}
/ Ajustes para dispositivos pequeños o cuando no queremos animación perpetua /
@media (prefers-reduced-motion: reduce) {
  .cg-card::before { animation: none }
}

Notas sobre el código anterior

Versión: borde que aparece al pasar el ratón (hover)

Si prefieres que la animación se active solo en hover, controla la opacidad y la animación en :hover.

.cg-card:hover::before {
  opacity: 1
  transform: rotate(0)
  animation: cg-rotate var(--speed) linear infinite
}

/ Inicio oculto /
.cg-card::before {
  opacity: 0
  transition: opacity .25s ease
  transform: rotate(0deg)
}

Implementación alternativa usando dos pseudo-elementos (mejor compatibilidad)

Si la máscara compuesta no funciona bien en algunos navegadores, usa dos pseudo-elementos: uno para el degradado grande y otro para cubrir el centro.

.cg-card {
  position: relative
  border-radius: var(--radius)
  background: var(--gap-color)
  padding: 1rem
  overflow: visible
}

.cg-card::before,
.cg-card::after {
  content: 
  position: absolute
  inset: 0
  border-radius: calc(var(--radius)   var(--border-size))
  pointer-events: none
  z-index: 1
}

/ Degradado animado, se expande para dejar sitio al frame /
.cg-card::before {
  transform: translateZ(0)
  background: conic-gradient(from 0deg, var(--colors))
  padding: var(--border-size)
  inset: calc(-1  var(--border-size))
  animation: cg-rotate var(--speed) linear infinite
}

/ Capa superior que cubre el centro dejando solo el borde visible /
.cg-card::after {
  inset: var(--border-size)
  background: var(--gap-color)
  border-radius: var(--radius)
}

Ejemplo completo: HTML CSS listo para pegar

Aquí un bloque completo, listo para pegar en un bloque HTML y añadir el CSS en el área de CSS adicional o en tu tema.

lt!-- HTML de la tarjeta --gt
ltdiv class=cg-cardgt
  ltdiv class=cg-card__contentgt
    lth3gtTítulo bonitolt/h3gt
    ltpgtUna descripción corta que encaje con el diseño.lt/pgt
  lt/divgt
lt/divgt
/ CSS completo (pegable en Customizer > Additional CSS) /
.cg-card {
  --border-size: 6px
  --radius: 14px
  --gap-color: #0f1720
  --speed: 5s
  --colors: #ff3cac 0deg, #784ba0 120deg, #2b86c5 240deg

  position: relative
  padding: 1.25rem
  border-radius: var(--radius)
  background: var(--gap-color)
  color: #fff
  overflow: visible
}

.cg-card__content { position: relative z-index: 2 }

/ Uso de dos pseudo-elementos para máxima compatibilidad /
.cg-card::before,
.cg-card::after { content:  position: absolute z-index: 1 border-radius: calc(var(--radius)   var(--border-size)) pointer-events: none }

/ degradado y animación /
.cg-card::before {
  inset: calc(-1  var(--border-size))
  background: conic-gradient(from 0deg, var(--colors))
  animation: cg-rotate var(--speed) linear infinite
}

/ tapa central /
.cg-card::after {
  inset: var(--border-size)
  background: var(--gap-color)
  border-radius: var(--radius)
}

/ animación /
@keyframes cg-rotate { to { transform: rotate(1turn) } }

@media (prefers-reduced-motion: reduce) {
  .cg-card::before { animation: none }
}

Integración específica en WordPress

Opción A: Customizer gt CSS adicional

  1. Ve a Apariencia gt Personalizar gt CSS adicional.
  2. Pega el CSS completo del ejemplo. Guarda y aplica la clase cg-card al bloque HTML o al contenedor que uses.

Opción B: Encolar un archivo CSS desde functions.php

Si prefieres añadir un archivo en tu tema hijo, crea un CSS y encola con este fragmento en functions.php del tema hijo.

/ functions.php (tema hijo) /
function mi_tema_enqueue_cg_card_styles() {
  wp_enqueue_style( cg-cards-style, get_stylesheet_directory_uri() . /css/cg-cards.css, array(), 1.0 )
}
add_action( wp_enqueue_scripts, mi_tema_enqueue_cg_card_styles )

Opción C: Bloque HTML en Gutenberg

  1. Añade un bloque HTML y pega el HTML de la tarjeta.
  2. Añade el CSS en el Personalizador o usa un plugin de CSS adicional.

Personalizaciones y variantes

Consideraciones de accesibilidad y rendimiento

Problemas comunes y soluciones rápidas

  1. La máscara no funciona en algún navegador: usa la versión con dos pseudo-elementos (antes explicada) que tiene mejor compatibilidad.
  2. El borde parece pixelado: aumenta el tamaño del pseudo-elemento o evita background-size pequeños también prueba transform: translateZ(0) para forzar composición por GPU.
  3. Animación no se reproduce en móvil: comprueba prefers-reduced-motion y que no haya reglas específicas del tema que sobrescriban las animaciones.
  4. El borde se solapa con otros elementos: usa z-index y asegúrate de que el contenedor tenga position: relative e isolation: isolate si es necesario.

Ejemplos avanzados (tips rápidos)

Fragmento opcional: iniciar animación al entrar en viewport (JS)

Si deseas que la animación empiece solo cuando la tarjeta entra en pantalla, puedes usar IntersectionObserver y añadir una clase que active la animación. Pega este JS en un archivo o en un bloque de scripts de tu tema (este código es mínimo).

// Activar animación al entrar en viewport
document.addEventListener(DOMContentLoaded, function () {
  const cards = document.querySelectorAll(.cg-card)
  if (!(IntersectionObserver in window)) {
    // Fallback: activar todas
    cards.forEach(c => c.classList.add(in-view))
    return
  }
  const io = new IntersectionObserver((entries) => {
    entries.forEach(e => {
      if (e.isIntersecting) {
        e.target.classList.add(in-view)
        // si quieres observar solo una vez:
        io.unobserve(e.target)
      }
    })
  }, { threshold: 0.2 })

  cards.forEach(c => io.observe(c))
})
/ En CSS activa animación solo cuando .in-view está presente /
.cg-card::before { animation: none }
.cg-card.in-view::before { animation: cg-rotate var(--speed) linear infinite }

Resumen

Crear tarjetas con bordes animados mediante conic-gradient es una técnica versátil, eficiente y altamente personalizable. Puedes implementarla desde el Customizer de WordPress, inyectando CSS, o encolando archivos en tu tema hijo. Usando pseudo-elementos y máscaras (o la alternativa de dos pseudo-elementos) obtendrás resultados consistentes. Ten en cuenta accesibilidad, prefer-reduced-motion y optimización para mantener buena experiencia en todas las plataformas.



Leave a Reply

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