Theme hook suggestions

A great thing about theme hooks is that they are reusable. However, one problem you'll encounter is that theme hook templates lose context when a theme hook is reused. For example, the item_list theme hook, whose definition we saw in the previous section, has no idea what list it is theming. And this makes it difficult to style differently depending on what that content is. Fortunately, we can provide context to the theme system by using a theme hook pattern instead of the original theme hook name, and this pattern looks something like this:

base_theme_hook__some_context 

The parts of the pattern are separated with a double underscore and together they are called a theme hook suggestion. But how does this work?

Client code (the render arrays, as we will soon see), when using a theme hook to render a piece of data, can append the context to the theme hook, turning it into a suggestion. The theme system will then check for the following:

In this case, the caller (the render array) is responsible for "proposing" a suggestion. For example, consider the following render array:

return [
'#theme' => 'item_list__my_list',
'#items' => $items,
];

The base theme hook is item_list, which is rendered using the item-list.html.twig template file provided by Drupal core. If there is no item-list—my-list.html.twig template file in the theme, and there is no item_list__my_list theme hook registered, the default item_list theme hook will be used. Otherwise, we will follow the order that I mentioned before. A module can register that suggestion as a hook, which will be used instead. However, a theme can override that further by just creating the template file with that name.

And all this is done so that when rendering something with a reusable theme hook, we give the possibility to themers and manipulators to determine what exactly is being themed. However, the example we saw just now is static in the sense that we hardcoded my_list as the theme hook suggestion. We can do better than that.

A module that registers a theme hook can also provide a list of suggestions that should go with that theme hook automatically. It does so by implementing hook_theme_suggestions_HOOK(), where HOOK is the theme hook name. This hook is fired at runtime by the theme system, trying to determine how a certain render array needs to be rendered. It receives the same $variables array as an argument as the template preprocessors do. This means that we can make use of those variables and dynamically provide theme hook suggestions. We will see an example of this later in the chapter.

Moreover, as module developers, we can also provide a list of theme hook suggestions to theme hooks registered by other modules or Drupal core. We can do so by implementing hook_theme_suggestions_HOOK_alter(), where we receive the available suggestions for that theme hook in addition to the variables.

In summary, theme hook suggestions are a powerful way of adding some context to the generic theme hooks that are responsible for rendering multiple things.