Tutorial WordPress: Crear un grid de posts por categoría con CSS sin plugins

·

·

Introducción

Este tutorial explica, paso a paso y con todo lujo de detalles, cómo crear un grid (rejilla) de entradas de WordPress filtrado por categoría usando únicamente CSS y código en tu tema (sin plugins). Incluye un shortcode reutilizable, ejemplos de plantilla, el CSS necesario, recomendaciones de accesibilidad y rendimiento, y soluciones a problemas comunes. Todo el código necesario está listo para copiar y pegar.

Requisitos y buenas prácticas previas

1) Crear un shortcode PHP para mostrar la rejilla por categoría

El método más flexible es registrar un shortcode que acepte parámetros: categoría (slug o ID), número de posts, columnas, longitud del extracto, mostrar fecha, etc. Pega este código en el archivo functions.php del child theme o en un plugin de funcionalidades.

 ,           // slug o ID de la categoría
        posts => 6,
        cols => 3,
        excerpt => 18,
        show_date => 1,
        class => ,         // clases adicionales
    ), atts, cat_grid )

    // Preparar args para WP_Query
    query_args = array(
        posts_per_page => intval(atts[posts]),
        post_status => publish,
        ignore_sticky_posts => true,
    )

    // Soportar tanto slug (category_name) como ID (cat)
    if ( is_numeric( atts[cat] )  intval( atts[cat] ) > 0 ) {
        query_args[cat] = intval( atts[cat] )
    } elseif ( ! empty( atts[cat] ) ) {
        query_args[category_name] = sanitize_text_field( atts[cat] )
    }

    q = new WP_Query( query_args )

    // Construir clases para el grid
    cols = max(1, intval(atts[cols]))
    grid_class = cat-grid cols- . cols
    if ( ! empty( atts[class] ) ) {
        grid_class .=   . sanitize_html_class( atts[class] )
    }

    ob_start()

    if ( q->have_posts() ) {
        echo ltdiv class= . esc_attr( grid_class ) .  role=listgt
        while ( q->have_posts() ) {
            q->the_post()
            post_id = get_the_ID()
            title = get_the_title()
            permalink = get_permalink()
            has_thumb = has_post_thumbnail(post_id)
            excerpt = wp_trim_words( get_the_excerpt() ? get_the_excerpt() : get_the_content(), intval(atts[excerpt]), ... )
            date_html = atts[show_date] ? lttime datetime= . esc_attr( get_the_date( c ) ) .  class=post-dategt . esc_html( get_the_date() ) . lt/timegt : 

            echo ltarticle class=cat-grid-item role=listitemgt
            // Imagen destacada (con fallbacks)
            if ( has_thumb ) {
                thumb = get_the_post_thumbnail( post_id, medium, array(loading => lazy, alt => get_the_title(post_id)) )
                echo ltdiv class=cat-grid-mediagtlta href= . esc_url( permalink ) . gt . thumb . lt/agtlt/divgt
            } else {
                // Fallback: elemento vacío con clase para estilizar
                echo ltdiv class=cat-grid-media no-thumbgtlta href= . esc_url( permalink ) . gtltspan class=no-thumb-innergt . esc_html( title ) . lt/spangtlt/agtlt/divgt
            }

            // Contenido
            echo ltdiv class=cat-grid-bodygt
            echo lth3 class=cat-grid-titlegtlta href= . esc_url( permalink ) . gt . esc_html( title ) . lt/agtlt/h3gt
            if ( date_html ) {
                echo date_html
            }
            echo ltdiv class=cat-grid-excerptgt . wp_kses_post( wpautop( excerpt ) ) . lt/divgt
            echo lta class=cat-grid-more href= . esc_url( permalink ) . gtLeer máslt/agt
            echo lt/divgt

            echo lt/articlegt
        }
        echo lt/divgt // .cat-grid
    } else {
        echo ltp class=cat-grid-no-resultsgtNo hay entradas en esta categoría.lt/pgt
    }

    wp_reset_postdata()

    return ob_get_clean()
}
add_shortcode(cat_grid, wp_cat_grid_shortcode)
?>

Uso del shortcode

Ejemplos de uso dentro del editor de entradas/páginas o en bloques de texto:

2) CSS para el grid (responsivo y moderno)

Pega este CSS en el archivo style.css de tu tema, o en Apariencia → Personalizar → CSS adicional. Ajusta colores, fuentes y medidas según tu diseño.

/ Grid base /
.cat-grid {
  display: grid
  gap: 1.25rem
  margin: 0
  padding: 0
}

/ Columnas: clases .cols-1 .cols-2 .cols-3 .cols-4 /
.cat-grid.cols-1 { grid-template-columns: 1fr }
.cat-grid.cols-2 { grid-template-columns: repeat(2, 1fr) }
.cat-grid.cols-3 { grid-template-columns: repeat(3, 1fr) }
.cat-grid.cols-4 { grid-template-columns: repeat(4, 1fr) }

/ Responsive: adaptamos para móviles /
@media (max-width: 900px) {
  .cat-grid.cols-4, .cat-grid.cols-3 { grid-template-columns: repeat(2, 1fr) }
}
@media (max-width: 520px) {
  .cat-grid { grid-template-columns: 1fr }
}

