Multiple headers

I’m having some trouble figuring out how to use different headers depending on the template. I’m using ACF to let the user decide the image to show on the banner and this is configurable at page and category levels. The call to get the correct value differs in each case:

if ( is_front_page() ) {
        $image = get_field( 'hero_image' ) ?: false;
} elseif ( is_category() ) {
        $image = get_field( 'banner_image', 'category_' . get_query_var( 'cat' ) ) ?: false;

<div class="banner-image" style="background-image: url(<?= $image['url'] ?>);">

I have this code in header.php, but I’m sure there must be a smarter way to do it. Since the header is included in the wrapper, does this mean I need different base files (base-front-page.php and base-category.php), set the variable $image on each and then include header.php (which would only have the markup to display the image)?

I would now have 3 different base files, all very similar except for the line that gets the banner image url. I think I would be repeating myself quite a lot.

Do you any suggestions on how to improve this? I hope I could get my point across. Thanks in advance!

You most certainly do not need multiple base.php files.

You said this is in your header.php, so why can’t it stay there?

If you want to have the logic to get the banner image extracted away from your template, why not put it in a function? Then it can grow as needed and you can keep the same base.php and header.php


$image = Roots\Sage\Extras\get_header_image();

if ($image) : ?>
<div class="banner-image" style="background-image: url(<?= $image['url'] ?>);">
<?php endif; ?>

function get_header_image() {
  if (is_front_page()) {
    return get_field('hero_image');
  } elseif (is_category()) {
    return get_field('banner_image', 'category_' . get_query_var( 'cat' ));
  else {
    return get_field('hero_image');

A few things to note, I always thought you needed to put ternary statements in rounded brackets. Perhaps it is not required if you aren’t getting any errors or warnings. But I don’t think that’s even necessary, since if there is no image added, ACF should return false anyways.

1 Like

My problem was to have that code in the template because I have similar if statements in a couple other places like the breadcrumbs and sidebar and this makes it more difficult to maintain. Moving it to functions in extras makes sense, to keep all changes on a single place.

Thanks for the suggestion!

This proved very useful to me, though I wound up using it slightly differently to add a hero image to the banner in header.php, by leveraging the Featured Image .

lib/extras.php :

    function banner_image() {
            // set default header background image
            $banner_image = get_stylesheet_directory_uri() . ('/dist/images/caffe_gelato_4664.jpg');
            $fullheight = false;
            if ( has_post_thumbnail() ) {
                    $banner_image = first( wp_get_attachment_image_src( get_post_thumbnail_id( is_home() ? get_option('page_for_posts') : null), 'full' ) );
                    $fullheight = true;
            return array( 'img' => $banner_image, 'is_hero' => $fullheight );
    function first( $ary ) { return $ary[0]; } ?>


            use Roots\Sage\Extras; 
            $cg_featured = Extras\banner_image();
            $heroclass = $cg_featured['is_hero'] ? 'hero' : '';

    if ( has_nav_menu('topbar_menu')) : ?>
    <section id="topbar" class="topclass">
    <?php wp_nav_menu(array(
                    'theme_location' => 'topbar_menu', 
                    'menu_class' => 'sf-menu',
                    'container' => 'nav'
            )); ?>
    <?php endif; ?>
    <!-- fixed navbar -->
    <header class="banner mb-4 <?php echo $heroclass ?>" style="background-image: url('<?php echo $cg_featured['img']; ?>');">
            <div class="container-fluid bg-faded">
                    <nav class="navbar navbar-toggleable-md navbar-inverse">
                            <button class="navbar-toggler navbar-toggler-right" type="button" data-toggle="collapse"
                                    data-target="#navbarSupportedContent" aria-controls="navbarSupportedContent" aria-expanded="false"
                                    aria-label="Toggle navigation">
                                    <span class="navbar-toggler-icon"></span>
                            <a class="navbar-brand" href="<?php echo esc_url( home_url('/') ) ?>"><?php echo Extras\site_brand(); ?></a>
                            <div class="collapse navbar-collapse" id="navbarSupportedContent">
                                    <?php if (has_nav_menu('primary_navigation')) :
                                    wp_nav_menu( array('theme_location' => 'primary_navigation', 'walker' => new wp_bootstrap_navwalker(), 'menu_class' => 'navbar-nav nav pull-right')); 
                                    endif; ?>

and in the css just add .banner.hero { height: 100vh; } and you’re done.

Hopefully this helps someone else as well.