site-branding.php

I’ll build this as a strong, reusable site-branding.php template part for your RX theme: logo, site title, tagline, schema, dark/light logo support, sticky/header states, accessibility, fallback SVG, hooks, and safe filters.

Yes friend — create this file:

rx-theme/template-parts/header/site-branding.php

This is an advanced RX Theme site branding template part with custom logo, dark logo, mobile logo, retina logo support, site title, tagline, schema markup, accessibility, hooks, filters, fallback SVG text logo, search-engine friendly markup, and many future extension points. It uses official WordPress functions like get_custom_logo(), has_custom_logo(), bloginfo(), and get_theme_mod() for safe theme integration.

<?php
/**
 * Template part: Site Branding
 *
 * File: template-parts/header/site-branding.php
 *
 * @package RX_Theme
 *
 * Features:
 * - WordPress custom logo support
 * - Optional dark logo
 * - Optional mobile logo
 * - Optional retina logo
 * - Site title fallback
 * - Tagline support
 * - SEO friendly homepage h1 / inner-page p logic
 * - Schema.org Organization / WebSite microdata
 * - Accessibility support
 * - Lazy/eager loading control
 * - Width / height attributes
 * - Customizer-ready theme mods
 * - Filters and hooks for future extension
 * - Safe escaping everywhere
 */

defined( 'ABSPATH' ) || exit;

/**
 * ------------------------------------------------------------
 * Basic site data
 * ------------------------------------------------------------
 */

$rx_site_name        = get_bloginfo( 'name' );
$rx_site_description = get_bloginfo( 'description', 'display' );
$rx_home_url         = home_url( '/' );
$rx_is_front         = is_front_page() && is_home();
$rx_is_home          = is_front_page();

/**
 * ------------------------------------------------------------
 * Theme mod options
 * ------------------------------------------------------------
 *
 * You may later register these in Customizer.
 */

$rx_show_title = (bool) get_theme_mod( 'rx_show_site_title', true );
$rx_show_desc  = (bool) get_theme_mod( 'rx_show_site_description', true );

$rx_branding_layout = get_theme_mod( 'rx_branding_layout', 'logo-title-tagline' );
// Options idea:
// logo-only
// title-only
// logo-title
// logo-title-tagline
// stacked
// inline
// centered

$rx_branding_alignment = get_theme_mod( 'rx_branding_alignment', 'left' );
// left, center, right

$rx_logo_position = get_theme_mod( 'rx_logo_position', 'before-title' );
// before-title, above-title, after-title

$rx_logo_loading = get_theme_mod( 'rx_logo_loading', 'eager' );
// eager is better for header logo because it appears above the fold.

$rx_logo_decoding = get_theme_mod( 'rx_logo_decoding', 'async' );

$rx_logo_fetchpriority = get_theme_mod( 'rx_logo_fetchpriority', 'high' );

$rx_enable_schema = (bool) get_theme_mod( 'rx_branding_enable_schema', true );

$rx_enable_dark_logo = (bool) get_theme_mod( 'rx_enable_dark_logo', true );

$rx_enable_mobile_logo = (bool) get_theme_mod( 'rx_enable_mobile_logo', true );

$rx_enable_retina_logo = (bool) get_theme_mod( 'rx_enable_retina_logo', true );

$rx_enable_fallback_svg = (bool) get_theme_mod( 'rx_enable_fallback_svg_logo', true );

$rx_site_title_tag_front = get_theme_mod( 'rx_site_title_tag_front', 'h1' );
$rx_site_title_tag_inner = get_theme_mod( 'rx_site_title_tag_inner', 'p' );

$rx_title_tag = $rx_is_home ? $rx_site_title_tag_front : $rx_site_title_tag_inner;

$rx_allowed_title_tags = array( 'h1', 'h2', 'h3', 'p', 'div', 'span' );

if ( ! in_array( $rx_title_tag, $rx_allowed_title_tags, true ) ) {
	$rx_title_tag = $rx_is_home ? 'h1' : 'p';
}

