I’ll build this as a reusable inc/builders/header-builder.php for your RX theme, with many header features: logo, menus, search, CTA, social links, top bar, sticky/mobile header, schema, accessibility, hooks, and customization filters.
Below is an advanced inc/builders/header-builder.php file for your RX Theme. It includes many possible header functions: logo, site title, primary menu, top bar, social icons, CTA button, search, mobile menu, sticky header, transparent header support, schema markup, hooks, accessibility, customizer-friendly filters, and safe fallback behavior.
Save this file here:
rx-theme/inc/builders/header-builder.php
Then include it from functions.php:
require_once get_template_directory() . '/inc/builders/header-builder.php';
Complete inc/builders/header-builder.php
<?php
/**
* RX Theme Header Builder
*
* File: inc/builders/header-builder.php
*
* Advanced reusable header builder for RX Theme.
*
* Features:
* - Top bar
* - Header logo
* - Site title and tagline
* - Primary navigation
* - Secondary navigation support
* - Mobile navigation toggle
* - Search button and search form
* - CTA button
* - Social links
* - Sticky header
* - Transparent header support
* - Header layout filters
* - Accessibility-ready markup
* - Schema.org support
* - WordPress hooks
* - Safe fallbacks
*
* @package RX_Theme
*/
defined( 'ABSPATH' ) || exit;
if ( ! class_exists( 'RX_Header_Builder' ) ) :
final class RX_Header_Builder {
/**
* Class instance.
*
* @var RX_Header_Builder|null
*/
private static $instance = null;
/**
* Header settings.
*
* @var array
*/
private $settings = array();
/**
* Get instance.
*
* @return RX_Header_Builder
*/
public static function instance() {
if ( null === self::$instance ) {
self::$instance = new self();
}
return self::$instance;
}
/**
* Constructor.
*/
private function __construct() {
$this->settings = $this->get_default_settings();
add_action( 'after_setup_theme', array( $this, 'register_menus' ) );
add_action( 'wp_enqueue_scripts', array( $this, 'enqueue_header_assets' ) );
add_action( 'rx_theme_header', array( $this, 'render_header' ) );
add_action( 'rx_theme_mobile_header', array( $this, 'render_mobile_header' ) );
add_filter( 'body_class', array( $this, 'body_classes' ) );
}
/**
* Default header settings.
*
* You can override these using:
* add_filter( 'rx_header_builder_settings', function( $settings ) { ... } );
*
* @return array
*/
private function get_default_settings() {
$settings = array(
'enable_top_bar' => true,
'enable_sticky_header' => true,
'enable_transparent' => false,
'enable_search' => true,
'enable_cta' => true,
'enable_social_links' => true,
'enable_tagline' => true,
'enable_mobile_header' => true,
'enable_schema' => true,
'enable_skip_link' => true,
'container_class' => 'rx-container',
'header_layout' => 'default',
'logo_position' => 'left',
'menu_position' => 'right',
'top_bar_left_text' => __( 'A global war against illness!', 'rx-theme' ),
'top_bar_right_text' => '',
'cta_text' => __( 'Book Appointment', 'rx-theme' ),
'cta_url' => home_url( '/contact/' ),
'cta_target' => '_self',
'search_placeholder' => __( 'Search...', 'rx-theme' ),
'social_links' => array(
'facebook' => '',
'twitter' => '',
'linkedin' => '',
'youtube' => '',
'instagram' => '',
'github' => '',
),
);
return apply_filters( 'rx_header_builder_settings', $settings );
}
/**
* Register menus.
*
* @return void
*/
public function register_menus() {
register_nav_menus(
array(
'primary' => esc_html__( 'Primary Menu', 'rx-theme' ),
'secondary' => esc_html__( 'Secondary Menu', 'rx-theme' ),
'mobile' => esc_html__( 'Mobile Menu', 'rx-theme' ),
'topbar' => esc_html__( 'Top Bar Menu', 'rx-theme' ),
)
);
}
/**
* Enqueue header CSS and JS.
*
* @return void
*/
public function enqueue_header_assets() {
$theme_version = wp_get_theme()->get( 'Version' );
wp_register_style(
'rx-header-builder',
get_template_directory_uri() . '/assets/css/header-builder.css',
array(),
$theme_version
);
wp_register_script(
'rx-header-builder',
get_template_directory_uri() . '/assets/js/header-builder.js',
array(),
$theme_version,
true
);
wp_localize_script(
'rx-header-builder',
'rxHeaderBuilder',
array(
'ajaxUrl' => admin_url( 'admin-ajax.php' ),
'homeUrl' => home_url( '/' ),
'isSticky' => (bool) $this->settings['enable_sticky_header'],
'isSearch' => (bool) $this->settings['enable_search'],
'menuLabelOpen' => esc_html__( 'Open menu', 'rx-theme' ),
'menuLabelClose'=> esc_html__( 'Close menu', 'rx-theme' ),
)
);
wp_enqueue_style( 'rx-header-builder' );
wp_enqueue_script( 'rx-header-builder' );
$this->inline_header_css();
}
/**
* Add body classes.
*
* @param array $classes Body classes.
* @return array
*/
public function body_classes( $classes ) {
if ( ! empty( $this->settings['enable_sticky_header'] ) ) {
$classes[] = 'rx-has-sticky-header';
}
if ( ! empty( $this->settings['enable_transparent'] ) ) {
$classes[] = 'rx-has-transparent-header';
}
$classes[] = 'rx-header-layout-' . sanitize_html_class( $this->settings['header_layout'] );
return $classes;
}
/**
* Render full header.
*
* @return void
*/
public function render_header() {
do_action( 'rx_before_header' );
if ( ! empty( $this->settings['enable_skip_link'] ) ) {
$this->render_skip_link();
}
if ( ! empty( $this->settings['enable_top_bar'] ) ) {
$this->render_top_bar();
}
$header_classes = $this->get_header_classes();
?>
<header id="masthead" class="<?php echo esc_attr( implode( ' ', $header_classes ) ); ?>" <?php $this->schema_attr( 'WPHeader' ); ?>>
<?php do_action( 'rx_header_start' ); ?>
<div class="<?php echo esc_attr( $this->settings['container_class'] ); ?>">
<div class="rx-header-inner">
<div class="rx-header-branding">
<?php $this->render_branding(); ?>
</div>
<nav id="site-navigation" class="rx-primary-navigation" aria-label="<?php esc_attr_e( 'Primary Navigation', 'rx-theme' ); ?>">
<?php $this->render_primary_menu(); ?>
</nav>
<div class="rx-header-actions">
<?php
if ( ! empty( $this->settings['enable_search'] ) ) {
$this->render_search_button();
}
if ( ! empty( $this->settings['enable_social_links'] ) ) {
$this->render_social_links();
}
if ( ! empty( $this->settings['enable_cta'] ) ) {
$this->render_cta_button();
}
if ( ! empty( $this->settings['enable_mobile_header'] ) ) {
$this->render_mobile_toggle();
}
?>
</div>
</div>
</div>
<?php
if ( ! empty( $this->settings['enable_search'] ) ) {
$this->render_search_overlay();
}
if ( ! empty( $this->settings['enable_mobile_header'] ) ) {
$this->render_mobile_panel();
}
?>
<?php do_action( 'rx_header_end' ); ?>
</header>
<?php
do_action( 'rx_after_header' );
}
/**
* Render mobile header only.
*
* @return void
*/
public function render_mobile_header() {
?>
<div class="rx-mobile-only-header">
<div class="<?php echo esc_attr( $this->settings['container_class'] ); ?>">
<div class="rx-mobile-header-inner">
<?php $this->render_branding(); ?>
<?php $this->render_mobile_toggle(); ?>
</div>
</div>
</div>
<?php
}
/**
* Render skip link.
*
* @return void
*/
private function render_skip_link() {
?>
<a class="rx-skip-link screen-reader-text" href="#content">
<?php esc_html_e( 'Skip to content', 'rx-theme' ); ?>
</a>
<?php
}
/**
* Render top bar.
*
* @return void
*/
private function render_top_bar() {
$left_text = $this->settings['top_bar_left_text'];
$right_text = $this->settings['top_bar_right_text'];
?>
<div class="rx-top-bar">
<div class="<?php echo esc_attr( $this->settings['container_class'] ); ?>">
<div class="rx-top-bar-inner">
<div class="rx-top-bar-left">
<?php
if ( ! empty( $left_text ) ) {
echo wp_kses_post( $left_text );
}
if ( has_nav_menu( 'topbar' ) ) {
wp_nav_menu(
array(
'theme_location' => 'topbar',
'menu_class' => 'rx-topbar-menu',
'container' => false,
'depth' => 1,
'fallback_cb' => false,
)
);
}
?>
</div>
<div class="rx-top-bar-right">
<?php
if ( ! empty( $right_text ) ) {
echo wp_kses_post( $right_text );
}
if ( ! empty( $this->settings['enable_social_links'] ) ) {
$this->render_social_links( 'topbar' );
}
?>
</div>
</div>
</div>
</div>
<?php
}
/**
* Render branding area.
*
* @return void
*/
private function render_branding() {
?>
<div class="rx-site-branding" <?php $this->schema_attr( 'Organization' ); ?>>
<?php
if ( has_custom_logo() ) {
the_custom_logo();
} else {
$this->render_text_logo();
}
?>
<?php if ( ! has_custom_logo() ) : ?>
<?php $this->render_site_description(); ?>
<?php endif; ?>
</div>
<?php
}
/**
* Render text logo fallback.
*
* @return void
*/
private function render_text_logo() {
$site_name = get_bloginfo( 'name' );
if ( is_front_page() && is_home() ) {
?>
<h1 class="rx-site-title">
<a href="<?php echo esc_url( home_url( '/' ) ); ?>" rel="home">
<?php echo esc_html( $site_name ); ?>
</a>
</h1>
<?php
} else {
?>
<p class="rx-site-title">
<a href="<?php echo esc_url( home_url( '/' ) ); ?>" rel="home">
<?php echo esc_html( $site_name ); ?>
</a>
</p>
<?php
}
}
/**
* Render site description.
*
* @return void
*/
private function render_site_description() {
if ( empty( $this->settings['enable_tagline'] ) ) {
return;
}
$description = get_bloginfo( 'description', 'display' );
if ( $description || is_customize_preview() ) {
?>
<p class="rx-site-description">
<?php echo esc_html( $description ); ?>
</p>
<?php
}
}
/**
* Render primary menu.
*
* @return void
*/
private function render_primary_menu() {
if ( has_nav_menu( 'primary' ) ) {
wp_nav_menu(
array(
'theme_location' => 'primary',
'menu_id' => 'primary-menu',
'menu_class' => 'rx-primary-menu',
'container' => false,
'fallback_cb' => false,
'depth' => 4,
)
);
} else {
$this->render_fallback_menu();
}
}
/**
* Render fallback menu.
*
* @return void
*/
private function render_fallback_menu() {
?>
<ul id="primary-menu" class="rx-primary-menu rx-fallback-menu">
<li>
<a href="<?php echo esc_url( home_url( '/' ) ); ?>">
<?php esc_html_e( 'Home', 'rx-theme' ); ?>
</a>
</li>
<?php
wp_list_pages(
array(
'title_li' => '',
'depth' => 1,
)
);
?>
</ul>
<?php
}
/**
* Render mobile toggle.
*
* @return void
*/
private function render_mobile_toggle() {
?>
<button
type="button"
class="rx-mobile-menu-toggle"
aria-controls="rx-mobile-panel"
aria-expanded="false"
aria-label="<?php esc_attr_e( 'Open mobile menu', 'rx-theme' ); ?>"
>
<span class="rx-toggle-line"></span>
<span class="rx-toggle-line"></span>
<span class="rx-toggle-line"></span>
</button>
<?php
}
/**
* Render mobile panel.
*
* @return void
*/
private function render_mobile_panel() {
?>
<div id="rx-mobile-panel" class="rx-mobile-panel" aria-hidden="true">
<div class="rx-mobile-panel-overlay"></div>
<div class="rx-mobile-panel-content" role="dialog" aria-modal="true" aria-label="<?php esc_attr_e( 'Mobile Menu', 'rx-theme' ); ?>">
<div class="rx-mobile-panel-header">
<?php $this->render_branding(); ?>
<button type="button" class="rx-mobile-panel-close" aria-label="<?php esc_attr_e( 'Close mobile menu', 'rx-theme' ); ?>">
<span aria-hidden="true">×</span>
</button>
</div>
<nav class="rx-mobile-navigation" aria-label="<?php esc_attr_e( 'Mobile Navigation', 'rx-theme' ); ?>">
<?php
if ( has_nav_menu( 'mobile' ) ) {
wp_nav_menu(
array(
'theme_location' => 'mobile',
'menu_class' => 'rx-mobile-menu',
'container' => false,
'fallback_cb' => false,
'depth' => 4,
)
);
} else {
wp_nav_menu(
array(
'theme_location' => 'primary',
'menu_class' => 'rx-mobile-menu',
'container' => false,
'fallback_cb' => array( $this, 'render_mobile_fallback_menu' ),
'depth' => 4,
)
);
}
?>
</nav>
<?php if ( ! empty( $this->settings['enable_search'] ) ) : ?>
<div class="rx-mobile-search">
<?php get_search_form(); ?>
</div>
<?php endif; ?>
<?php if ( ! empty( $this->settings['enable_cta'] ) ) : ?>
<div class="rx-mobile-cta">
<?php $this->render_cta_button(); ?>
</div>
<?php endif; ?>
<?php if ( ! empty( $this->settings['enable_social_links'] ) ) : ?>
<div class="rx-mobile-social">
<?php $this->render_social_links( 'mobile' ); ?>
</div>
<?php endif; ?>
</div>
</div>
<?php
}
/**
* Mobile fallback menu.
*
* @return void
*/
public function render_mobile_fallback_menu() {
?>
<ul class="rx-mobile-menu rx-fallback-menu">
<li>
<a href="<?php echo esc_url( home_url( '/' ) ); ?>">
<?php esc_html_e( 'Home', 'rx-theme' ); ?>
</a>
</li>
<?php
wp_list_pages(
array(
'title_li' => '',
'depth' => 2,
)
);
?>
</ul>
<?php
}
/**
* Render search button.
*
* @return void
*/
private function render_search_button() {
?>
<button
type="button"
class="rx-header-search-toggle"
aria-controls="rx-search-overlay"
aria-expanded="false"
aria-label="<?php esc_attr_e( 'Open search', 'rx-theme' ); ?>"
>
<span class="rx-search-icon" aria-hidden="true">
<?php $this->icon_svg( 'search' ); ?>
</span>
</button>
<?php
}
/**
* Render search overlay.
*
* @return void
*/
private function render_search_overlay() {
?>
<div id="rx-search-overlay" class="rx-search-overlay" aria-hidden="true">
<div class="rx-search-overlay-inner">
<button type="button" class="rx-search-close" aria-label="<?php esc_attr_e( 'Close search', 'rx-theme' ); ?>">
<span aria-hidden="true">×</span>
</button>
<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"
placeholder="<?php echo esc_attr( $this->settings['search_placeholder'] ); ?>"
value="<?php echo esc_attr( get_search_query() ); ?>"
name="s"
/>
<button type="submit" class="rx-search-submit">
<?php esc_html_e( 'Search', 'rx-theme' ); ?>
</button>
</form>
</div>
</div>
<?php
}
/**
* Render CTA button.
*
* @return void
*/
private function render_cta_button() {
$cta_text = $this->settings['cta_text'];
$cta_url = $this->settings['cta_url'];
$cta_target = $this->settings['cta_target'];
if ( empty( $cta_text ) || empty( $cta_url ) ) {
return;
}
$rel = '_blank' === $cta_target ? 'noopener noreferrer' : '';
?>
<a
class="rx-header-cta"
href="<?php echo esc_url( $cta_url ); ?>"
target="<?php echo esc_attr( $cta_target ); ?>"
<?php if ( $rel ) : ?>
rel="<?php echo esc_attr( $rel ); ?>"
<?php endif; ?>
>
<?php echo esc_html( $cta_text ); ?>
</a>
<?php
}
/**
* Render social links.
*
* @param string $context Context.
* @return void
*/
private function render_social_links( $context = 'header' ) {
$social_links = $this->settings['social_links'];
if ( empty( $social_links ) || ! is_array( $social_links ) ) {
return;
}
$has_link = false;
foreach ( $social_links as $url ) {
if ( ! empty( $url ) ) {
$has_link = true;
break;
}
}
if ( ! $has_link ) {
return;
}
?>
<div class="rx-social-links rx-social-links-<?php echo esc_attr( $context ); ?>">
<?php foreach ( $social_links as $network => $url ) : ?>
<?php if ( empty( $url ) ) : ?>
<?php continue; ?>
<?php endif; ?>
<a
class="rx-social-link rx-social-<?php echo esc_attr( sanitize_html_class( $network ) ); ?>"
href="<?php echo esc_url( $url ); ?>"
target="_blank"
rel="noopener noreferrer"
aria-label="<?php echo esc_attr( ucfirst( $network ) ); ?>"
>
<?php $this->icon_svg( $network ); ?>
</a>
<?php endforeach; ?>
</div>
<?php
}
/**
* Get header classes.
*
* @return array
*/
private function get_header_classes() {
$classes = array(
'rx-site-header',
'rx-header-builder',
'rx-header-layout-' . sanitize_html_class( $this->settings['header_layout'] ),
'rx-logo-position-' . sanitize_html_class( $this->settings['logo_position'] ),
'rx-menu-position-' . sanitize_html_class( $this->settings['menu_position'] ),
);
if ( ! empty( $this->settings['enable_sticky_header'] ) ) {
$classes[] = 'rx-sticky-header';
}
if ( ! empty( $this->settings['enable_transparent'] ) ) {
$classes[] = 'rx-transparent-header';
}
return apply_filters( 'rx_header_classes', $classes );
}
/**
* Schema attribute.
*
* @param string $type Schema type.
* @return void
*/
private function schema_attr( $type = '' ) {
if ( empty( $this->settings['enable_schema'] ) || empty( $type ) ) {
return;
}
echo 'itemscope itemtype="https://schema.org/' . esc_attr( $type ) . '"';
}
/**
* Inline CSS fallback.
*
* You can move this CSS into:
* assets/css/header-builder.css
*
* @return void
*/
private function inline_header_css() {
$css = '
.rx-container {
width: min(1200px, calc(100% - 32px));
margin-left: auto;
margin-right: auto;
}
.rx-skip-link {
position: absolute;
left: -9999px;
top: 10px;
background: #111;
color: #fff;
padding: 10px 16px;
z-index: 999999;
}
.rx-skip-link:focus {
left: 10px;
}
.rx-top-bar {
background: #0f172a;
color: #fff;
font-size: 14px;
}
.rx-top-bar a {
color: inherit;
text-decoration: none;
}
.rx-top-bar-inner {
display: flex;
align-items: center;
justify-content: space-between;
gap: 20px;
min-height: 38px;
}
.rx-site-header {
background: #fff;
border-bottom: 1px solid rgba(15, 23, 42, 0.08);
position: relative;
z-index: 999;
}
.rx-sticky-header {
position: sticky;
top: 0;
}
.admin-bar .rx-sticky-header {
top: 32px;
}
.rx-transparent-header {
background: transparent;
position: absolute;
left: 0;
right: 0;
top: 0;
}
.rx-header-inner {
display: flex;
align-items: center;
justify-content: space-between;
gap: 24px;
min-height: 82px;
}
.rx-site-branding {
display: flex;
align-items: center;
flex-direction: column;
align-items: flex-start;
min-width: 160px;
}
.rx-site-title {
margin: 0;
font-size: 28px;
line-height: 1.1;
font-weight: 800;
}
.rx-site-title a {
color: #0f172a;
text-decoration: none;
}
.rx-site-description {
margin: 4px 0 0;
font-size: 13px;
color: #64748b;
}
.rx-primary-navigation {
flex: 1;
}
.rx-primary-menu,
.rx-primary-menu ul,
.rx-mobile-menu,
.rx-mobile-menu ul {
list-style: none;
margin: 0;
padding: 0;
}
.rx-primary-menu {
display: flex;
align-items: center;
justify-content: flex-end;
gap: 6px;
}
.rx-primary-menu li {
position: relative;
}
.rx-primary-menu a {
display: block;
padding: 14px 12px;
color: #0f172a;
text-decoration: none;
font-weight: 600;
}
.rx-primary-menu a:hover,
.rx-primary-menu a:focus {
color: #2563eb;
}
.rx-primary-menu ul {
position: absolute;
top: 100%;
left: 0;
min-width: 220px;
background: #fff;
box-shadow: 0 14px 40px rgba(15, 23, 42, 0.14);
opacity: 0;
visibility: hidden;
transform: translateY(10px);
transition: all 0.2s ease;
z-index: 9999;
}
.rx-primary-menu li:hover > ul,
.rx-primary-menu li:focus-within > ul {
opacity: 1;
visibility: visible;
transform: translateY(0);
}
.rx-primary-menu ul ul {
top: 0;
left: 100%;
}
.rx-primary-menu ul a {
padding: 11px 14px;
font-weight: 500;
border-bottom: 1px solid rgba(15, 23, 42, 0.06);
}
.rx-header-actions {
display: flex;
align-items: center;
gap: 10px;
}
.rx-header-search-toggle,
.rx-mobile-menu-toggle,
.rx-search-close,
.rx-mobile-panel-close {
border: 0;
background: transparent;
cursor: pointer;
color: #0f172a;
}
.rx-header-search-toggle {
width: 42px;
height: 42px;
display: inline-flex;
align-items: center;
justify-content: center;
border-radius: 999px;
background: #f1f5f9;
}
.rx-header-cta {
display: inline-flex;
align-items: center;
justify-content: center;
min-height: 42px;
padding: 0 18px;
background: #2563eb;
color: #fff;
text-decoration: none;
font-weight: 700;
border-radius: 999px;
}
.rx-header-cta:hover,
.rx-header-cta:focus {
background: #1d4ed8;
color: #fff;
}
.rx-social-links {
display: flex;
align-items: center;
gap: 8px;
}
.rx-social-link {
display: inline-flex;
align-items: center;
justify-content: center;
width: 34px;
height: 34px;
border-radius: 999px;
background: #f1f5f9;
color: #0f172a;
text-decoration: none;
}
.rx-social-link svg,
.rx-header-search-toggle svg {
width: 18px;
height: 18px;
fill: currentColor;
}
.rx-mobile-menu-toggle {
display: none;
width: 44px;
height: 44px;
flex-direction: column;
align-items: center;
justify-content: center;
gap: 5px;
border-radius: 8px;
background: #f1f5f9;
}
.rx-toggle-line {
display: block;
width: 22px;
height: 2px;
background: currentColor;
}
.rx-search-overlay {
position: fixed;
inset: 0;
display: none;
align-items: center;
justify-content: center;
background: rgba(15, 23, 42, 0.86);
z-index: 99999;
}
.rx-search-overlay.is-active {
display: flex;
}
.rx-search-overlay-inner {
width: min(720px, calc(100% - 32px));
position: relative;
}
.rx-search-close {
position: absolute;
right: 0;
top: -60px;
color: #fff;
font-size: 42px;
}
.rx-search-form {
display: flex;
background: #fff;
border-radius: 12px;
overflow: hidden;
}
.rx-search-field {
flex: 1;
border: 0;
padding: 20px;
font-size: 18px;
outline: none;
}
.rx-search-submit {
border: 0;
background: #2563eb;
color: #fff;
padding: 0 24px;
font-weight: 700;
cursor: pointer;
}
.rx-mobile-panel {
position: fixed;
inset: 0;
display: none;
z-index: 99999;
}
.rx-mobile-panel.is-active {
display: block;
}
.rx-mobile-panel-overlay {
position: absolute;
inset: 0;
background: rgba(15, 23, 42, 0.65);
}
.rx-mobile-panel-content {
position: absolute;
top: 0;
right: 0;
width: min(380px, 88vw);
height: 100%;
background: #fff;
padding: 22px;
overflow-y: auto;
box-shadow: -20px 0 50px rgba(15, 23, 42, 0.18);
}
.rx-mobile-panel-header {
display: flex;
align-items: center;
justify-content: space-between;
gap: 16px;
margin-bottom: 24px;
}
.rx-mobile-panel-close {
font-size: 36px;
line-height: 1;
}
.rx-mobile-menu a {
display: block;
padding: 13px 0;
border-bottom: 1px solid rgba(15, 23, 42, 0.08);
color: #0f172a;
text-decoration: none;
font-weight: 600;
}
.rx-mobile-menu ul {
padding-left: 16px;
}
.rx-mobile-search,
.rx-mobile-cta,
.rx-mobile-social {
margin-top: 22px;
}
@media (max-width: 992px) {
.rx-primary-navigation,
.rx-header-actions .rx-social-links,
.rx-header-actions .rx-header-cta {
display: none;
}
.rx-mobile-menu-toggle {
display: inline-flex;
}
.rx-header-inner {
min-height: 72px;
}
}
@media (max-width: 782px) {
.admin-bar .rx-sticky-header {
top: 46px;
}
.rx-top-bar-inner {
flex-direction: column;
align-items: flex-start;
padding: 8px 0;
}
}
@media (max-width: 600px) {
.admin-bar .rx-sticky-header {
top: 0;
}
.rx-site-title {
font-size: 23px;
}
}
';
wp_add_inline_style( 'rx-header-builder', $css );
}
/**
* SVG icons.
*
* @param string $icon Icon name.
* @return void
*/
private function icon_svg( $icon ) {
$icon = sanitize_key( $icon );
switch ( $icon ) {
case 'search':
echo '<svg viewBox="0 0 24 24" aria-hidden="true"><path d="M21.71 20.29l-4.39-4.39A8.46 8.46 0 0019 10.5C19 5.81 15.19 2 10.5 2S2 5.81 2 10.5 5.81 19 10.5 19a8.46 8.46 0 005.4-1.68l4.39 4.39a1 1 0 001.42-1.42zM4 10.5C4 6.91 6.91 4 10.5 4S17 6.91 17 10.5 14.09 17 10.5 17 4 14.09 4 10.5z"></path></svg>';
break;
case 'facebook':
echo '<svg viewBox="0 0 24 24" aria-hidden="true"><path d="M13.5 22v-8h2.7l.4-3h-3.1V9.1c0-.9.2-1.5 1.5-1.5h1.7V4.9c-.3 0-1.3-.1-2.4-.1-2.4 0-4.1 1.5-4.1 4.2V11H7.5v3h2.7v8h3.3z"></path></svg>';
break;
case 'twitter':
echo '<svg viewBox="0 0 24 24" aria-hidden="true"><path d="M22 5.9c-.7.3-1.5.6-2.4.7.9-.5 1.5-1.3 1.8-2.3-.8.5-1.7.8-2.6 1A4.1 4.1 0 0015.8 4c-2.3 0-4.1 1.8-4.1 4.1 0 .3 0 .6.1.9A11.7 11.7 0 013.4 4.7a4 4 0 001.3 5.4c-.7 0-1.3-.2-1.9-.5v.1c0 2 1.4 3.6 3.3 4-.3.1-.7.1-1.1.1-.3 0-.5 0-.8-.1.5 1.7 2.1 2.9 3.9 2.9A8.3 8.3 0 012 18.3 11.7 11.7 0 008.3 20c7.5 0 11.6-6.2 11.6-11.6v-.5c.8-.6 1.5-1.3 2.1-2z"></path></svg>';
break;
case 'linkedin':
echo '<svg viewBox="0 0 24 24" aria-hidden="true"><path d="M6.9 21H3.6V9h3.3v12zM5.2 7.4A1.9 1.9 0 115.2 3.6a1.9 1.9 0 010 3.8zM21 21h-3.3v-5.8c0-1.4 0-3.2-1.9-3.2s-2.2 1.5-2.2 3.1V21h-3.3V9h3.1v1.6h.1c.4-.8 1.5-1.9 3.1-1.9 3.4 0 4 2.2 4 5.1V21z"></path></svg>';
break;
case 'youtube':
echo '<svg viewBox="0 0 24 24" aria-hidden="true"><path d="M21.6 7.2s-.2-1.5-.8-2.1c-.8-.8-1.6-.8-2-.9C16 4 12 4 12 4h0s-4 0-6.8.2c-.4.1-1.3.1-2 .9-.6.6-.8 2.1-.8 2.1S2 9 2 10.8v1.7c0 1.8.2 3.6.2 3.6s.2 1.5.8 2.1c.8.8 1.8.8 2.3.9 1.7.2 6.7.2 6.7.2s4 0 6.8-.2c.4-.1 1.3-.1 2-.9.6-.6.8-2.1.8-2.1s.2-1.8.2-3.6v-1.7c0-1.8-.2-3.6-.2-3.6zM10 14.8V8.6l5.8 3.1L10 14.8z"></path></svg>';
break;
case 'instagram':
echo '<svg viewBox="0 0 24 24" aria-hidden="true"><path d="M7.5 2h9A5.5 5.5 0 0122 7.5v9a5.5 5.5 0 01-5.5 5.5h-9A5.5 5.5 0 012 16.5v-9A5.5 5.5 0 017.5 2zm0 2A3.5 3.5 0 004 7.5v9A3.5 3.5 0 007.5 20h9a3.5 3.5 0 003.5-3.5v-9A3.5 3.5 0 0016.5 4h-9zM12 7a5 5 0 110 10 5 5 0 010-10zm0 2a3 3 0 100 6 3 3 0 000-6zm5.3-2.3a1.2 1.2 0 110 2.4 1.2 1.2 0 010-2.4z"></path></svg>';
break;
case 'github':
echo '<svg viewBox="0 0 24 24" aria-hidden="true"><path d="M12 2a10 10 0 00-3.2 19.5c.5.1.7-.2.7-.5v-1.8c-2.9.6-3.5-1.2-3.5-1.2-.5-1.1-1.1-1.4-1.1-1.4-.9-.6.1-.6.1-.6 1 .1 1.5 1 1.5 1 .9 1.5 2.3 1.1 2.9.8.1-.6.3-1.1.6-1.3-2.3-.3-4.7-1.2-4.7-5.1 0-1.1.4-2.1 1-2.8-.1-.3-.4-1.3.1-2.8 0 0 .8-.3 2.8 1a9.6 9.6 0 015.1 0c1.9-1.3 2.8-1 2.8-1 .5 1.5.2 2.5.1 2.8.6.7 1 1.6 1 2.8 0 4-2.4 4.9-4.7 5.1.4.3.7 1 .7 2V21c0 .3.2.6.7.5A10 10 0 0012 2z"></path></svg>';
break;
default:
echo '<span aria-hidden="true">' . esc_html( strtoupper( substr( $icon, 0, 1 ) ) ) . '</span>';
break;
}
}
}
endif;
/**
* Initialize RX Header Builder.
*
* @return RX_Header_Builder
*/
function rx_header_builder() {
return RX_Header_Builder::instance();
}
rx_header_builder();
/**
* Template function to render header.
*
* Use inside header.php:
*
* <?php rx_render_header(); ?>
*
* @return void
*/
function rx_render_header() {
do_action( 'rx_theme_header' );
}
/**
* Template function to render mobile header.
*
* @return void
*/
function rx_render_mobile_header() {
do_action( 'rx_theme_mobile_header' );
}
Use it inside header.php
In your theme header.php, use:
<?php
/**
* Theme Header
*
* @package RX_Theme
*/
?>
<!doctype html>
<html <?php language_attributes(); ?>>
<head>
<meta charset="<?php bloginfo( 'charset' ); ?>">
<meta name="viewport" content="width=device-width, initial-scale=1">
<?php wp_head(); ?>
</head>
<body <?php body_class(); ?>>
<?php wp_body_open(); ?>
<?php
if ( function_exists( 'rx_render_header' ) ) {
rx_render_header();
}
?>
<main id="content" class="site-content">
Optional JS file
Create:
assets/js/header-builder.js
Add this:
(function () {
'use strict';
const body = document.body;
function toggleAttribute(element, attribute, trueValue, falseValue) {
if (!element) return;
const current = element.getAttribute(attribute);
element.setAttribute(attribute, current === trueValue ? falseValue : trueValue);
}
function initMobileMenu() {
const toggle = document.querySelector('.rx-mobile-menu-toggle');
const panel = document.querySelector('#rx-mobile-panel');
const close = document.querySelector('.rx-mobile-panel-close');
const overlay = document.querySelector('.rx-mobile-panel-overlay');
if (!toggle || !panel) return;
function openMenu() {
panel.classList.add('is-active');
panel.setAttribute('aria-hidden', 'false');
toggle.setAttribute('aria-expanded', 'true');
body.classList.add('rx-mobile-menu-open');
}
function closeMenu() {
panel.classList.remove('is-active');
panel.setAttribute('aria-hidden', 'true');
toggle.setAttribute('aria-expanded', 'false');
body.classList.remove('rx-mobile-menu-open');
}
toggle.addEventListener('click', openMenu);
if (close) {
close.addEventListener('click', closeMenu);
}
if (overlay) {
overlay.addEventListener('click', closeMenu);
}
document.addEventListener('keydown', function (event) {
if (event.key === 'Escape') {
closeMenu();
}
});
}
function initSearchOverlay() {
const toggle = document.querySelector('.rx-header-search-toggle');
const overlay = document.querySelector('#rx-search-overlay');
const close = document.querySelector('.rx-search-close');
const field = document.querySelector('#rx-search-field');
if (!toggle || !overlay) return;
function openSearch() {
overlay.classList.add('is-active');
overlay.setAttribute('aria-hidden', 'false');
toggle.setAttribute('aria-expanded', 'true');
setTimeout(function () {
if (field) {
field.focus();
}
}, 120);
}
function closeSearch() {
overlay.classList.remove('is-active');
overlay.setAttribute('aria-hidden', 'true');
toggle.setAttribute('aria-expanded', 'false');
}
toggle.addEventListener('click', openSearch);
if (close) {
close.addEventListener('click', closeSearch);
}
overlay.addEventListener('click', function (event) {
if (event.target === overlay) {
closeSearch();
}
});
document.addEventListener('keydown', function (event) {
if (event.key === 'Escape') {
closeSearch();
}
});
}
function initStickyShadow() {
const header = document.querySelector('.rx-sticky-header');
if (!header) return;
function checkScroll() {
if (window.scrollY > 20) {
header.classList.add('rx-header-scrolled');
} else {
header.classList.remove('rx-header-scrolled');
}
}
checkScroll();
window.addEventListener('scroll', checkScroll, {
passive: true
});
}
document.addEventListener('DOMContentLoaded', function () {
initMobileMenu();
initSearchOverlay();
initStickyShadow();
});
})();
Optional extra CSS for sticky shadow
You can add this to style.css:
.rx-header-scrolled {
box-shadow: 0 10px 35px rgba(15, 23, 42, 0.12);
}
.rx-mobile-menu-open {
overflow: hidden;
}
How to customize header settings from functions.php
Example:
add_filter( 'rx_header_builder_settings', function( $settings ) {
$settings['enable_top_bar'] = true;
$settings['enable_sticky_header'] = true;
$settings['enable_search'] = true;
$settings['enable_cta'] = true;
$settings['top_bar_left_text'] = 'Welcome to RX Harun Medical Knowledge Platform';
$settings['cta_text'] = 'Contact Doctor';
$settings['cta_url'] = home_url( '/contact/' );
$settings['social_links']['facebook'] = 'https://facebook.com/';
$settings['social_links']['linkedin'] = 'https://linkedin.com/';
$settings['social_links']['youtube'] = 'https://youtube.com/';
return $settings;
} );
This gives your RX Theme a powerful, expandable header builder system.