Introducción y objetivo
Este tutorial muestra, con todo lujo de detalles, cómo crear badges visibles de “Nuevo” y “Actualizado” en un sitio WordPress usando pseudo-elementos CSS. La idea es mantener el marcado HTML lo más limpio posible y delegar la presentación al CSS mediante ::before/::after, mientras que la lógica que determina si una entrada es nueva o ha sido actualizada se implementa en PHP (por ejemplo en functions.php). El resultado: badges ligeros, fáciles de mantener y compatibles con temas tradicionales y con muchos bloques.
Visión general del enfoque
- En PHP: añadir clases CSS (por ejemplo, is-new y is-updated) al array de clases del post (post_class) según la fecha de publicación y de modificación.
- En las plantillas: no es necesario añadir tags extra visibles el CSS generará el badge con pseudo-elementos y, para accesibilidad, incluiremos un texto visualmente oculto dentro del título (ejemplos en código).
- En CSS: usar ::before o ::after para dibujar los badges, posicionarlos sobre la miniatura o cerca del título, y aplicar estilos responsivos y animaciones suaves.
Paso 1 — Añadir clases dinámicas en PHP (functions.php)
El siguiente snippet añade las clases is-new y is-updated al array de clases del post. Ajusta las variables new_days y updated_days según tu criterio (por ejemplo 7 días para “Nuevo”, 3-7 días para “Actualizado”).
lt?php
// functions.php
add_filter( post_class, mi_agregar_clases_nuevo_actualizado, 10, 3 )
function mi_agregar_clases_nuevo_actualizado( classes, class, post_id ) {
post = get_post( post_id )
if ( ! post ) {
return classes
}
// Configuración: umbrales en días
new_days = 7 // considera Nuevo publicaciones de los últimos 7 días
updated_days = 7 // considera Actualizado modificaciones en los últimos 7 días
// Fechas en timestamp respetando zona horaria de WP
now = current_time( timestamp )
published = get_post_time( U, true, post )
modified = get_post_modified_time( U, true, post )
// Si la publicación es reciente
if ( ( now - published ) <= ( new_days DAY_IN_SECONDS ) ) {
classes[] = is-new
}
// Si ha sido modificada y la modificación es reciente
if ( modified > published ( now - modified ) <= ( updated_days DAY_IN_SECONDS ) ) {
classes[] = is-updated
}
return classes
}
?gt
Notas:
- La función se aplica a cualquier post type que use post_class (entradas, páginas, productos si el tema/plantilla usa post_class).
- Si quieres restringirlo a post type específico, añade una comprobación con get_post_type( post_id ).
Paso 2 — Marcado en las plantillas (loop / entry)
Lo ideal es no introducir elementos visibles extra sólo para el badge. No obstante, para accesibilidad añadiremos un texto escondido dentro del título para que lectores de pantalla anuncien “Nuevo” o “Actualizado”. Aquí un ejemplo de fragmento típico de plantilla (loop) que incluye un span con clase screen-reader-text. El span debe estar presente para que el contenido del pseudo-elemento no sea la única pista para lectores de pantalla.
ltarticle id=post-lt?php the_ID() ?gtSi tu tema ya tiene una clase para esconder texto a los lectores visuales (screen-reader-text), úsala. Si no, añade una regla CSS para ocultarla visualmente pero mantenerla accesible desde el lector de pantalla (ejemplo más abajo dentro de CSS).
Paso 3 — Estilos con pseudo-elementos CSS
Usaremos pseudo-elementos para no tocar el DOM visual. Asegúrate de que el contenedor del post tenga position: relative para poder posicionar el badge con position: absolute. A continuación un conjunto de estilos básicos y variantes:
/ Base: asegurar contexto de posicionamiento / .article, .post, article { position: relative / si tu tema ya tiene layout distinto, apunta al selector correcto (por ejemplo .post, .entry) / } / Badge Nuevo sobre el título (esquina superior derecha) / .post.is-new .entry-title { position: relative / para que ::before se posicione respecto al título / } .post.is-new .entry-title::before { content: Nuevo position: absolute top: -0.5rem right: -0.5rem background: #e53935 / rojo / color: #fff font-weight: 700 font-size: 0.65rem padding: 0.35rem 0.6rem border-radius: 0.25rem text-transform: uppercase box-shadow: 0 2px 6px rgba(0,0,0,0.12) transform: translateY(-50%) line-height: 1 white-space: nowrap z-index: 5 } / Badge Actualizado con otro color / .post.is-updated .entry-title::before { content: Actualizado position: absolute top: -0.5rem right: -0.5rem background: #f57c00 / naranja / color: #fff font-weight: 700 font-size: 0.62rem padding: 0.3rem 0.6rem border-radius: 0.25rem text-transform: uppercase box-shadow: 0 2px 6px rgba(0,0,0,0.12) z-index: 5 } / Variante: badge sobre la miniatura/imagen destacada / .post .post-thumbnail { position: relative } .post.is-new .post-thumbnail::after, .post.is-updated .post-thumbnail::after { content: attr(data-badge) / si quieres contenido dinámico con data-, alternativa a content literal / position: absolute top: 0.5rem left: 0.5rem background: rgba(0,0,0,0.65) color: #fff padding: 0.35rem 0.5rem border-radius: 0.25rem font-size: 0.7rem font-weight: 700 z-index: 6 } / Transiciones suaves (pero respetar preferencias de movimiento) / .post .entry-title::before, .post .post-thumbnail::after { transition: transform 0.18s ease, opacity 0.18s ease } / Reducir tamaño en pantallas pequeñas / @media (max-width: 480px) { .post.is-new .entry-title::before, .post.is-updated .entry-title::before { font-size: 0.55rem padding: 0.25rem 0.45rem top: -0.4rem right: -0.4rem } } / Respetar usuarios con preferencia por reducir movimiento / @media (prefers-reduced-motion: reduce) { .post .entry-title::before, .post .post-thumbnail::after { transition: none } } / Ejemplo de .screen-reader-text (si tu tema no la define) / .screen-reader-text { position: absolute width: 1px height: 1px padding: 0 margin: -1px overflow: hidden clip: rect(0,0,0,0) white-space: nowrap border: 0 }Notas sobre el CSS:
- content: Nuevo / Actualizado es simple y directo. Si necesitas traducciones, genera la clase en PHP y usa reglas CSS con content en pseudo-elemento o bien incluye el texto accesible en el DOM (recomendado para i18n).
- Si usas content: attr(data-badge), tendrás que generar el atributo data-badge en el markup del thumbnail desde PHP/plantilla.
- Asegúrate de que los badges no solapen elementos importantes (prueba con distintos anchos y tamaños de imagen).
Variantes avanzadas y ejemplos
Badge con “ribbon” o triángulo
/ Ribbon simple - esquina superior derecha /
.post.is-new .entry-title::before {
content: Nuevo
position: absolute
top: 0
right: 0
padding: 0.35rem 0.9rem
background: #e53935
color: #fff
transform: rotate(10deg) translate(6px, -6px)
box-shadow: 0 2px 6px rgba(0,0,0,0.12)
}
Usar data-attributes para contenido dinámico (ejemplo PHP CSS)
Si prefieres no codificar el texto en CSS (mejor para traducciones), añade un atributo data-badge desde PHP y usa content: attr(data-badge) en CSS.
lt?php
// En la plantilla, al output de la miniatura:
badge =
if ( in_array( is-new, get_post_class( , null ) ) ) {
badge = Nuevo
} elseif ( in_array( is-updated, get_post_class( , null ) ) ) {
badge = Actualizado
}
?gt
ltdiv class=post-thumbnail
Compatibilidad con WooCommerce y otros post types
El mismo filtro post_class funciona para productos si el código de la plantilla usa post_class o product_class. Si WooCommerce no usa post_class en tu plantilla, añade la lógica en la plantilla de archivo de productos o usa hooks específicos del plugin para inyectar clases o atributos.
// Ejemplo: limitar a post_type product
add_filter( post_class, clases_producto_nuevo_actualizado, 10, 3 )
function clases_producto_nuevo_actualizado( classes, class, post_id ) {
if ( product !== get_post_type( post_id ) ) {
return classes
}
// ... lógica igual que antes ...
return classes
}
Pruebas y depuración
- Crea entradas con fecha actual y fechas pasadas para comprobar el umbral de “Nuevo”.
- Modifica la entrada (cambia contenido y guarda) y comprueba el badge “Actualizado”.
- En entornos locales puedes forzar fechas con WP-CLI o editando la fecha de publicación/modificación desde el editor.
- Comprueba en móvil y en pantallas pequeñas que el badge no ocultE información importante.
- Valida con un lector de pantalla que el texto accesible (screen-reader-text) se anuncia correctamente.
Consideraciones de rendimiento y accesibilidad
- Rendimiento: la lógica añade poca carga (simple cálculo de timestamps). Evita consultas adicionales por post dentro del loop.
- Accesibilidad: los pseudo-elementos no son leídos por lectores de pantalla. Por eso la práctica recomendada es incluir una porción de texto accesible (ej. screen-reader-text) en el HTML que anuncie “Nuevo” o “Actualizado”.
- SEO: los badges son puramente presentación no alteran el contenido principal ni el HTML visible importante.
- Internacionalización: si tu sitio es multilenguaje, genera la cadena del badge en PHP usando funciones de traducción (esc_html__ / esc_attr__ / __) y pásala al data-attribute o imprime el span traducido.
Resumen práctico
- En functions.php: añade clases dinámicas (is-new / is-updated) con el filtro post_class basándote en las fechas.
- En plantillas: mantén el DOM limpio añade un pequeño span con clase de lector de pantalla para accesibilidad cuando sea necesario.
- En CSS: crea los badges con ::before / ::after, posicionándolos donde convenga (título, miniatura) y ofreciendo variantes responsivas.
- Prueba y ajusta umbrales y posición para que los badges no interfieran con la experiencia de lectura.
Ejemplo final — flujo mínimo completo
A continuación resume el flujo mínimo: PHP que añade clases, plantilla que muestra el título y thumbnail, y CSS que dibuja el badge.
/ 1) functions.php (añadir clases): ya mostrado anteriormente / lt?php // ... código de mi_agregar_clases_nuevo_actualizado ... ?gt
ltarticle id=post-lt?php the_ID() ?gt/ 3) CSS (ejemplo mínimo de estilos) / .article, .post, article { position: relative } .post .post-thumbnail { position: relative } / Badge desde data-badge / .post .post-thumbnail::after { content: attr(data-badge) position: absolute top: 0.5rem left: 0.5rem background: #e53935 color: #fff padding: 0.3rem 0.55rem border-radius: 0.25rem font-size: 0.7rem font-weight: 700 z-index: 6 }Con esto tienes una solución completa, accesible y personalizable para mostrar badges de “Nuevo” o “Actualizado” en WordPress usando pseudo-elementos CSS y una mínima lógica en PHP. Ajusta colores, posiciones y umbrales según la estética y necesidades de tu sitio.
Leave a Reply