search.php

I’ll make this as a complete advanced search.php template for your rx theme, using safe WordPress functions, SEO-friendly markup, accessibility, pagination, filters, and rich search-result cards.

Below is an advanced search.php file for your rx theme.
Place it here:

rx-theme/search.php

This template includes:

Search title, search form, result count, sorting UI, result type badges, featured image, excerpt, author/date/category/meta, reading time fallback, highlighted search keyword, pagination, no-result section, schema JSON-LD, accessibility, and clean WordPress security escaping.

<?php
/**
 * Search Results Template
 *
 * @package RX_Theme
 * @since 1.0.0
 */

defined( 'ABSPATH' ) || exit;

get_header();

/**
 * Current search query.
 */
$rx_search_query = get_search_query();

/**
 * Current paged number.
 */
$rx_paged = max( 1, get_query_var( 'paged' ), get_query_var( 'page' ) );

/**
 * Current global query.
 */
global $wp_query;

/**
 * Result count.
 */
$rx_found_posts = isset( $wp_query->found_posts ) ? (int) $wp_query->found_posts : 0;

/**
 * Search result URL.
 */
$rx_search_url = get_search_link( $rx_search_query );

/**
 * Current sort parameter.
 */
$rx_sort = isset( $_GET['rx_sort'] ) ? sanitize_key( wp_unslash( $_GET['rx_sort'] ) ) : 'relevance';

/**
 * Helper: Highlight searched words inside title/excerpt.
 */
if ( ! function_exists( 'rx_search_highlight_text' ) ) {
	function rx_search_highlight_text( $text, $query ) {
		if ( empty( $query ) || empty( $text ) ) {
			return $text;
		}

		$words = preg_split( '/\s+/', $query );

		if ( empty( $words ) || ! is_array( $words ) ) {
			return $text;
		}

		foreach ( $words as $word ) {
			$word = trim( $word );

			if ( mb_strlen( $word ) < 2 ) {
				continue;
			}

			$pattern = '/' . preg_quote( $word, '/' ) . '/iu';

			$text = preg_replace(
				$pattern,
				'<mark class="rx-search-highlight">$0</mark>',
				$text
			);
		}

		return $text;
	}
}

/**
 * Helper: Reading time fallback.
 */
if ( ! function_exists( 'rx_get_reading_time' ) ) {
	function rx_get_reading_time( $post_id = null ) {
		$post_id = $post_id ? absint( $post_id ) : get_the_ID();

		$content = get_post_field( 'post_content', $post_id );
		$content = wp_strip_all_tags( $content );

		$word_count = str_word_count( $content );
		$minutes    = max( 1, ceil( $word_count / 200 ) );

		return sprintf(
			/* translators: %d: reading minutes */
			_n( '%d min read', '%d min read', $minutes, 'rx-theme' ),
			$minutes
		);
	}
}

/**
 * Helper: Search result type label.
 */
if ( ! function_exists( 'rx_get_search_result_type_label' ) ) {
	function rx_get_search_result_type_label( $post_id = null ) {
		$post_id   = $post_id ? absint( $post_id ) : get_the_ID();
		$post_type = get_post_type( $post_id );

		if ( 'post' === $post_type ) {
			return esc_html__( 'Article', 'rx-theme' );
		}

		if ( 'page' === $post_type ) {
			return esc_html__( 'Page', 'rx-theme' );
		}

		$post_type_obj = get_post_type_object( $post_type );

		if ( $post_type_obj && ! empty( $post_type_obj->labels->singular_name ) ) {
			return esc_html( $post_type_obj->labels->singular_name );
		}

		return esc_html__( 'Result', 'rx-theme' );
	}
}

/**
 * Helper: Result content type icon.
 */
if ( ! function_exists( 'rx_get_search_result_icon' ) ) {
	function rx_get_search_result_icon( $post_id = null ) {
		$post_id   = $post_id ? absint( $post_id ) : get_the_ID();
		$post_type = get_post_type( $post_id );

		switch ( $post_type ) {
			case 'post':
				return '📄';
			case 'page':
				return '📘';
			case 'product':
				return '🛒';
			default:
				return '🔎';
		}
	}
}

/**
 * Optional sorting message.
 * Real sorting is best handled in functions.php using pre_get_posts.
 */
$rx_sort_labels = array(
	'relevance' => esc_html__( 'Relevance', 'rx-theme' ),
	'newest'    => esc_html__( 'Newest', 'rx-theme' ),
	'oldest'    => esc_html__( 'Oldest', 'rx-theme' ),
	'title'     => esc_html__( 'Title', 'rx-theme' ),
);

$rx_current_sort_label = isset( $rx_sort_labels[ $rx_sort ] ) ? $rx_sort_labels[ $rx_sort ] : $rx_sort_labels['relevance'];