/**
 * ------------------------------------------------------------
 * Logo IDs from Customizer / theme mods
 * ------------------------------------------------------------
 *
 * WordPress default custom logo ID:
 * get_theme_mod( 'custom_logo' )
 *
 * Extra optional IDs:
 * rx_dark_logo
 * rx_mobile_logo
 * rx_retina_logo
 */

$rx_default_logo_id = absint( get_theme_mod( 'custom_logo' ) );
$rx_dark_logo_id    = absint( get_theme_mod( 'rx_dark_logo' ) );
$rx_mobile_logo_id  = absint( get_theme_mod( 'rx_mobile_logo' ) );
$rx_retina_logo_id  = absint( get_theme_mod( 'rx_retina_logo' ) );

/**
 * ------------------------------------------------------------
 * Logo image data helper
 * ------------------------------------------------------------
 */

if ( ! function_exists( 'rx_theme_get_logo_image_data' ) ) {
	/**
	 * Get logo attachment data safely.
	 *
	 * @param int    $attachment_id Attachment ID.
	 * @param string $size Image size.
	 * @return array
	 */
	function rx_theme_get_logo_image_data( $attachment_id, $size = 'full' ) {
		$attachment_id = absint( $attachment_id );

		if ( ! $attachment_id ) {
			return array();
		}

		$image = wp_get_attachment_image_src( $attachment_id, $size );

		if ( empty( $image[0] ) ) {
			return array();
		}

		$alt = get_post_meta( $attachment_id, '_wp_attachment_image_alt', true );

		if ( empty( $alt ) ) {
			$alt = get_bloginfo( 'name' );
		}

		return array(
			'id'     => $attachment_id,
			'url'    => esc_url( $image[0] ),
			'width'  => isset( $image[1] ) ? absint( $image[1] ) : '',
			'height' => isset( $image[2] ) ? absint( $image[2] ) : '',
			'alt'    => sanitize_text_field( $alt ),
		);
	}
}

/**
 * ------------------------------------------------------------
 * Prepare logo image data
 * ------------------------------------------------------------
 */

$rx_default_logo = rx_theme_get_logo_image_data( $rx_default_logo_id, 'full' );
$rx_dark_logo    = rx_theme_get_logo_image_data( $rx_dark_logo_id, 'full' );
$rx_mobile_logo  = rx_theme_get_logo_image_data( $rx_mobile_logo_id, 'full' );
$rx_retina_logo  = rx_theme_get_logo_image_data( $rx_retina_logo_id, 'full' );

/**
 * ------------------------------------------------------------
 * Classes
 * ------------------------------------------------------------
 */

$rx_branding_classes = array(
	'rx-site-branding',
	'rx-branding',
	'rx-branding--layout-' . sanitize_html_class( $rx_branding_layout ),
	'rx-branding--align-' . sanitize_html_class( $rx_branding_alignment ),
	'rx-branding--logo-position-' . sanitize_html_class( $rx_logo_position ),
);

if ( has_custom_logo() ) {
	$rx_branding_classes[] = 'rx-branding--has-logo';
} else {
	$rx_branding_classes[] = 'rx-branding--no-logo';
}

if ( $rx_show_title ) {
	$rx_branding_classes[] = 'rx-branding--has-title';
}

if ( $rx_show_desc && ! empty( $rx_site_description ) ) {
	$rx_branding_classes[] = 'rx-branding--has-description';
}

if ( $rx_enable_dark_logo && ! empty( $rx_dark_logo['url'] ) ) {
	$rx_branding_classes[] = 'rx-branding--has-dark-logo';
}

if ( $rx_enable_mobile_logo && ! empty( $rx_mobile_logo['url'] ) ) {
	$rx_branding_classes[] = 'rx-branding--has-mobile-logo';
}

if ( $rx_enable_retina_logo && ! empty( $rx_retina_logo['url'] ) ) {
	$rx_branding_classes[] = 'rx-branding--has-retina-logo';
}

$rx_branding_classes = apply_filters( 'rx_theme_site_branding_classes', $rx_branding_classes );

