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.