?>

<main id="primary" class="rx-site-main rx-search-page" role="main">

	<section class="rx-search-hero" aria-labelledby="rx-search-title">
		<div class="rx-container">

			<nav class="rx-breadcrumbs rx-search-breadcrumbs" aria-label="<?php esc_attr_e( 'Breadcrumb', 'rx-theme' ); ?>">
				<a href="<?php echo esc_url( home_url( '/' ) ); ?>">
					<?php esc_html_e( 'Home', 'rx-theme' ); ?>
				</a>
				<span aria-hidden="true">/</span>
				<span>
					<?php esc_html_e( 'Search', 'rx-theme' ); ?>
				</span>
			</nav>

			<header class="rx-search-header">
				<p class="rx-search-kicker">
					<?php esc_html_e( 'Search Results', 'rx-theme' ); ?>
				</p>

				<h1 id="rx-search-title" class="rx-search-title">
					<?php if ( $rx_search_query ) : ?>
						<?php
						printf(
							wp_kses_post(
								/* translators: %s: search query */
								__( 'Results for: <span>%s</span>', 'rx-theme' )
							),
							esc_html( $rx_search_query )
						);
						?>
					<?php else : ?>
						<?php esc_html_e( 'Search RX Theme', 'rx-theme' ); ?>
					<?php endif; ?>
				</h1>

				<div class="rx-search-summary" aria-live="polite">
					<?php if ( $rx_search_query && $rx_found_posts > 0 ) : ?>
						<?php
						printf(
							esc_html(
								_n(
									'We found %s result for your search.',
									'We found %s results for your search.',
									$rx_found_posts,
									'rx-theme'
								)
							),
							number_format_i18n( $rx_found_posts )
						);
						?>
					<?php elseif ( $rx_search_query ) : ?>
						<?php esc_html_e( 'No matching result was found. Try another keyword below.', 'rx-theme' ); ?>
					<?php else : ?>
						<?php esc_html_e( 'Type a keyword to find articles, pages, and resources.', 'rx-theme' ); ?>
					<?php endif; ?>
				</div>
			</header>

			<div class="rx-search-form-wrap">
				<form role="search" method="get" class="rx-search-form" action="<?php echo esc_url( home_url( '/' ) ); ?>">
					<label class="screen-reader-text" for="rx-search-field">
						<?php esc_html_e( 'Search for:', 'rx-theme' ); ?>
					</label>

					<input
						type="search"
						id="rx-search-field"
						class="rx-search-field"
						name="s"
						value="<?php echo esc_attr( $rx_search_query ); ?>"
						placeholder="<?php esc_attr_e( 'Search health articles, guides, pages...', 'rx-theme' ); ?>"
						autocomplete="off"
						required
					/>

					<button type="submit" class="rx-search-submit">
						<span aria-hidden="true">🔍</span>
						<span><?php esc_html_e( 'Search', 'rx-theme' ); ?></span>
					</button>
				</form>
			</div>

			<?php if ( $rx_search_query ) : ?>
				<div class="rx-search-tools">

					<div class="rx-search-tool-left">
						<span class="rx-search-tool-label">
							<?php esc_html_e( 'Current sorting:', 'rx-theme' ); ?>
						</span>
						<strong><?php echo esc_html( $rx_current_sort_label ); ?></strong>
					</div>

					<div class="rx-search-sort">
						<span class="rx-search-sort-label">
							<?php esc_html_e( 'Sort by:', 'rx-theme' ); ?>
						</span>

						<?php foreach ( $rx_sort_labels as $rx_sort_key => $rx_sort_label ) : ?>
							<?php
							$rx_sort_url = add_query_arg(
								array(
									's'       => rawurlencode( $rx_search_query ),
									'rx_sort' => $rx_sort_key,
								),
								home_url( '/' )
							);

							$rx_is_active_sort = $rx_sort === $rx_sort_key;
							?>

							<a
								class="rx-search-sort-link <?php echo $rx_is_active_sort ? 'is-active' : ''; ?>"
								href="<?php echo esc_url( $rx_sort_url ); ?>"
								<?php echo $rx_is_active_sort ? 'aria-current="true"' : ''; ?>
							>
								<?php echo esc_html( $rx_sort_label ); ?>
							</a>
						<?php endforeach; ?>
					</div>

				</div>
			<?php endif; ?>

		</div>
	</section>

	<section class="rx-search-content-section">
		<div class="rx-container rx-search-layout">

			<div class="rx-search-main-content">

				<?php if ( have_posts() ) : ?>

					<div class="rx-search-results-list" aria-label="<?php esc_attr_e( 'Search results list', 'rx-theme' ); ?>">

						<?php
						while ( have_posts() ) :
							the_post();

							$rx_post_id       = get_the_ID();
							$rx_title         = get_the_title();
							$rx_permalink     = get_permalink();
							$rx_post_type     = get_post_type();
							$rx_type_label    = rx_get_search_result_type_label( $rx_post_id );
							$rx_icon          = rx_get_search_result_icon( $rx_post_id );
							$rx_excerpt       = has_excerpt() ? get_the_excerpt() : wp_trim_words( wp_strip_all_tags( get_the_content() ), 38, '...' );
							$rx_author_id     = get_post_field( 'post_author', $rx_post_id );
							$rx_author_name   = get_the_author_meta( 'display_name', $rx_author_id );
							$rx_author_url    = get_author_posts_url( $rx_author_id );
							$rx_reading_time  = rx_get_reading_time( $rx_post_id );
							$rx_modified_time = get_the_modified_time( get_option( 'date_format' ) );
							$rx_date_iso      = get_the_date( DATE_W3C );
							$rx_modified_iso  = get_the_modified_date( DATE_W3C );
							?>

							<article id="post-<?php the_ID(); ?>" <?php post_class( 'rx-search-card' ); ?>>

								<div class="rx-search-card-inner">

									<?php if ( has_post_thumbnail() ) : ?>
										<a class="rx-search-thumbnail" href="<?php echo esc_url( $rx_permalink ); ?>" aria-hidden="true" tabindex="-1">
											<?php
											the_post_thumbnail(
												'medium_large',
												array(
													'class'   => 'rx-search-image',
													'loading' => 'lazy',
													'alt'     => esc_attr( $rx_title ),
												)
											);
											?>
										</a>
									<?php else : ?>
										<a class="rx-search-thumbnail rx-search-thumbnail-placeholder" href="<?php echo esc_url( $rx_permalink ); ?>" aria-hidden="true" tabindex="-1">
											<span><?php echo esc_html( $rx_icon ); ?></span>
										</a>
									<?php endif; ?>

									<div class="rx-search-card-body">

										<div class="rx-search-card-top">
											<span class="rx-search-type-badge">
												<?php echo esc_html( $rx_icon ); ?>
												<?php echo esc_html( $rx_type_label ); ?>
											</span>

											<?php if ( 'post' === $rx_post_type ) : ?>
												<?php
												$rx_categories = get_the_category();

												if ( ! empty( $rx_categories ) ) :
													$rx_primary_category = $rx_categories[0];
													?>
													<a class="rx-search-category" href="<?php echo esc_url( get_category_link( $rx_primary_category->term_id ) ); ?>">
														<?php echo esc_html( $rx_primary_category->name ); ?>
													</a>
												<?php endif; ?>
											<?php endif; ?>
										</div>

										<h2 class="rx-search-card-title">
											<a href="<?php echo esc_url( $rx_permalink ); ?>">
												<?php
												echo wp_kses(
													rx_search_highlight_text( esc_html( $rx_title ), $rx_search_query ),
													array(
														'mark' => array(
															'class' => array(),
														),
													)
												);
												?>
											</a>
										</h2>

										<div class="rx-search-card-meta">
											<span class="rx-search-meta-item">
												<span aria-hidden="true">📅</span>
												<time datetime="<?php echo esc_attr( $rx_date_iso ); ?>">
													<?php echo esc_html( get_the_date() ); ?>
												</time>
											</span>

											<span class="rx-search-meta-item">
												<span aria-hidden="true">✍️</span>
												<a href="<?php echo esc_url( $rx_author_url ); ?>">
													<?php echo esc_html( $rx_author_name ); ?>
												</a>
											</span>

											<span class="rx-search-meta-item">
												<span aria-hidden="true">⏱️</span>
												<?php echo esc_html( $rx_reading_time ); ?>
											</span>

											<span class="rx-search-meta-item">
												<span aria-hidden="true">🔄</span>
												<?php
												printf(
													/* translators: %s: modified date */
													esc_html__( 'Updated %s', 'rx-theme' ),
													esc_html( $rx_modified_time )
												);
												?>
											</span>
										</div>

										<div class="rx-search-card-excerpt">
											<?php
											echo wp_kses(
												rx_search_highlight_text( esc_html( $rx_excerpt ), $rx_search_query ),
												array(
													'mark' => array(
														'class' => array(),
													),
												)
											);
											?>
										</div>

										<div class="rx-search-card-footer">
											<a class="rx-search-read-more" href="<?php echo esc_url( $rx_permalink ); ?>">
												<?php esc_html_e( 'Read full result', 'rx-theme' ); ?>
												<span aria-hidden="true"></span>
											</a>

											<span class="rx-search-result-url">
												<?php echo esc_html( wp_parse_url( $rx_permalink, PHP_URL_PATH ) ); ?>
											</span>
										</div>

									</div>
								</div>

								<script type="application/ld+json">
									<?php
									$rx_schema = array(
										'@context'     => 'https://schema.org',
										'@type'        => 'Article',
										'headline'     => wp_strip_all_tags( $rx_title ),
										'url'          => esc_url_raw( $rx_permalink ),
										'datePublished'=> get_the_date( DATE_W3C ),
										'dateModified' => $rx_modified_iso,
										'author'       => array(
											'@type' => 'Person',
											'name'  => wp_strip_all_tags( $rx_author_name ),
										),
										'publisher'    => array(
											'@type' => 'Organization',
											'name'  => get_bloginfo( 'name' ),
										),
									);

									if ( has_post_thumbnail() ) {
										$rx_schema['image'] = get_the_post_thumbnail_url( $rx_post_id, 'full' );
									}

									echo wp_json_encode( $rx_schema, JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT );
									?>
								</script>

							</article>

						<?php endwhile; ?>

					</div>

					<nav class="rx-search-pagination" aria-label="<?php esc_attr_e( 'Search results pagination', 'rx-theme' ); ?>">
						<?php
						echo wp_kses_post(
							paginate_links(
								array(
									'total'     => $wp_query->max_num_pages,
									'current'   => $rx_paged,
									'mid_size'  => 2,
									'prev_text' => '<span aria-hidden="true">←</span> ' . esc_html__( 'Previous', 'rx-theme' ),
									'next_text' => esc_html__( 'Next', 'rx-theme' ) . ' <span aria-hidden="true">→</span>',
									'type'      => 'list',
									'add_args'  => array(
										'rx_sort' => $rx_sort,
									),
								)
							)
						);
						?>
					</nav>

				<?php else : ?>

					<section class="rx-no-search-results" aria-labelledby="rx-no-results-title">

						<div class="rx-no-results-icon" aria-hidden="true">
							🔎
						</div>

						<h2 id="rx-no-results-title">
							<?php esc_html_e( 'No result found', 'rx-theme' ); ?>
						</h2>

						<p>
							<?php
							printf(
								wp_kses_post(
									/* translators: %s: search query */
									__( 'We could not find anything for <strong>%s</strong>. Please try another keyword, check spelling, or use a broader medical term.', 'rx-theme' )
								),
								esc_html( $rx_search_query )
							);
							?>
						</p>

						<form role="search" method="get" class="rx-search-form rx-no-result-form" action="<?php echo esc_url( home_url( '/' ) ); ?>">
							<label class="screen-reader-text" for="rx-no-result-search-field">
								<?php esc_html_e( 'Search again:', 'rx-theme' ); ?>
							</label>

							<input
								type="search"
								id="rx-no-result-search-field"
								class="rx-search-field"
								name="s"
								value="<?php echo esc_attr( $rx_search_query ); ?>"
								placeholder="<?php esc_attr_e( 'Try another keyword...', 'rx-theme' ); ?>"
							/>

							<button type="submit" class="rx-search-submit">
								<?php esc_html_e( 'Search Again', 'rx-theme' ); ?>
							</button>
						</form>

						<div class="rx-search-suggestions">
							<h3><?php esc_html_e( 'Search suggestions', 'rx-theme' ); ?></h3>

							<ul>
								<li><?php esc_html_e( 'Check spelling carefully.', 'rx-theme' ); ?></li>
								<li><?php esc_html_e( 'Use shorter keywords.', 'rx-theme' ); ?></li>
								<li><?php esc_html_e( 'Try a similar medical word.', 'rx-theme' ); ?></li>
								<li><?php esc_html_e( 'Try broader topics such as symptoms, causes, diagnosis, or treatment.', 'rx-theme' ); ?></li>
							</ul>
						</div>

						<?php
						$rx_recent_posts = new WP_Query(
							array(
								'post_type'           => 'post',
								'post_status'         => 'publish',
								'posts_per_page'      => 6,
								'ignore_sticky_posts' => true,
								'no_found_rows'       => true,
							)
						);
						?>

						<?php if ( $rx_recent_posts->have_posts() ) : ?>
							<div class="rx-recent-after-no-results">
								<h3><?php esc_html_e( 'Recent articles you may like', 'rx-theme' ); ?></h3>

								<div class="rx-recent-mini-grid">
									<?php while ( $rx_recent_posts->have_posts() ) : ?>
										<?php $rx_recent_posts->the_post(); ?>

										<a class="rx-recent-mini-card" href="<?php the_permalink(); ?>">
											<?php if ( has_post_thumbnail() ) : ?>
												<?php
												the_post_thumbnail(
													'thumbnail',
													array(
														'class'   => 'rx-recent-mini-image',
														'loading' => 'lazy',
														'alt'     => esc_attr( get_the_title() ),
													)
												);
												?>
											<?php endif; ?>

											<span><?php the_title(); ?></span>
										</a>

									<?php endwhile; ?>
								</div>
							</div>

							<?php wp_reset_postdata(); ?>
						<?php endif; ?>

					</section>

				<?php endif; ?>

			</div>

			<aside class="rx-search-sidebar" aria-label="<?php esc_attr_e( 'Search sidebar', 'rx-theme' ); ?>">

				<div class="rx-search-widget">
					<h2 class="rx-search-widget-title">
						<?php esc_html_e( 'Refine your search', 'rx-theme' ); ?>
					</h2>

					<form role="search" method="get" class="rx-sidebar-search-form" action="<?php echo esc_url( home_url( '/' ) ); ?>">
						<label for="rx-sidebar-search-field">
							<?php esc_html_e( 'Keyword', 'rx-theme' ); ?>
						</label>

						<input
							type="search"
							id="rx-sidebar-search-field"
							name="s"
							value="<?php echo esc_attr( $rx_search_query ); ?>"
							placeholder="<?php esc_attr_e( 'Enter keyword...', 'rx-theme' ); ?>"
						/>

						<label for="rx-sidebar-sort-field">
							<?php esc_html_e( 'Sort results', 'rx-theme' ); ?>
						</label>

						<select id="rx-sidebar-sort-field" name="rx_sort">
							<?php foreach ( $rx_sort_labels as $rx_sort_key => $rx_sort_label ) : ?>
								<option value="<?php echo esc_attr( $rx_sort_key ); ?>" <?php selected( $rx_sort, $rx_sort_key ); ?>>
									<?php echo esc_html( $rx_sort_label ); ?>
								</option>
							<?php endforeach; ?>
						</select>

						<button type="submit">
							<?php esc_html_e( 'Apply', 'rx-theme' ); ?>
						</button>
					</form>
				</div>

				<?php
				$rx_popular_categories = get_categories(
					array(
						'orderby'    => 'count',
						'order'      => 'DESC',
						'number'     => 8,
						'hide_empty' => true,
					)
				);
				?>

				<?php if ( ! empty( $rx_popular_categories ) && ! is_wp_error( $rx_popular_categories ) ) : ?>
					<div class="rx-search-widget">
						<h2 class="rx-search-widget-title">
							<?php esc_html_e( 'Popular categories', 'rx-theme' ); ?>
						</h2>

						<ul class="rx-search-category-list">
							<?php foreach ( $rx_popular_categories as $rx_category ) : ?>
								<li>
									<a href="<?php echo esc_url( get_category_link( $rx_category->term_id ) ); ?>">
										<span><?php echo esc_html( $rx_category->name ); ?></span>
										<small><?php echo esc_html( number_format_i18n( $rx_category->count ) ); ?></small>
									</a>
								</li>
							<?php endforeach; ?>
						</ul>
					</div>
				<?php endif; ?>

				<?php
				$rx_recent_sidebar_posts = new WP_Query(
					array(
						'post_type'           => 'post',
						'post_status'         => 'publish',
						'posts_per_page'      => 5,
						'ignore_sticky_posts' => true,
						'no_found_rows'       => true,
					)
				);
				?>

				<?php if ( $rx_recent_sidebar_posts->have_posts() ) : ?>
					<div class="rx-search-widget">
						<h2 class="rx-search-widget-title">
							<?php esc_html_e( 'Latest articles', 'rx-theme' ); ?>
						</h2>

						<ul class="rx-latest-search-posts">
							<?php while ( $rx_recent_sidebar_posts->have_posts() ) : ?>
								<?php $rx_recent_sidebar_posts->the_post(); ?>

								<li>
									<a href="<?php the_permalink(); ?>">
										<?php if ( has_post_thumbnail() ) : ?>
											<?php
											the_post_thumbnail(
												'thumbnail',
												array(
													'class'   => 'rx-latest-search-thumb',
													'loading' => 'lazy',
													'alt'     => esc_attr( get_the_title() ),
												)
											);
											?>
										<?php endif; ?>

										<span><?php the_title(); ?></span>
									</a>
								</li>

							<?php endwhile; ?>
						</ul>
					</div>

					<?php wp_reset_postdata(); ?>
				<?php endif; ?>

				<?php if ( is_active_sidebar( 'search-sidebar' ) ) : ?>
					<div class="rx-search-widget-area">
						<?php dynamic_sidebar( 'search-sidebar' ); ?>
					</div>
				<?php endif; ?>

			</aside>

		</div>
	</section>

	<?php if ( $rx_search_query ) : ?>
		<script type="application/ld+json">
			<?php
			$rx_search_page_schema = array(
				'@context'        => 'https://schema.org',
				'@type'           => 'SearchResultsPage',
				'name'            => sprintf(
					/* translators: %s: search query */
					__( 'Search results for %s', 'rx-theme' ),
					$rx_search_query
				),
				'url'             => esc_url_raw( $rx_search_url ),
				'mainEntity'      => array(
					'@type'       => 'ItemList',
					'numberOfItems' => $rx_found_posts,
				),
				'potentialAction' => array(
					'@type'       => 'SearchAction',
					'target'      => esc_url_raw( home_url( '/?s={search_term_string}' ) ),
					'query-input' => 'required name=search_term_string',
				),
			);

			echo wp_json_encode( $rx_search_page_schema, JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT );
			?>
		</script>
	<?php endif; ?>