$rx_branding_class_attr = implode( ' ', array_map( 'sanitize_html_class', $rx_branding_classes ) );

/**
 * ------------------------------------------------------------
 * Attributes
 * ------------------------------------------------------------
 */

$rx_branding_attrs = array(
	'class' => $rx_branding_class_attr,
	'role'  => 'banner',
);

if ( $rx_enable_schema ) {
	$rx_branding_attrs['itemscope'] = 'itemscope';
	$rx_branding_attrs['itemtype']  = 'https://schema.org/Organization';
}

$rx_branding_attrs = apply_filters( 'rx_theme_site_branding_attributes', $rx_branding_attrs );

$rx_attr_html = '';

foreach ( $rx_branding_attrs as $attr_key => $attr_value ) {
	if ( '' === $attr_value || null === $attr_value || false === $attr_value ) {
		continue;
	}

	if ( true === $attr_value ) {
		$rx_attr_html .= ' ' . esc_attr( $attr_key );
	} else {
		$rx_attr_html .= ' ' . esc_attr( $attr_key ) . '="' . esc_attr( $attr_value ) . '"';
	}
}

/**
 * ------------------------------------------------------------
 * Hook before branding
 * ------------------------------------------------------------
 */

do_action( 'rx_theme_before_site_branding' );
?>

