Creating a hero page template in Drupal


  • Using Panopoly + Panels + Panelizer

Our current sub-pages look like this:

Screen Shot 2015-04-30 at 3.56.24 PM


Drupal is really good at having a consistent header throughout the site. But what if you want to have a landing page that looks like this:

Screen Shot 2015-04-30 at 3.58.00 PM

At first this seemed impossible to me, but after reading about theme_hook_suggestions and preprocess functions, I began to see the light.

  1. Create Hero Landing Page content type with appropriate fields
  2. Create image style to ensure the image is always the right size for the hero area
  3. Add theme_preprocess_page function to grab the image from the node
  4. Add a theme_hook_suggestion to load a different page template file
  5. Disable the hero image field in the default panels
  6. Profit

1. Create Hero Landing Page content type with appropriate fields

You don’t technically have to create a separate content type, but you do need a specific field to hold your hero image. I created a separate content type for landing pages because our landing pages will have some differences from basic pages within our system.

First thing I needed to do was create a “Hero Landing Page” content type that would be able to crank these types of pages out. Within this content type, I created a “Hero Image” field that would be used to hold the appropriate image. Keep note of the “field_landingpage_hero_image” field. That’s what we’ll need later to grab our image.

fields2. Create an image style for the hero image

If you don’t create an image style, you’ll be stuck with Drupal’s defaults which probably won’t suit your needs. In our case, we need the hero image to be 1920px x 768px in order to fit nicely within the theme. Navigate to admin/config/media/image-styles and create a new Image Style called “Landing Page Hero Image”. Under “Effect” choose “Scale and crop” and enter in 1920 for the width and 768 for the height. Once we apply this image style to the hero image field, this will take any image the user uploads and wrangle it into those dimensions.


3 + 4. Pull out the hero image so we can use it within our page template file & and a theme_hook_suggestion

Using Drupal’s hook system, we can override the template_preprocess_page() function to grab the hero image (if it exists) and make it accessible to the page template file. The way template_preprocess_page works is, you substitute your theme’s machine name for the word ‘template’, and pass in a reference to the $variable’s array. Now within the function you can play with the variables that Drupal is about to render on the page.

* Implements template_preprocess_page().
function oswego_preprocess_page(&$variables) {

  // Check to see if a hero image field is set
  if (isset($variables['node']->field_landingpage_hero_image[LANGUAGE_NONE][0])) {

    // Store the image into $img for easy reference
    $img = $variables['node']->field_landingpage_hero_image[LANGUAGE_NONE][0];

    // Build the $hero array to be used in templates/page/page--hero.tpl.php
    $variables['hero']['path'] = image_style_url('landing_page_hero_image', $img['uri']);
    $variables['hero']['alt'] = $img['alt'];
    $variables['hero']['title'] = $img['title'];

    // Add a theme hook suggestion to load templates/page/page--hero.tpl.php
    $variables['theme_hook_suggestions'][] = 'page__hero';

Note the function ‘image_style_url’ that is being called. The first parameter takes the machine name of an image style. In our case, we created our image style in step 2, so I’ll use the machine name of that image style. The function will then return the URL of the image using the specified image style.

By making a $variables[‘hero’] array, we can now access items within it on our page template file using $hero. For example, $hero[‘path’] will point to the URL that image_style_url built in our preprocess function. You can see within the code comments above that I make reference to a file called page–hero.tpl.php. By adding ‘page__hero’ to $variables[‘theme_hook_suggestions’], Drupal will now look for a page template file named page–hero.tpl.php.

Copy your existing page.tpl.php and name it page–hero.tpl.php. I won’t go into the specifics of how I used CSS to style it, but now it is possible to add the hero image in the new page–hero.tpl.php file. Example:

<div class="hero-image">
  <img src="<?php print $hero['path']; ?>" alt="<?php print $hero['alt']; ?>" title="<?php print $hero['title']; ?>">
  <?php if ($title): ?>
    <div class="hero-header">

    <div class="row">
      <div class="section-title-container">
        <div class="section-title-inner">
          <?php print $breadcrumb; ?>

    <h1 class="hero-title"><?php print $title; ?></h1>
  <?php endif; ?>

Disable the Hero Image within your panels configuration

This step will differ greatly depending on how you’re using panels/panelizer. For us, we have a default template that the content type goes into. By default I disabled the node:field_landingpage_hero_image pane so that the image wouldn’t display twice and confuse editors.


And that’s all! Quite a different process than I’m used to when I used to make WordPress themes, but still very effective. Drupal’s powerful hook system allows you to tap into the process and modify data, giving a themer and developer a ton of control. Drupal’s ability to separate logic (template.php) from the theme (*.tpl.php) files is pretty nice as well.

What do you think?