</main>

<?php
get_footer();

For your sorting buttons to actually change the search order, add this in functions.php:

<?php
/**
 * RX Search Sorting Controller
 */
function rx_theme_search_sorting_query( $query ) {

	if ( is_admin() || ! $query->is_main_query() ) {
		return;
	}

	if ( ! $query->is_search() ) {
		return;
	}

	$sort = isset( $_GET['rx_sort'] ) ? sanitize_key( wp_unslash( $_GET['rx_sort'] ) ) : 'relevance';

	switch ( $sort ) {
		case 'newest':
			$query->set( 'orderby', 'date' );
			$query->set( 'order', 'DESC' );
			break;

		case 'oldest':
			$query->set( 'orderby', 'date' );
			$query->set( 'order', 'ASC' );
			break;

		case 'title':
			$query->set( 'orderby', 'title' );
			$query->set( 'order', 'ASC' );
			break;

		case 'relevance':
		default:
			$query->set( 'orderby', 'relevance' );
			break;
	}

	/**
	 * Search only useful public content types.
	 * Add more custom post types here if needed.
	 */
	$query->set(
		'post_type',
		array(
			'post',
			'page',
		)
	);

	$query->set( 'post_status', 'publish' );
}
add_action( 'pre_get_posts', 'rx_theme_search_sorting_query' );