<div<?php echo $rx_attr_html; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?>>

	<?php
	/**
	 * Hook inside branding before content.
	 */
	do_action( 'rx_theme_site_branding_before_content' );
	?>

	<a
		class="rx-branding__link"
		href="<?php echo esc_url( $rx_home_url ); ?>"
		rel="home"
		aria-label="<?php echo esc_attr( sprintf( __( 'Go to %s homepage', 'rx-theme' ), $rx_site_name ) ); ?>"
		<?php echo $rx_enable_schema ? 'itemprop="url"' : ''; ?>
	>
		<?php if ( has_custom_logo() && ! empty( $rx_default_logo['url'] ) ) : ?>

			<span class="rx-branding__logo-wrap">

				<img
					class="rx-branding__logo rx-branding__logo--default"
					src="<?php echo esc_url( $rx_default_logo['url'] ); ?>"
					alt="<?php echo esc_attr( $rx_default_logo['alt'] ); ?>"
					<?php echo ! empty( $rx_default_logo['width'] ) ? 'width="' . esc_attr( $rx_default_logo['width'] ) . '"' : ''; ?>
					<?php echo ! empty( $rx_default_logo['height'] ) ? 'height="' . esc_attr( $rx_default_logo['height'] ) . '"' : ''; ?>
					loading="<?php echo esc_attr( $rx_logo_loading ); ?>"
					decoding="<?php echo esc_attr( $rx_logo_decoding ); ?>"
					fetchpriority="<?php echo esc_attr( $rx_logo_fetchpriority ); ?>"
					<?php echo $rx_enable_schema ? 'itemprop="logo"' : ''; ?>
				/>

				<?php if ( $rx_enable_dark_logo && ! empty( $rx_dark_logo['url'] ) ) : ?>
					<img
						class="rx-branding__logo rx-branding__logo--dark"
						src="<?php echo esc_url( $rx_dark_logo['url'] ); ?>"
						alt="<?php echo esc_attr( $rx_dark_logo['alt'] ); ?>"
						<?php echo ! empty( $rx_dark_logo['width'] ) ? 'width="' . esc_attr( $rx_dark_logo['width'] ) . '"' : ''; ?>
						<?php echo ! empty( $rx_dark_logo['height'] ) ? 'height="' . esc_attr( $rx_dark_logo['height'] ) . '"' : ''; ?>
						loading="<?php echo esc_attr( $rx_logo_loading ); ?>"
						decoding="<?php echo esc_attr( $rx_logo_decoding ); ?>"
						aria-hidden="true"
					/>
				<?php endif; ?>

				<?php if ( $rx_enable_mobile_logo && ! empty( $rx_mobile_logo['url'] ) ) : ?>
					<img
						class="rx-branding__logo rx-branding__logo--mobile"
						src="<?php echo esc_url( $rx_mobile_logo['url'] ); ?>"
						alt="<?php echo esc_attr( $rx_mobile_logo['alt'] ); ?>"
						<?php echo ! empty( $rx_mobile_logo['width'] ) ? 'width="' . esc_attr( $rx_mobile_logo['width'] ) . '"' : ''; ?>
						<?php echo ! empty( $rx_mobile_logo['height'] ) ? 'height="' . esc_attr( $rx_mobile_logo['height'] ) . '"' : ''; ?>
						loading="<?php echo esc_attr( $rx_logo_loading ); ?>"
						decoding="<?php echo esc_attr( $rx_logo_decoding ); ?>"
						aria-hidden="true"
					/>
				<?php endif; ?>

				<?php if ( $rx_enable_retina_logo && ! empty( $rx_retina_logo['url'] ) ) : ?>
					<span
						class="rx-branding__retina-source"
						data-retina-logo="<?php echo esc_url( $rx_retina_logo['url'] ); ?>"
						aria-hidden="true"
					></span>
				<?php endif; ?>

			</span>

		<?php elseif ( $rx_enable_fallback_svg ) : ?>

			<span class="rx-branding__fallback-logo" aria-hidden="true">
				<svg
					class="rx-branding__fallback-svg"
					width="56"
					height="56"
					viewBox="0 0 56 56"
					role="img"
					focusable="false"
					xmlns="http://www.w3.org/2000/svg"
				>
					<rect width="56" height="56" rx="14"></rect>
					<text
						x="50%"
						y="54%"
						text-anchor="middle"
						dominant-baseline="middle"
						font-size="20"
						font-weight="700"
					>
						<?php
						$rx_initials = '';
						$rx_words    = preg_split( '/\s+/', trim( $rx_site_name ) );

						if ( ! empty( $rx_words ) ) {
							foreach ( $rx_words as $rx_word ) {
								$rx_initials .= mb_substr( $rx_word, 0, 1 );
								if ( mb_strlen( $rx_initials ) >= 2 ) {
									break;
								}
							}
						}

						echo esc_html( mb_strtoupper( $rx_initials ) );
						?>
					</text>
				</svg>
			</span>

		<?php endif; ?>

		<?php if ( $rx_show_title || ( $rx_show_desc && ! empty( $rx_site_description ) ) ) : ?>
			<span class="rx-branding__text">
				<?php if ( $rx_show_title && ! empty( $rx_site_name ) ) : ?>
					<<?php echo tag_escape( $rx_title_tag ); ?> class="rx-branding__title site-title" <?php echo $rx_enable_schema ? 'itemprop="name"' : ''; ?>>
						<?php echo esc_html( $rx_site_name ); ?>
					</<?php echo tag_escape( $rx_title_tag ); ?>>
				<?php endif; ?>

				<?php if ( $rx_show_desc && ! empty( $rx_site_description ) ) : ?>
					<span class="rx-branding__description site-description">
						<?php echo esc_html( $rx_site_description ); ?>
					</span>
				<?php endif; ?>
			</span>
		<?php endif; ?>

	</a>

	<?php
	/**
	 * Hidden schema meta.
	 */
	if ( $rx_enable_schema ) :
		?>
		<meta itemprop="name" content="<?php echo esc_attr( $rx_site_name ); ?>">
		<meta itemprop="url" content="<?php echo esc_url( $rx_home_url ); ?>">
		<?php if ( ! empty( $rx_site_description ) ) : ?>
			<meta itemprop="description" content="<?php echo esc_attr( $rx_site_description ); ?>">
		<?php endif; ?>
	<?php endif; ?>

	<?php
	/**
	 * Hook inside branding after content.
	 */
	do_action( 'rx_theme_site_branding_after_content' );
	?>

</div>

<?php
/**
 * Hook after branding.
 */
do_action( 'rx_theme_after_site_branding' );

