content-archive.php

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.

Leave a Reply

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