/ Card /
.cat-grid-item {
  background: #ffffff
  border: 1px solid #e5e7eb
  display: flex
  flex-direction: column
  overflow: hidden
  border-radius: 6px
  transition: transform .18s ease, box-shadow .18s ease
}

/ Elevación en hover /
.cat-grid-item:hover {
  transform: translateY(-6px)
  box-shadow: 0 8px 24px rgba(16,24,40,0.08)
}

/ Media (imagen) - mantener ratio consistente /
.cat-grid-media {
  width: 100%
  aspect-ratio: 16/9 / si el navegador no soporta, sustituir por padding-top hack /
  overflow: hidden
  background: #f3f4f6
  display: block
}
.cat-grid-media img {
  width: 100%
  height: 100%
  object-fit: cover
  display: block
}

/ Fallback cuando no hay miniatura /
.cat-grid-media.no-thumb {
  display: flex
  align-items: center
  justify-content: center
  padding: 1rem
  color: #374151
  font-weight: 600
  text-align: center
}
.cat-grid-media.no-thumb .no-thumb-inner {
  display: block
}

/ Body: título, meta y excerpt /
.cat-grid-body {
  padding: 1rem
  display: flex
  flex-direction: column
  gap: 0.5rem
  flex: 1 1 auto
}
.cat-grid-title {
  margin: 0
  font-size: 1.05rem
  line-height: 1.3
}
.cat-grid-title a {
  color: #0f172a
  text-decoration: none
}
.cat-grid-title a:hover {
  color: #2563eb
  text-decoration: underline
}
.post-date {
  color: #6b7280
  font-size: 0.875rem
}

/ Excerpt /
.cat-grid-excerpt {
  color: #374151
  font-size: 0.95rem
  margin-top: 0.25rem
  flex: 1 1 auto
}

/ Botón Leer más /
.cat-grid-more {
  display: inline-block
  margin-top: 0.5rem
  color: #2563eb
  text-decoration: none
  font-weight: 600
}
.cat-grid-more:hover { text-decoration: underline }

/ Ajustes visuales menores /
.cat-grid-no-results { color: #6b7280 }

3) Alternativa: insertar el grid directamente en una plantilla (por ejemplo category.php)

Si prefieres mostrar la rejilla automáticamente en una plantilla (por ejemplo en archive de categoría), puedes usar una variante del loop dentro de tu archivo category.php o un template part. Ejemplo de código para insertar en una plantilla:

 cat->term_id,
    posts_per_page => 12,
    ignore_sticky_posts => true,
)
q = new WP_Query(args)
if (q->have_posts()) : ?>
    ltdiv class=cat-grid cols-3gt
    have_posts()) : q->the_post() ?>
        ltarticle class=cat-grid-itemgt
            ltdiv class=cat-grid-mediagt
                lta href=lt?php the_permalink() ?gtgtlt?php the_post_thumbnail(medium) ?gtlt/agt
            lt/divgt
            ltdiv class=cat-grid-bodygt
                lth3 class=cat-grid-titlegtlta href=lt?php the_permalink() ?gtgtlt?php the_title() ?gtlt/agtlt/h3gt
                ltdiv class=cat-grid-excerptgtlt?php echo wp_trim_words(get_the_excerpt(), 18, ...) ?gtlt/divgt
                lta class=cat-grid-more href=lt?php the_permalink() ?gtgtLeer máslt/agt
            lt/divgt
        lt/articlegt
    
    lt/divgt
    lt?php wp_reset_postdata() ?gt
lt?php endif ?gt

4) Mejoras opcionales y personalizaciones

  1. Lazy loading: WordPress 5.5 ya añade loading=lazy a las imágenes generadas por funciones como the_post_thumbnail. En el shortcode anterior ya se añade para compatibilidad.
  2. Regenerar miniaturas: si cambias tamaños de imagen, usa plugin Regenerate Thumbnails o comandos WP-CLI para regenerar.
  3. Paginación: si quieres paginar la lista en vez de limitar a X posts, reemplaza posts_per_page y añade paginación con get_query_var(paged) y functions como get_the_posts_pagination().
  4. Filtros por múltiples categorías: extiende query_args con tax_query para mostrar varias categorías o excluir alguna.
  5. Personalizar columnas dinámicamente: ya se soporta con el atributo cols del shortcode (cols=234).
  6. Cache: para tráfico alto, cachea la salida del shortcode con transients o sistema de cache de objetos.

5) Accesibilidad y SEO

6) Solución de problemas comunes

7) Ejemplo final: todo junto (uso básico)

1) Añade la función del shortcode en functions.php. 2) Añade el CSS en style.css. 3) Inserta en una página: [cat_grid cat=noticias posts=6 cols=3].

Conclusión

Con unas pocas líneas de PHP y CSS puedes obtener una rejilla de entradas por categoría completamente personalizada, ligera y sin plugins. El enfoque con shortcode facilita reutilizar la rejilla en cualquier página o plantilla el enfoque de plantilla integra la rejilla directamente en páginas de archivo. Ajusta estilos y estructura según tu diseño y aplica las recomendaciones de accesibilidad y rendimiento para obtener un resultado profesional.



Leave a Reply

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