Optional CSS for style.css:

.rx-search-page {
	background: #fff;
}

.rx-container {
	width: min(1180px, calc(100% - 32px));
	margin-inline: auto;
}

.rx-search-hero {
	padding: 48px 0 32px;
	background: linear-gradient(180deg, #f8fafc 0%, #ffffff 100%);
	border-bottom: 1px solid #e5e7eb;
}

.rx-breadcrumbs {
	display: flex;
	gap: 8px;
	align-items: center;
	font-size: 14px;
	margin-bottom: 24px;
	color: #64748b;
}

.rx-breadcrumbs a {
	color: inherit;
	text-decoration: none;
}

.rx-breadcrumbs a:hover {
	text-decoration: underline;
}

.rx-search-kicker {
	margin: 0 0 8px;
	font-weight: 700;
	letter-spacing: .08em;
	text-transform: uppercase;
	font-size: 13px;
	color: #2563eb;
}

.rx-search-title {
	margin: 0;
	font-size: clamp(32px, 5vw, 56px);
	line-height: 1.05;
	letter-spacing: -0.04em;
	color: #0f172a;
}

.rx-search-title span {
	color: #2563eb;
}

.rx-search-summary {
	margin-top: 16px;
	max-width: 720px;
	font-size: 18px;
	color: #475569;
}

.rx-search-form-wrap {
	margin-top: 28px;
}

.rx-search-form,
.rx-sidebar-search-form {
	display: flex;
	gap: 10px;
}

.rx-search-field,
.rx-sidebar-search-form input,
.rx-sidebar-search-form select {
	width: 100%;
	border: 1px solid #cbd5e1;
	border-radius: 14px;
	padding: 14px 16px;
	font-size: 16px;
	background: #fff;
	color: #0f172a;
}

.rx-search-submit,
.rx-sidebar-search-form button {
	border: 0;
	border-radius: 14px;
	padding: 14px 20px;
	font-size: 16px;
	font-weight: 700;
	cursor: pointer;
	background: #2563eb;
	color: #fff;
	white-space: nowrap;
}

.rx-search-submit:hover,
.rx-sidebar-search-form button:hover {
	background: #1d4ed8;
}

.rx-search-tools {
	display: flex;
	justify-content: space-between;
	gap: 16px;
	flex-wrap: wrap;
	margin-top: 24px;
	padding-top: 20px;
	border-top: 1px solid #e5e7eb;
}

.rx-search-tool-label,
.rx-search-sort-label {
	color: #64748b;
	margin-right: 6px;
}

.rx-search-sort {
	display: flex;
	gap: 8px;
	flex-wrap: wrap;
	align-items: center;
}

.rx-search-sort-link {
	display: inline-flex;
	padding: 7px 12px;
	border-radius: 999px;
	border: 1px solid #cbd5e1;
	color: #334155;
	text-decoration: none;
	font-size: 14px;
}

.rx-search-sort-link:hover,
.rx-search-sort-link.is-active {
	background: #2563eb;
	border-color: #2563eb;
	color: #fff;
}

.rx-search-content-section {
	padding: 40px 0 64px;
}

.rx-search-layout {
	display: grid;
	grid-template-columns: minmax(0, 1fr) 320px;
	gap: 32px;
	align-items: start;
}

.rx-search-results-list {
	display: grid;
	gap: 20px;
}

.rx-search-card {
	border: 1px solid #e2e8f0;
	border-radius: 24px;
	background: #fff;
	overflow: hidden;
	transition: transform .2s ease, box-shadow .2s ease, border-color .2s ease;
}

.rx-search-card:hover {
	transform: translateY(-2px);
	box-shadow: 0 20px 45px rgba(15, 23, 42, 0.08);
	border-color: #bfdbfe;
}

.rx-search-card-inner {
	display: grid;
	grid-template-columns: 220px minmax(0, 1fr);
	gap: 0;
}

.rx-search-thumbnail {
	display: block;
	position: relative;
	min-height: 100%;
	background: #f1f5f9;
	overflow: hidden;
}

.rx-search-image {
	width: 100%;
	height: 100%;
	object-fit: cover;
	display: block;
}

.rx-search-thumbnail-placeholder {
	display: grid;
	place-items: center;
	font-size: 48px;
	text-decoration: none;
}

.rx-search-card-body {
	padding: 24px;
}

.rx-search-card-top {
	display: flex;
	align-items: center;
	gap: 10px;
	flex-wrap: wrap;
	margin-bottom: 12px;
}

.rx-search-type-badge,
.rx-search-category {
	display: inline-flex;
	align-items: center;
	gap: 6px;
	padding: 6px 10px;
	border-radius: 999px;
	font-size: 13px;
	font-weight: 700;
	text-decoration: none;
}

.rx-search-type-badge {
	background: #eff6ff;
	color: #1d4ed8;
}

.rx-search-category {
	background: #f8fafc;
	color: #334155;
	border: 1px solid #e2e8f0;
}

.rx-search-card-title {
	margin: 0;
	font-size: 26px;
	line-height: 1.2;
	letter-spacing: -0.02em;
}

.rx-search-card-title a {
	color: #0f172a;
	text-decoration: none;
}

.rx-search-card-title a:hover {
	color: #2563eb;
}

.rx-search-card-meta {
	display: flex;
	flex-wrap: wrap;
	gap: 12px;
	margin-top: 12px;
	font-size: 14px;
	color: #64748b;
}

.rx-search-meta-item {
	display: inline-flex;
	align-items: center;
	gap: 5px;
}

.rx-search-meta-item a {
	color: inherit;
	text-decoration: none;
}

.rx-search-meta-item a:hover {
	text-decoration: underline;
}

.rx-search-card-excerpt {
	margin-top: 14px;
	color: #475569;
	line-height: 1.75;
	font-size: 16px;
}

.rx-search-highlight {
	background: #fef3c7;
	color: #92400e;
	padding: 0 3px;
	border-radius: 4px;
}

.rx-search-card-footer {
	display: flex;
	justify-content: space-between;
	gap: 16px;
	flex-wrap: wrap;
	align-items: center;
	margin-top: 18px;
}

.rx-search-read-more {
	display: inline-flex;
	align-items: center;
	gap: 8px;
	font-weight: 800;
	color: #2563eb;
	text-decoration: none;
}

.rx-search-read-more:hover {
	text-decoration: underline;
}

.rx-search-result-url {
	color: #94a3b8;
	font-size: 13px;
	word-break: break-all;
}

.rx-search-pagination {
	margin-top: 32px;
}

.rx-search-pagination ul {
	display: flex;
	flex-wrap: wrap;
	gap: 8px;
	list-style: none;
	padding: 0;
	margin: 0;
}

.rx-search-pagination a,
.rx-search-pagination span {
	display: inline-flex;
	min-width: 42px;
	height: 42px;
	align-items: center;
	justify-content: center;
	border-radius: 12px;
	border: 1px solid #cbd5e1;
	padding: 0 12px;
	text-decoration: none;
	color: #334155;
	font-weight: 700;
}

.rx-search-pagination .current {
	background: #2563eb;
	border-color: #2563eb;
	color: #fff;
}

.rx-search-sidebar {
	position: sticky;
	top: 24px;
	display: grid;
	gap: 20px;
}

.rx-search-widget {
	border: 1px solid #e2e8f0;
	border-radius: 22px;
	padding: 22px;
	background: #fff;
}

.rx-search-widget-title {
	margin: 0 0 16px;
	font-size: 20px;
	letter-spacing: -0.02em;
}

.rx-sidebar-search-form {
	display: grid;
}

.rx-sidebar-search-form label {
	font-weight: 700;
	font-size: 14px;
	color: #334155;
}

.rx-search-category-list,
.rx-latest-search-posts {
	list-style: none;
	margin: 0;
	padding: 0;
	display: grid;
	gap: 10px;
}

.rx-search-category-list a {
	display: flex;
	justify-content: space-between;
	gap: 12px;
	text-decoration: none;
	color: #334155;
	padding: 10px 0;
	border-bottom: 1px solid #f1f5f9;
}

.rx-search-category-list small {
	background: #f1f5f9;
	border-radius: 999px;
	padding: 2px 8px;
}

.rx-latest-search-posts a {
	display: grid;
	grid-template-columns: 52px minmax(0, 1fr);
	gap: 10px;
	align-items: center;
	color: #334155;
	text-decoration: none;
}

.rx-latest-search-thumb {
	width: 52px;
	height: 52px;
	object-fit: cover;
	border-radius: 12px;
	background: #f1f5f9;
}

.rx-no-search-results {
	border: 1px solid #e2e8f0;
	border-radius: 24px;
	padding: 32px;
	text-align: center;
	background: #fff;
}

.rx-no-results-icon {
	font-size: 56px;
	margin-bottom: 12px;
}

.rx-no-search-results h2 {
	font-size: 32px;
	margin: 0 0 12px;
}

.rx-no-result-form {
	max-width: 680px;
	margin: 24px auto;
}

.rx-search-suggestions {
	text-align: left;
	max-width: 680px;
	margin: 24px auto;
	background: #f8fafc;
	border-radius: 18px;
	padding: 20px;
}

.rx-search-suggestions h3 {
	margin-top: 0;
}

.rx-recent-after-no-results {
	margin-top: 32px;
	text-align: left;
}

.rx-recent-mini-grid {
	display: grid;
	grid-template-columns: repeat(3, minmax(0, 1fr));
	gap: 14px;
}

.rx-recent-mini-card {
	display: grid;
	gap: 8px;
	padding: 12px;
	border: 1px solid #e2e8f0;
	border-radius: 16px;
	text-decoration: none;
	color: #0f172a;
	font-weight: 700;
}

.rx-recent-mini-image {
	width: 100%;
	aspect-ratio: 16 / 10;
	object-fit: cover;
	border-radius: 12px;
}

.screen-reader-text {
	border: 0;
	clip: rect(1px, 1px, 1px, 1px);
	clip-path: inset(50%);
	height: 1px;
	margin: -1px;
	overflow: hidden;
	padding: 0;
	position: absolute;
	width: 1px;
	word-wrap: normal !important;
}

@media (max-width: 980px) {
	.rx-search-layout {
		grid-template-columns: 1fr;
	}

	.rx-search-sidebar {
		position: static;
	}

	.rx-search-card-inner {
		grid-template-columns: 180px minmax(0, 1fr);
	}
}

@media (max-width: 720px) {
	.rx-search-form {
		flex-direction: column;
	}

	.rx-search-card-inner {
		grid-template-columns: 1fr;
	}

	.rx-search-thumbnail {
		aspect-ratio: 16 / 9;
	}

	.rx-search-card-title {
		font-size: 22px;
	}

	.rx-recent-mini-grid {
		grid-template-columns: 1fr;
	}
}

For sidebar support, add this to inc/core/sidebars.php or functions.php:

<?php
/**
 * Register RX Search Sidebar.
 */
function rx_theme_register_search_sidebar() {
	register_sidebar(
		array(
			'name'          => esc_html__( 'Search Sidebar', 'rx-theme' ),
			'id'            => 'search-sidebar',
			'description'   => esc_html__( 'Widgets shown on the search results page.', 'rx-theme' ),
			'before_widget' => '<section id="%1$s" class="widget rx-widget %2$s">',
			'after_widget'  => '</section>',
			'before_title'  => '<h2 class="widget-title rx-widget-title">',
			'after_title'   => '</h2>',
		)
	);
}
add_action( 'widgets_init', 'rx_theme_register_search_sidebar' );

This is a strong search.php foundation for your RX theme. It is advanced but still safe, readable, and WordPress-standard.

Leave a Reply

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