Add this in your header.php where you want the branding to show:

<?php get_template_part( 'template-parts/header/site-branding' ); ?>

Also make sure your inc/core/theme-setup.php or functions.php has custom logo support:

<?php
/**
 * RX Theme setup.
 */

defined( 'ABSPATH' ) || exit;

add_action( 'after_setup_theme', 'rx_theme_setup' );

function rx_theme_setup() {

	add_theme_support( 'title-tag' );

	add_theme_support(
		'custom-logo',
		array(
			'height'      => 80,
			'width'       => 260,
			'flex-height' => true,
			'flex-width'  => true,
			'unlink-homepage-logo' => true,
		)
	);

	add_theme_support( 'post-thumbnails' );

	add_theme_support( 'html5', array(
		'search-form',
		'comment-form',
		'comment-list',
		'gallery',
		'caption',
		'style',
		'script',
	) );
}

Optional CSS for style.css:

.rx-site-branding {
	display: flex;
	align-items: center;
	min-width: 0;
}

.rx-branding__link {
	display: inline-flex;
	align-items: center;
	gap: 12px;
	text-decoration: none;
	color: inherit;
	min-width: 0;
}

.rx-branding__logo-wrap {
	display: inline-flex;
	align-items: center;
	position: relative;
	flex-shrink: 0;
}

.rx-branding__logo {
	display: block;
	max-width: 220px;
	width: auto;
	height: auto;
	max-height: 72px;
}

.rx-branding__logo--dark,
.rx-branding__logo--mobile {
	display: none;
}

.rx-branding__text {
	display: flex;
	flex-direction: column;
	line-height: 1.15;
	min-width: 0;
}

.rx-branding__title {
	margin: 0;
	font-size: clamp(1.25rem, 2vw, 2rem);
	font-weight: 800;
	letter-spacing: -0.02em;
	color: inherit;
}

.rx-branding__description {
	margin-top: 4px;
	font-size: 0.875rem;
	opacity: 0.78;
	color: inherit;
}

.rx-branding--align-center {
	justify-content: center;
	text-align: center;
}

.rx-branding--align-right {
	justify-content: flex-end;
	text-align: right;
}

.rx-branding--layout-stacked .rx-branding__link,
.rx-branding--logo-position-above-title .rx-branding__link {
	flex-direction: column;
	align-items: flex-start;
}

.rx-branding--align-center.rx-branding--layout-stacked .rx-branding__link,
.rx-branding--align-center.rx-branding--logo-position-above-title .rx-branding__link {
	align-items: center;
}

.rx-branding--align-right.rx-branding--layout-stacked .rx-branding__link,
.rx-branding--align-right.rx-branding--logo-position-above-title .rx-branding__link {
	align-items: flex-end;
}

.rx-branding__fallback-svg rect {
	fill: currentColor;
	opacity: 0.12;
}

.rx-branding__fallback-svg text {
	fill: currentColor;
}

@media (prefers-color-scheme: dark) {
	.rx-branding--has-dark-logo .rx-branding__logo--default {
		display: none;
	}

	.rx-branding--has-dark-logo .rx-branding__logo--dark {
		display: block;
	}
}

@media (max-width: 768px) {
	.rx-branding__logo {
		max-width: 170px;
		max-height: 56px;
	}

	.rx-branding--has-mobile-logo .rx-branding__logo--default,
	.rx-branding--has-mobile-logo .rx-branding__logo--dark {
		display: none;
	}

	.rx-branding--has-mobile-logo .rx-branding__logo--mobile {
		display: block;
	}

	.rx-branding__title {
		font-size: 1.25rem;
	}

	.rx-branding__description {
		font-size: 0.78rem;
	}
}

Important: this file is ready, but dark logo, mobile logo, and retina logo need Customizer fields later using these theme mod names:

rx_dark_logo
rx_mobile_logo
rx_retina_logo
rx_show_site_title
rx_show_site_description
rx_branding_layout
rx_branding_alignment
rx_logo_position
rx_branding_enable_schema

Leave a Reply

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