Introducción
Este tutorial muestra, con todo lujo de detalles, cómo personalizar el bloque de navegación post anterior / siguiente en WordPress. Incluye varias rutas: modificar la plantilla PHP clásica, crear estilos o variaciones para el bloque de Gutenberg (core/post-navigation), usar filtros para reescribir el HTML generado por el bloque, añadir miniaturas, iconos SVG, atributos rel para SEO y buenas prácticas de accesibilidad y rendimiento.
Enfoques posibles (resumen)
- Plantilla PHP clásica: editar single.php o crear una función en functions.php y llamar desde la plantilla.
- Gutenberg – variación o estilo de bloque: registrar un estilo para core/post-navigation o modificar su salida con filtros.
- Filtro render_block: interceptar la salida del bloque y transformarla (útil si el sitio usa bloques en lugar de PHP puro).
Antes de empezar: recomendaciones
- Trabaja en un child theme o en un plugin de utilidades para no perder cambios con actualizaciones.
- Escapa todas las salidas (esc_url, esc_html, esc_attr) en PHP.
- Prueba la accesibilidad con lector de pantalla y verifica el contraste de colores.
- Opta por lazy-loading en imágenes y usa tamaños de imagen adecuados para rendimiento.
1) Implementación en plantilla PHP (ejemplo completo)
Ejemplo de función que muestra navegación con miniaturas, títulos, texto para lectores de pantalla, rel=prev/next y manejo condicional si no existe anterior o siguiente:
lt?php
function mi_post_nav_bonito() {
// Solo en single posts
if ( ! is_singular( post ) ) {
return
}
prev = get_previous_post()
next = get_next_post()
// Si no hay ninguno, no hacemos nada
if ( ! prev ! next ) {
return
}
echo ltnav class=mi-post-nav role=navigation aria-label=Navegación entre entradasgt
if ( prev ) {
prev_url = esc_url( get_permalink( prev ) )
prev_title = esc_html( get_the_title( prev ) )
thumb = get_the_post_thumbnail( prev->ID, array(120,120), array(loading =gt lazy, alt =gt prev_title) )
// Rel prev y enlace semántico
echo ltdiv class=nav-item nav-prevgt
echo lta href=. prev_url . rel=prev aria-label=Entrada anterior: . esc_attr( prev_title ) .gt
echo ltspan class=nav-thumbgt. thumb .lt/spangt
echo ltspan class=nav-metagtltspan class=nav-labelgtAnteriorlt/spangtltspan class=nav-titlegt. prev_title .lt/spangtlt/spangt
echo lt/agt
echo lt/divgt
}
if ( next ) {
next_url = esc_url( get_permalink( next ) )
next_title = esc_html( get_the_title( next ) )
thumb = get_the_post_thumbnail( next->ID, array(120,120), array(loading =gt lazy, alt =gt next_title) )
echo ltdiv class=nav-item nav-nextgt
echo lta href=. next_url . rel=next aria-label=Entrada siguiente: . esc_attr( next_title ) .gt
echo ltspan class=nav-metagtltspan class=nav-labelgtSiguientelt/spangtltspan class=nav-titlegt. next_title .lt/spangtlt/spangt
echo ltspan class=nav-thumbgt. thumb .lt/spangt
echo lt/agt
echo lt/divgt
}
echo lt/navgt
}
?gt
Uso: coloca la llamada mi_post_nav_bonito() donde quieras en single.php (por ejemplo, al final del contenido) o añádela a una plantilla parcial.
CSS sugerido para la plantilla (estilos base y responsive)
.mi-post-nav{
display:flex
justify-content:space-between
gap:1rem
align-items:center
margin:2rem 0
}
.mi-post-nav .nav-item{
flex:1 1 45%
background:#fff
border:1px solid #e1e1e1
padding:0.75rem
border-radius:8px
display:flex
align-items:center
text-decoration:none
}
.mi-post-nav .nav-item a{
display:flex
align-items:center
gap:0.75rem
color:inherit
text-decoration:none
}
.mi-post-nav .nav-thumb img{
width:72px
height:72px
object-fit:cover
border-radius:6px
display:block
}
.mi-post-nav .nav-meta{ display:flex flex-direction:column }
.mi-post-nav .nav-label{ font-size:0.8rem color:#666 }
.mi-post-nav .nav-title{ font-weight:700 color:#222 }
/ Responsive: apila en móviles /
@media (max-width:700px){
.mi-post-nav{ flex-direction:column }
.mi-post-nav .nav-item{ width:100% }
}
/ Clase para ocultar visualmente pero dejar accesible para SR /
.visually-hidden{
position:absolute!important
height:1pxwidth:1px
overflow:hidden
clip:rect(1px,1px,1px,1px)
white-space:nowrap
}
2) Personalizar el bloque de Gutenberg (core/post-navigation)
Si tu sitio usa el editor de bloques para componer la plantilla single, puedes registrar un nuevo estilo de bloque o interceptar la salida del bloque con filtros.
Registrar un estilo de bloque (functions.php)
Con register_block_style añades una opción en el editor que aplica una clase CSS específica al bloque.
lt?php
function registrar_estilos_post_navigation() {
if ( function_exists( register_block_style ) ) {
register_block_style( core/post-navigation, array(
name =gt mi-nav-cards,
label =gt Navegación con tarjetas
) )
}
}
add_action( init, registrar_estilos_post_navigation )
?gt
Luego en tu CSS (o enqueue para bloques) defines las reglas para .wp-block-post-navigation.is-style-mi-nav-cards
.wp-block-post-navigation.is-style-mi-nav-cards {
/ estilos similares a los mostrados anteriormente /
display:flex
gap:1rem
align-items:center
}
.wp-block-post-navigation.is-style-mi-nav-cards .wp-block-post-navigation-link { / ... / }
Modificar la salida del bloque con render_block
Este patrón permite interceptar el HTML que genera el bloque y reescribirlo para incluir miniaturas, SVG o atributos extra.
lt?php
add_filter( render_block, mi_custom_render_post_navigation, 10, 2 )
function mi_custom_render_post_navigation( block_content, block ) {
if ( isset( block[blockName] ) core/post-navigation === block[blockName] ) {
// Modificamos sólo si estamos en single
if ( is_singular( post ) ) {
// Ejemplo simple: añadimos un contenedor con clase y un atributo aria adicional
block_content = str_replace( class=wp-block-post-navigation, class=wp-block-post-navigation mi-post-nav-block role=navigation aria-label=Navegación entre entradas, block_content )
// O más avanzado: parsear HTML y reemplazar el enlace por uno con miniatura (requiere DOMDocument o regex cuidadoso)
}
}
return block_content
}
?gt
3) Añadir miniaturas al bloque (estrategia)
core/post-navigation no incluye por defecto miniaturas en todas las configuraciones. Para insertarlas desde PHP puedes usar render_block y, mediante DOMDocument o patrones, inyectar el HTML con get_the_post_thumbnail( id, thumbnail ). Otra alternativa es crear un bloque personalizado que renderice exactamente el HTML que deseas (más trabajo, pero control total).
Ejemplo simplificado: inyectar thumbnail mediante simple replace
lt?php
add_filter( render_block, mi_inyectar_thumb_post_nav, 10, 2 )
function mi_inyectar_thumb_post_nav( block_content, block ) {
if ( isset( block[blockName] ) core/post-navigation === block[blockName] is_singular( post ) ) {
// Atención: esto es una aproximación en producción usar DOMDocument o un parser robusto
// Reemplazar placeholder imaginario y si existieran,
// o buscar los enlaces y añadir antes la miniatura.
// Aquí mostramos lógica conceptual.
}
return block_content
}
?gt
Si necesitas insertar miniaturas de forma robusta, construir un bloque personalizado (o usar server-side render con register_block_type) es la opción más segura.
4) Accesibilidad y SEO
- Rel prev/next: añade rel=prev y rel=next en los enlaces para que los buscadores entiendan la relación.
- Etiquetas ARIA: role=navigation y aria-label descriptivo (por ejemplo Navegación entre entradas).
- Textos para lectores de pantalla: incluir span con clase visually-hidden para indicar Entrada anterior: o Entrada siguiente: si el diseño solo muestra iconos.
- Enfoque y teclado: asegúrate de que los enlaces sean focusables y el estilo :focus sea visible.
- Contraste: colores legibles y contraste mínimo según WCAG.
5) Icons y microinteracciones
Usar SVG inline dentro de los enlaces proporciona iconos nítidos y control de color con CSS. Ejemplo de inserción simple:
ltsvg width=20 height=20 viewBox=0 0 24 24 aria-hidden=true focusable=falsegt ltpath d=M15.41 7.41L14 6l-6 6 6 6 1.41-1.41L10.83 12zgtlt/pathgt lt/svggt
Colócalo antes del título en anterior (flecha izquierda) y después del título en siguiente (flecha derecha). Controla el color con fill:currentColor para heredar el color del enlace.
6) Ejemplo completo y compacto (plantilla con todo integrado)
Ejemplo que combina miniatura, SVG, rel, lazy loading y clases semánticas. Inserta esto en functions.php o en plantilla parcial según prefieras.
lt?php
function mi_post_nav_completo() {
if ( ! is_singular( post ) ) return
prev = get_previous_post()
next = get_next_post()
if ( ! prev ! next ) return
echo ltnav class=mi-post-nav role=navigation aria-label=Navegación entre entradasgt
if ( prev ) {
url = esc_url( get_permalink( prev ) )
title = esc_attr( get_the_title( prev ) )
thumb = get_the_post_thumbnail( prev->ID, thumbnail, array(loading =gt lazy, alt =gt title ) )
echo ltdiv class=nav-item nav-prevgt
echo lta href=. url . rel=prev aria-label=Entrada anterior: . title .gt
echo ltspan class=nav-thumbgt. thumb .lt/spangt
echo ltspan class=nav-contentgt
echo ltsvg width=18 height=18 viewBox=0 0 24 24 aria-hidden=true focusable=falsegtltpath d=M15.41 7.41L14 6l-6 6 6 6 1.41-1.41L10.83 12zgtlt/pathgtlt/svggt
echo ltspan class=nav-labelgtAnteriorlt/spangt
echo ltspan class=nav-titlegt. esc_html( get_the_title( prev ) ) .lt/spangt
echo lt/spangt
echo lt/agt
echo lt/divgt
}
if ( next ) {
url = esc_url( get_permalink( next ) )
title = esc_attr( get_the_title( next ) )
thumb = get_the_post_thumbnail( next->ID, thumbnail, array(loading =gt lazy, alt =gt title ) )
echo ltdiv class=nav-item nav-nextgt
echo lta href=. url . rel=next aria-label=Entrada siguiente: . title .gt
echo ltspan class=nav-contentgt
echo ltspan class=nav-labelgtSiguientelt/spangt
echo ltspan class=nav-titlegt. esc_html( get_the_title( next ) ) .lt/spangt
echo ltsvg width=18 height=18 viewBox=0 0 24 24 aria-hidden=true focusable=falsegtltpath d=M8.59 16.59L13.17 12 8.59 7.41 10 6l6 6-6 6zgtlt/pathgtlt/svggt
echo lt/spangt
echo ltspan class=nav-thumbgt. thumb .lt/spangt
echo lt/agt
echo lt/divgt
}
echo lt/navgt
}
?gt
7) Buenas prácticas y consideraciones finales
- Usa un child theme o plugin para cambios que afecten a functions.php o estilos globales.
- Evita imágenes muy pesadas y sirve tamaños adecuados mediante las funciones de imagen de WP.
- Prueba en diferentes dispositivos y navegadores revisa enfoque de teclado y lector de pantalla.
- Si modificas bloques de Gutenberg, documenta la modificación para editores del sitio (qué estilos hay disponibles y cómo activarlos).
- Usa control de versiones (Git) para mantener un historial de cambios en plantillas y funciones.
Resumen práctico
Para mayor control: crea una función PHP que genere exactamente el HTML que quieras y úsala en la plantilla. Para integración con el editor de bloques: registra un estilo de bloque o intercepta la salida con render_block. Para personalizaciones profundas (miniaturas, microdiseño, lógica condicional): lo más robusto es un bloque personalizado o server-side render. En todos los casos, prioriza accesibilidad, SEO y rendimiento.
Leave a Reply