How to add page templates for content types in Drupal 8

The problem

Sometimes you need to create a page template for a specific content type so that you can customise it. Drupal allows you to create content types for node templates out of the box by following the naming convention node--content-type.html.twig. But things aren’t so simple for page templates. Drupal does not automatically detect page templates for content types purely based on the naming convention. Fortunately it just takes a few lines of code and you can create a page template for any content type you choose.

Before we start, let’s take a brief look at the difference between a node and a page template.

 Page: the template that controls the whole page. This will include a $content variable, which after rendering will be the node.
 Node: the template that controls just the content part of the page.

A solution

To tell Drupal to use the page template for a content type, you can implement hook\_theme\_suggestions\_page\_alter(). This hook is used whenever a page.tpl.php template is used and allows you to suggest alternative templates.

In this case, you are going to use hook_theme_suggestions_page_alter() to tell Drupal to use a specific page template for a specific content type, instead of the default page.tpl.php.

Here is an example of how to tell Drupal to use a template for a content type. Add this code to the example.theme file in your theme, and change hook to the name of your theme. If you have already implemented theme_preprocess_page in your theme’s template.php, you can add the 'if' statement to that.

Here is the solution:

/**
 * Implements hook_theme_suggestions_page_alter().
 */
function example_theme_suggestions_page_alter(array &$suggestions, array $variables) {
  if ($node = \Drupal::routeMatch()->getParameter('node')) {
    $suggestions[] = 'page__' . $node->bundle();
  }
}

The solution explained

In this example, you are telling Drupal that you’d like to use a template with the name of the content type when a page is being viewed. Example templates include:

  • page--article.html.twig for a article content type
  • page--gallery.html.twig for a gallery content type

This is added to 'theme_hook_suggestions', which adds it to the pool of potential templates that Drupal can use. In most cases it will use this one, unless you have another template that meets a more specific criteria. For example, you might have a page template for a single node, which would be more specific and used instead. To add a new theme suggestion, implement hook_theme_suggestions_page_alter() in your theme’s .theme file.

Another example, if you have a theme named example, open the file called example.theme (or create one if it doesn’t exist). And then adding the the following function.

function example_theme_suggestions_page_alter(array &$suggestions, array $variables)  

And inside that function, check that you are viewing a node with:

if ($node = \Drupal::routeMatch()->getParameter('node')) {

And finally, add the naming convention to the theme suggestions with:

$suggestions[] = 'page__' . $node->bundle();

$node->bundle(); will return the name of the content type. So the suggested page template for the article content type will be:

page__article

The complete steps

  1. Open example.theme (replace example with your actual theme name)
  2. Add the code snippet below
  3. Replace example in the function name example_theme_suggestions_page_alter with your actual theme name
  4. Refresh the cache

The complete code in example.theme once again is:

/**
 * Implements hook_theme_suggestions_page_alter().
 */
function example_theme_suggestions_page_alter(array &$suggestions, array $variables) {
  if ($node = \Drupal::routeMatch()->getParameter('node')) {
    $suggestions[] = 'page__' . $node->bundle();
  }
}