I’ll build this as a strong content-archive.php template part for your RX Theme, with safe WordPress functions, SEO/schema-friendly markup, accessibility, thumbnails, categories, meta, excerpt, reading time fallback, comments, tags, and hook points for future expansion.
Below is an advanced template-parts/content/content-archive.php file for your RX Theme.
It is made for archive pages like blog archive, category archive, tag archive, author archive, search results, and date archive.
Create/update this file:
rx-theme/template-parts/content/content-archive.php
<?php
/**
* Template part for displaying posts in archive loops.
*
* File: template-parts/content/content-archive.php
*
* Used by:
* - archive.php
* - category.php
* - tag.php
* - author.php
* - search.php
* - home.php
* - index.php
*
* @package RX_Theme
*/
defined( 'ABSPATH' ) || exit;
/**
* ------------------------------------------------------------
* Basic Post Data
* ------------------------------------------------------------
*/
$post_id = get_the_ID();
$post_type = get_post_type( $post_id );
$permalink = get_permalink( $post_id );
$title = get_the_title( $post_id );
$excerpt = get_the_excerpt( $post_id );
$author_id = get_the_author_meta( 'ID' );
$author_name = get_the_author();
$author_url = get_author_posts_url( $author_id );
$published_time = get_the_date( DATE_W3C, $post_id );
$modified_time = get_the_modified_date( DATE_W3C, $post_id );
$comment_count = get_comments_number( $post_id );
$is_sticky = is_sticky( $post_id );
$has_thumbnail = has_post_thumbnail( $post_id );
/**
* ------------------------------------------------------------
* Theme Option / Filter Defaults
* ------------------------------------------------------------
*/
$rx_show_thumbnail = apply_filters( 'rx_theme_archive_show_thumbnail', true );
$rx_show_category = apply_filters( 'rx_theme_archive_show_category', true );
$rx_show_author = apply_filters( 'rx_theme_archive_show_author', true );
$rx_show_date = apply_filters( 'rx_theme_archive_show_date', true );
$rx_show_modified_date = apply_filters( 'rx_theme_archive_show_modified_date', false );
$rx_show_comments = apply_filters( 'rx_theme_archive_show_comments', true );
$rx_show_excerpt = apply_filters( 'rx_theme_archive_show_excerpt', true );
$rx_show_tags = apply_filters( 'rx_theme_archive_show_tags', true );
$rx_show_reading_time = apply_filters( 'rx_theme_archive_show_reading_time', true );
$rx_show_read_more = apply_filters( 'rx_theme_archive_show_read_more', true );
$rx_show_schema = apply_filters( 'rx_theme_archive_show_schema', true );
$rx_thumbnail_size = apply_filters( 'rx_theme_archive_thumbnail_size', 'medium_large' );
$rx_excerpt_length = apply_filters( 'rx_theme_archive_excerpt_length', 28 );
$rx_read_more_text = apply_filters( 'rx_theme_archive_read_more_text', __( 'Read More', 'rx-theme' ) );
/**
* ------------------------------------------------------------
* Fallback Reading Time
* ------------------------------------------------------------
*/
if ( ! function_exists( 'rx_theme_get_reading_time' ) ) {
/**
* Get estimated reading time.
*
* @param int $post_id Post ID.
* @return string
*/
function rx_theme_get_reading_time( $post_id ) {
$content = get_post_field( 'post_content', $post_id );
$word_count = str_word_count( wp_strip_all_tags( $content ) );
$minutes = max( 1, ceil( $word_count / 200 ) );
return sprintf(
/* translators: %s: reading time in minutes */
_n( '%s min read', '%s min read', $minutes, 'rx-theme' ),
number_format_i18n( $minutes )
);
}
}
/**
* ------------------------------------------------------------
* Fallback Trimmed Excerpt
* ------------------------------------------------------------
*/
if ( ! function_exists( 'rx_theme_get_trimmed_excerpt' ) ) {
/**
* Get custom trimmed excerpt.
*
* @param int $post_id Post ID.
* @param int $length Word length.
* @return string
*/
function rx_theme_get_trimmed_excerpt( $post_id, $length = 28 ) {
$manual_excerpt = get_the_excerpt( $post_id );
if ( ! empty( $manual_excerpt ) ) {
return wp_trim_words( $manual_excerpt, $length, '...' );
}
$content = get_post_field( 'post_content', $post_id );
$content = strip_shortcodes( $content );
$content = wp_strip_all_tags( $content );
return wp_trim_words( $content, $length, '...' );
}
}
/**
* ------------------------------------------------------------
* Classes
* ------------------------------------------------------------
*/
$article_classes = array(
'rx-archive-card',
'rx-content-card',
'rx-post-card',
'rx-post-card--archive',
'post-' . absint( $post_id ),
'post-type-' . sanitize_html_class( $post_type ),
);
if ( $has_thumbnail ) {
$article_classes[] = 'has-post-thumbnail';
} else {
$article_classes[] = 'no-post-thumbnail';
}
if ( $is_sticky ) {
$article_classes[] = 'is-sticky';
}
if ( is_search() ) {
$article_classes[] = 'is-search-result';
}
if ( is_category() ) {
$article_classes[] = 'is-category-archive';
}
if ( is_tag() ) {
$article_classes[] = 'is-tag-archive';
}
if ( is_author() ) {
$article_classes[] = 'is-author-archive';
}
if ( is_date() ) {
$article_classes[] = 'is-date-archive';
}
$article_classes = apply_filters( 'rx_theme_archive_article_classes', $article_classes, $post_id );
/**
* ------------------------------------------------------------
* Category Data
* ------------------------------------------------------------
*/
$categories = get_the_category( $post_id );
$primary_category = ! empty( $categories ) && ! is_wp_error( $categories ) ? $categories[0] : null;
/**
* ------------------------------------------------------------
* Schema Data
* ------------------------------------------------------------
*/
$schema_attrs = '';
if ( $rx_show_schema ) {
$schema_attrs = ' itemscope itemtype="https://schema.org/BlogPosting"';
}
?>
<article id="post-<?php the_ID(); ?>" <?php post_class( $article_classes ); ?><?php echo $schema_attrs; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?>>
<?php
/**
* Hook before archive card.
*/
do_action( 'rx_theme_before_archive_card', $post_id );
?>
<?php if ( $rx_show_schema ) : ?>
<meta itemprop="mainEntityOfPage" content="<?php echo esc_url( $permalink ); ?>">
<meta itemprop="datePublished" content="<?php echo esc_attr( $published_time ); ?>">
<meta itemprop="dateModified" content="<?php echo esc_attr( $modified_time ); ?>">
<?php endif; ?>
<?php if ( $rx_show_thumbnail && $has_thumbnail ) : ?>
<div class="rx-archive-card__media">
<a
class="rx-archive-card__thumbnail-link"
href="<?php echo esc_url( $permalink ); ?>"
aria-label="<?php echo esc_attr( sprintf( __( 'Read full article: %s', 'rx-theme' ), $title ) ); ?>"
>
<?php
the_post_thumbnail(
$rx_thumbnail_size,
array(
'class' => 'rx-archive-card__thumbnail',
'loading' => 'lazy',
'decoding' => 'async',
'alt' => esc_attr( $title ),
'itemprop' => $rx_show_schema ? 'image' : '',
)
);
?>
</a>
<?php if ( $is_sticky ) : ?>
<span class="rx-archive-card__badge rx-archive-card__badge--sticky">
<?php esc_html_e( 'Featured', 'rx-theme' ); ?>
</span>
<?php endif; ?>
<?php if ( $rx_show_category && $primary_category ) : ?>
<a
class="rx-archive-card__badge rx-archive-card__badge--category"
href="<?php echo esc_url( get_category_link( $primary_category->term_id ) ); ?>"
>
<?php echo esc_html( $primary_category->name ); ?>
</a>
<?php endif; ?>
</div>
<?php endif; ?>
<div class="rx-archive-card__body">
<?php if ( $rx_show_category && ! empty( $categories ) && ! is_wp_error( $categories ) ) : ?>
<div class="rx-archive-card__categories" aria-label="<?php esc_attr_e( 'Post categories', 'rx-theme' ); ?>">
<?php foreach ( array_slice( $categories, 0, 3 ) as $category ) : ?>
<a
class="rx-archive-card__category-link"
href="<?php echo esc_url( get_category_link( $category->term_id ) ); ?>"
>
<?php echo esc_html( $category->name ); ?>
</a>
<?php endforeach; ?>
</div>
<?php endif; ?>
<header class="rx-archive-card__header">
<?php
/**
* Hook before archive title.
*/
do_action( 'rx_theme_before_archive_title', $post_id );
?>
<?php if ( $title ) : ?>
<h2 class="rx-archive-card__title" itemprop="<?php echo $rx_show_schema ? esc_attr( 'headline' ) : ''; ?>">
<a href="<?php echo esc_url( $permalink ); ?>" rel="bookmark">
<?php echo esc_html( $title ); ?>
</a>
</h2>
<?php else : ?>
<h2 class="rx-archive-card__title rx-archive-card__title--empty">
<a href="<?php echo esc_url( $permalink ); ?>" rel="bookmark">
<?php esc_html_e( 'Untitled Post', 'rx-theme' ); ?>
</a>
</h2>
<?php endif; ?>
<?php
/**
* Hook after archive title.
*/
do_action( 'rx_theme_after_archive_title', $post_id );
?>
<div class="rx-archive-card__meta">
<?php if ( $rx_show_author ) : ?>
<span class="rx-archive-card__meta-item rx-archive-card__meta-author" itemprop="<?php echo $rx_show_schema ? esc_attr( 'author' ) : ''; ?>" itemscope itemtype="https://schema.org/Person">
<span class="rx-archive-card__meta-label">
<?php esc_html_e( 'By', 'rx-theme' ); ?>
</span>
<a href="<?php echo esc_url( $author_url ); ?>" class="rx-archive-card__author-link" itemprop="url">
<span itemprop="name"><?php echo esc_html( $author_name ); ?></span>
</a>
</span>
<?php endif; ?>
<?php if ( $rx_show_date ) : ?>
<span class="rx-archive-card__meta-item rx-archive-card__meta-date">
<span class="screen-reader-text">
<?php esc_html_e( 'Published on', 'rx-theme' ); ?>
</span>
<a href="<?php echo esc_url( get_day_link( get_the_time( 'Y' ), get_the_time( 'm' ), get_the_time( 'd' ) ) ); ?>">
<time datetime="<?php echo esc_attr( $published_time ); ?>">
<?php echo esc_html( get_the_date() ); ?>
</time>
</a>
</span>
<?php endif; ?>
<?php if ( $rx_show_modified_date && get_the_modified_time( 'U' ) !== get_the_time( 'U' ) ) : ?>
<span class="rx-archive-card__meta-item rx-archive-card__meta-modified">
<?php esc_html_e( 'Updated:', 'rx-theme' ); ?>
<time datetime="<?php echo esc_attr( $modified_time ); ?>">
<?php echo esc_html( get_the_modified_date() ); ?>
</time>
</span>
<?php endif; ?>
<?php if ( $rx_show_reading_time ) : ?>
<span class="rx-archive-card__meta-item rx-archive-card__meta-reading-time">
<?php echo esc_html( rx_theme_get_reading_time( $post_id ) ); ?>
</span>
<?php endif; ?>
<?php if ( $rx_show_comments && comments_open( $post_id ) ) : ?>
<span class="rx-archive-card__meta-item rx-archive-card__meta-comments">
<a href="<?php echo esc_url( get_comments_link( $post_id ) ); ?>">
<?php
printf(
esc_html(
_n(
'%s Comment',
'%s Comments',
$comment_count,
'rx-theme'
)
),
esc_html( number_format_i18n( $comment_count ) )
);
?>
</a>
</span>
<?php endif; ?>
</div>
</header>
<?php if ( $rx_show_excerpt ) : ?>
<div class="rx-archive-card__excerpt" itemprop="<?php echo $rx_show_schema ? esc_attr( 'description' ) : ''; ?>">
<p>
<?php echo esc_html( rx_theme_get_trimmed_excerpt( $post_id, $rx_excerpt_length ) ); ?>
</p>
</div>
<?php endif; ?>
<?php
/**
* Hook after archive excerpt.
*/
do_action( 'rx_theme_after_archive_excerpt', $post_id );
?>
<?php
$post_tags = get_the_tags( $post_id );
?>
<?php if ( $rx_show_tags && ! empty( $post_tags ) && ! is_wp_error( $post_tags ) ) : ?>
<div class="rx-archive-card__tags" aria-label="<?php esc_attr_e( 'Post tags', 'rx-theme' ); ?>">
<span class="rx-archive-card__tags-label">
<?php esc_html_e( 'Tags:', 'rx-theme' ); ?>
</span>
<?php foreach ( array_slice( $post_tags, 0, 5 ) as $tag ) : ?>
<a
class="rx-archive-card__tag-link"
href="<?php echo esc_url( get_tag_link( $tag->term_id ) ); ?>"
>
<?php echo esc_html( $tag->name ); ?>
</a>
<?php endforeach; ?>
</div>
<?php endif; ?>
<footer class="rx-archive-card__footer">
<?php if ( $rx_show_read_more ) : ?>
<a
class="rx-archive-card__read-more rx-button rx-button--archive"
href="<?php echo esc_url( $permalink ); ?>"
aria-label="<?php echo esc_attr( sprintf( __( 'Continue reading %s', 'rx-theme' ), $title ) ); ?>"
>
<span><?php echo esc_html( $rx_read_more_text ); ?></span>
<span class="rx-archive-card__read-more-icon" aria-hidden="true">→</span>
</a>
<?php endif; ?>
<?php edit_post_link(
esc_html__( 'Edit', 'rx-theme' ),
'<span class="rx-archive-card__edit-link">',
'</span>',
$post_id
); ?>
</footer>
</div>
<?php
/**
* Hook after archive card.
*/
do_action( 'rx_theme_after_archive_card', $post_id );
?>
</article>
Optional CSS for this archive card
Add this to your theme CSS file:
.rx-archive-card {
position: relative;
display: flex;
flex-direction: column;
gap: 0;
overflow: hidden;
background: #fff;
border: 1px solid rgba(0, 0, 0, 0.08);
border-radius: 18px;
box-shadow: 0 8px 30px rgba(0, 0, 0, 0.04);
transition: transform 0.25s ease, box-shadow 0.25s ease;
}
.rx-archive-card:hover {
transform: translateY(-4px);
box-shadow: 0 14px 40px rgba(0, 0, 0, 0.08);
}
.rx-archive-card__media {
position: relative;
overflow: hidden;
background: #f6f7f9;
}
.rx-archive-card__thumbnail-link {
display: block;
line-height: 0;
}
.rx-archive-card__thumbnail {
width: 100%;
height: auto;
aspect-ratio: 16 / 9;
object-fit: cover;
transition: transform 0.35s ease;
}
.rx-archive-card:hover .rx-archive-card__thumbnail {
transform: scale(1.04);
}
.rx-archive-card__badge {
position: absolute;
z-index: 2;
display: inline-flex;
align-items: center;
justify-content: center;
padding: 6px 12px;
font-size: 12px;
font-weight: 700;
line-height: 1;
text-decoration: none;
border-radius: 999px;
background: #111827;
color: #fff;
}
.rx-archive-card__badge--sticky {
top: 14px;
left: 14px;
}
.rx-archive-card__badge--category {
right: 14px;
bottom: 14px;
background: #2563eb;
}
.rx-archive-card__body {
padding: 22px;
}
.rx-archive-card__categories {
display: flex;
flex-wrap: wrap;
gap: 8px;
margin-bottom: 12px;
}
.rx-archive-card__category-link {
font-size: 13px;
font-weight: 700;
text-decoration: none;
color: #2563eb;
}
.rx-archive-card__title {
margin: 0 0 12px;
font-size: clamp(22px, 2vw, 30px);
line-height: 1.25;
}
.rx-archive-card__title a {
color: #111827;
text-decoration: none;
}
.rx-archive-card__title a:hover {
color: #2563eb;
}
.rx-archive-card__meta {
display: flex;
flex-wrap: wrap;
gap: 8px 14px;
margin-bottom: 16px;
font-size: 14px;
color: #6b7280;
}
.rx-archive-card__meta a {
color: inherit;
text-decoration: none;
}
.rx-archive-card__meta a:hover {
color: #2563eb;
}
.rx-archive-card__excerpt {
color: #374151;
font-size: 16px;
line-height: 1.75;
}
.rx-archive-card__excerpt p {
margin: 0 0 16px;
}
.rx-archive-card__tags {
display: flex;
flex-wrap: wrap;
gap: 8px;
margin-top: 14px;
font-size: 13px;
}
.rx-archive-card__tags-label {
font-weight: 700;
color: #111827;
}
.rx-archive-card__tag-link {
padding: 4px 9px;
color: #374151;
text-decoration: none;
background: #f3f4f6;
border-radius: 999px;
}
.rx-archive-card__tag-link:hover {
color: #fff;
background: #2563eb;
}
.rx-archive-card__footer {
display: flex;
align-items: center;
justify-content: space-between;
gap: 14px;
margin-top: 18px;
}
.rx-archive-card__read-more {
display: inline-flex;
align-items: center;
gap: 8px;
padding: 10px 16px;
font-size: 14px;
font-weight: 700;
color: #fff;
text-decoration: none;
background: #111827;
border-radius: 999px;
transition: background 0.2s ease;
}
.rx-archive-card__read-more:hover {
background: #2563eb;
}
.rx-archive-card__edit-link a {
font-size: 13px;
color: #6b7280;
}
.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;
}
@media (min-width: 768px) {
.rx-archive-card.rx-post-card--archive {
flex-direction: row;
}
.rx-archive-card.rx-post-card--archive .rx-archive-card__media {
flex: 0 0 38%;
}
.rx-archive-card.rx-post-card--archive .rx-archive-card__thumbnail {
height: 100%;
min-height: 260px;
}
}
@media (max-width: 767px) {
.rx-archive-card__body {
padding: 18px;
}
.rx-archive-card__footer {
align-items: flex-start;
flex-direction: column;
}
}
How to call it inside archive loop
Use this in archive.php, index.php, home.php, category.php, tag.php, or search.php:
<?php
if ( have_posts() ) :
while ( have_posts() ) :
the_post();
get_template_part( 'template-parts/content/content', 'archive' );
endwhile;
the_posts_pagination();
else :
get_template_part( 'template-parts/content/content', 'none' );
endif;
?>
This file is safe, expandable, SEO-friendly, schema-ready, mobile-friendly, and suitable for a professional WordPress theme archive card.