Este tutorial explica, paso a paso y con todo lujo de detalles, cómo convertir las imágenes insertadas en las entradas de WordPress en elementos semánticos figure con su correspondiente figcaption estilizado. La solución que propongo es segura, compatible con imágenes enlazadas, respeta clases de alineación y aprovecha la información de la propia librería de medios (caption / alt). Incluye el código PHP que puedes añadir en tu theme (functions.php) o como plugin mu, y también el CSS para estilizar los figcaption.
Por qué hacerlo
Mejora semántica: figure figcaption indican al navegador y a los motores que la leyenda pertenece a la imagen.
Accesibilidad: ofrece un texto visible y mejor etiquetado para quienes usan tecnologías asistivas.
Control visual: facilita aplicar estilos consistentes (márgenes, fondo, tipografía, alineaciones).
SEO: ayudas a que los contenidos de imágenes estén mejor indexados.
Descripción general de la técnica
La idea principal es interceptar el contenido de la entrada con el filtro the_content, procesar el HTML y convertir cada ltimggt (o su enlace padre ltagt) en un ltfiguregt que contenga la imagen y un ltfigcaptiongt con la leyenda. La leyenda se obtiene, en este orden de prioridad:
La caption (extracto) del attachment en la biblioteca de medios (wp_get_attachment_caption / post_excerpt).
Si no existe, el atributo alt de la etiqueta ltimggt.
Si no hay nada, se omite el ltfigcaptiongt.
Consideraciones y buenas prácticas
No volver a procesar imágenes que ya están dentro de un ltfiguregt.
Mantener clases de alineación (alignleft / aligncenter / alignright) aplicándolas al ltfiguregt para que el tema se comporte igual.
Preservar atributos responsive (srcset, sizes) y el resto de atributos de la ltimggt.
Ejecutar el filtro solo en el front-end (evitar el admin, feeds, Ajax innecesario).
Evitar usar expresiones regulares para manipular HTML de forma compleja usaremos DOMDocument para mayor robustez.
Implementación PHP (recomendada)
Sigue este fragmento y pégalo en el functions.php de tu child theme o crea un pequeño plugin (MU plugin recomendado si quieres que se aplique aunque cambies de tema).
lt?php
/
Wrap post images in ltfiguregt with ltfigcaptiongt.
Put this code in your child themes functions.php or in a small plugin.
/
function wp_wrap_post_images_with_figures( content ) {
// Only run on front-end single posts/pages skip admin, feeds and previews.
if ( is_admin() is_feed() is_preview() ) {
return content
}
// Avoid breaking when content is empty
if ( empty( content ) ) {
return content
}
// Use internal errors to suppress warnings from malformed HTML
libxml_use_internal_errors( true )
dom = new DOMDocument()
// Ensure proper encoding
loaded = dom->loadHTML( mb_convert_encoding( content, HTML-ENTITIES, UTF-8 ), LIBXML_HTML_NOIMPLIED LIBXML_HTML_NODEFDTD )
if ( ! loaded ) {
libxml_clear_errors()
return content
}
imgs = dom->getElementsByTagName( img )
// Iterate backwards because NodeList is live
for ( i = imgs->length - 1 i >= 0 i-- ) {
img = imgs->item( i )
// Skip if no src attribute
src = img->getAttribute( src )
if ( empty( src ) ) {
continue
}
// If image already inside a , skip
ancestor = img->parentNode
in_figure = false
wrap_node = img // node to be wrapped (img or its parent anchor)
while ( ancestor ) {
if ( ancestor->nodeName === figure ) {
in_figure = true
break
}
if ( ancestor->nodeName === a ) {
// Prefer wrapping the anchor so link behavior remains intact
wrap_node = ancestor
}
ancestor = ancestor->parentNode
}
if ( in_figure ) {
continue
}
// Try to find attachment id from URL
attachment_id = attachment_url_to_postid( src )
// Prefer the attachment caption (WP stores caption in post_excerpt)
caption =
if ( attachment_id ) {
// wp_get_attachment_caption is available in modern WP versions
if ( function_exists( wp_get_attachment_caption ) ) {
caption = wp_get_attachment_caption( attachment_id )
}
if ( empty( caption ) ) {
att_post = get_post( attachment_id )
if ( att_post ! empty( att_post->post_excerpt ) ) {
caption = att_post->post_excerpt
}
}
}
// Fallback to alt attribute
if ( empty( caption ) ) {
caption = img->getAttribute( alt )
}
// Create a element
figure = dom->createElement( figure )
// Copy alignment classes from the image (if any)
img_class = img->getAttribute( class )
figure_classes = array( wp-caption ) // base class
if ( img_class ) {
// detect alignleft, alignright, aligncenter, alignnone
if ( preg_match( /(alignleftalignrightaligncenteralignnone)/, img_class, m ) ) {
figure_classes[] = m[1]
}
// Optionally preserve other classes if you want: uncomment next line
// figure_classes[] = img_class
}
figure->setAttribute( class, implode( , array_unique( figure_classes ) ) )
// Clone the node to wrap (deep clone to include children / attributes)
cloned = wrap_node->cloneNode( true )
figure->appendChild( cloned )
// Append figcaption if we have text
if ( ! empty( caption ) ) {
// Create figcaption element and ensure the text is treated as text
figcap = dom->createElement( figcaption )
figcap->setAttribute( class, wp-caption-text )
figcap->appendChild( dom->createTextNode( html_entity_decode( caption, ENT_QUOTES ENT_HTML5, UTF-8 ) ) )
figure->appendChild( figcap )
}
// Replace the original node with the new
wrap_node->parentNode->replaceChild( figure, wrap_node )
}
// Get the HTML back (without adding html/body)
html = dom->saveHTML()
libxml_clear_errors()
return html
}
add_filter( the_content, wp_wrap_post_images_with_figures, 20 )
?gt
Notas sobre el código PHP
El código usa DOMDocument en lugar de regex para manipular el HTML de forma más segura.
Se detecta y respeta cuando la imagen está dentro de un enlace ltagt: se envuelve el ltagt con la etiqueta ltfiguregt, preservando la URL del enlace y su comportamiento.
Se evita re-envolver imágenes que ya estén en ltfiguregt.
El orden de prioridad para la leyenda es: caption del attachment → post_excerpt → alt.
Se añade una clase base wp-caption y se aplica la clase de alineación si está presente en la imagen.
El código se ejecuta solo en front-end para no interferir con el editor o AJAX en admin.
CSS para estilizar figure y figcaption
A continuación tienes un CSS de ejemplo para que las figuras y las leyendas se vean bien en la mayoría de temas y sean responsive.
/ Estilos básicos para figure figcaption /
figure.wp-caption {
display: block
margin: 1.25em 0
line-height: 1.2
width: auto
}
figure.wp-caption img {
display: block
max-width: 100%
height: auto
margin: 0 auto
}
/ Alineaciones clásicas que muchos themes usan /
figure.wp-caption.alignleft {
float: left
margin-right: 1.25em
margin-left: 0
max-width: 50%
}
figure.wp-caption.alignright {
float: right
margin-left: 1.25em
margin-right: 0
max-width: 50%
}
figure.wp-caption.aligncenter {
margin-left: auto
margin-right: auto
text-align: center
}
/ Figcaption: tipografía y apariencia /
figure.wp-caption .wp-caption-text {
margin-top: 0.45em
color: #555
font-size: 0.95rem
line-height: 1.3
background: rgba(0,0,0,0.02)
padding: 0.35em 0.6em
border-radius: 3px
}
/ Ajustes para dispositivos pequeños /
@media (max-width: 640px) {
figure.wp-caption.alignleft,
figure.wp-caption.alignright {
float: none
display: block
margin-left: auto
margin-right: auto
max-width: 100%
}
}
Alternativas y casos especiales
Gutenberg (Block Editor)
El editor por bloques suele generar ya estructuras ltfigure class=wp-block-imagegt con ltfigcaptiongt. Para evitar conflictos, el script propuesto solo actúa en el contenido final y detecta si la imagen ya está dentro de un ltfiguregt — en ese caso no hace nada. Si necesitas un comportamiento específico para bloques, valora crear un bloque personalizado o aplicar estilos globales a .wp-block-image figcaption.
Galerías
Las galerías nativas de WP a menudo usan shortcodes que generan su propio marcado. Si quieres leyendas en cada imagen de la galería, revisa cómo tu tema renderiza la galería o procesa el HTML generado por el shortcode. Puedes adaptar el mismo enfoque con DOMDocument si la salida no usa figure.
Ten cuidado de no romper el diseño grid: quizá prefieras no aplicar float a figuras dentro de galerías y usar grid/flexbox para maquetar.
Evitar duplicados y compatibilidad
Si ya tienes plugins o el tema que insertan figuras, evita activar al mismo tiempo dos procesos que hagan exactamente lo mismo. Siempre prueba en un entorno de staging antes de activarlo en producción.
Cómo empaquetarlo como plugin MU (opcional)
Si prefieres que la funcionalidad no dependa del tema, crea un archivo PHP en wp-content/mu-plugins/ por ejemplo mu-figure-captions.php con cabecera mínima. Ejemplo de cabecera (usa en archivo real, sin lt?phpgt duplicado):
lt?php
/
Plugin Name: MU - Convert Images to Figures with Captions
Description: Envuelve imágenes del contenido en ltfiguregt y añade ltfigcaptiongt con la caption del attachment o el atributo alt.
Version: 1.0
Author: Tu Nombre
/
// (Pega aquí la función wp_wrap_post_images_with_figures y el add_filter)
?gt
Pruebas recomendadas antes de publicar
Realiza una copia de seguridad completa del sitio.
Prueba en un entorno de desarrollo o staging.
Verifica entradas que contengan: imágenes sueltas, imágenes dentro de enlace, imágenes con srcset, galerías y bloques de Gutenberg.
Comprueba que no se dupliquen captions ni que se introduzcan caracteres HTML inesperados.
Revisa la apariencia en móviles y escritorio.
Conclusión
Convertir las imágenes de tus posts en ltfiguregt con ltfigcaptiongt mejora la semántica, la accesibilidad y te permite controlar el estilo de las leyendas de forma centralizada. La solución presentada usa DOMDocument para manipular el HTML de forma segura, respeta enlaces y clases de alineación, y toma la caption desde la librería de medios cuando existe. Integra el PHP en tu theme o como plugin MU y añade el CSS propuesto para obtener un resultado visual consistente.
Leave a Reply