
Drupal Custom Theme Suggestions for Views Explained (With Code Example)
Customizing Theme Suggestions for Drupal Views
In Drupal theming, having control over how views render is essential for building clean, maintainable, and specific templates. One powerful tool Drupal gives us is the ability to provide theme suggestions—and in this blog post, we’ll explore how to extend these suggestions for Views using hook_theme_suggestions_HOOK().
Here’s a real-world example where we dynamically add template suggestions based on the view ID, display ID, and even the current route.
What Are Theme Suggestions?
Theme suggestions are essentially ways to tell Drupal: “Hey, if you find a template file named like this, use it instead.” Drupal will look for these template files in the order provided. This allows developers to override templates in a very targeted manner—for example, rendering a views-view-fields differently depending on which View or Display is being shown.
The Custom Hook
Here’s the custom implementation we’ll walk through:
File:
themes/custom/mcs/mcs.theme

/**
* Implements hook_theme_suggestions_HOOK() for views_view.
*/
function mcs_theme_suggestions_alter(array &$suggestions, array $variables, $hook)
{
switch ($hook) {
case "views_view_unformatted":
$suggestions[] = 'views_view_unformatted__' . $variables['view']->id();
break;
case "views_view":
$suggestions[] = 'views_view__' . $variables['view']->id();
break;
case "views_view_fields":
$suggestions[] = 'views_view_fields';
if (!empty($variables['view']->current_display)) {
$suggestions[] = 'views_view_fields__' . str_replace('-', '_', $variables['view']->current_display);
}
$request = \Drupal::routeMatch()->getRouteObject() ? \Drupal::routeMatch()->getRouteObject()->getDefault('view_id') : '';
if (!empty($request)) {
$suggestions[] = 'views_view_fields__' . str_replace('-', '_', $request);
}
$view_bundle = null;
if (!empty($variables['view']->element['#view_id'])) {
$view_bundle = str_replace('-', '_', $variables['view']->element['#view_id']);
}
if ($view_bundle) {
$suggestions[] = 'views_view_fields__' . $view_bundle;
}
if (!empty($variables['view']->element['#view_id'])) {
$view_bundle = str_replace('-', '_', $variables['view']->element['#view_id']);
if (!empty($variables['view']->current_display)) {
$suggestions[] = 'views_view_fields__' . $view_bundle . '__' . str_replace('-', '_', $variables['view']->current_display);
}
}
break;
}
}
What This Code Does
Let’s break it down:
Case 1: views_view_unformatted
Adds a suggestion like:
views-view-unformatted--your_view_id.html.twig
Case 2: views_view
Adds a suggestion like:
views-view--your_view_id.html.twig
Case 3: views_view_fields
Adds multiple layered suggestions depending on:
- The current display (page_1, block_1, etc.)
- The view ID from route defaults
- The view element metadata
This results in suggestions like:
views-view-fields--block_1.html.twig
views-view-fields--your_view_id.html.twig
views-view-fields--your_view_id--block_1.html.twig
Each of these gives you granular control over the rendering of individual views.
Why Use This?
- Custom Templates: Easily target a view’s output with a unique template.
- Maintainability: Keep your if/else logic out of Twig by having the right template in the first place.
- Performance: Avoid rendering unnecessary logic by directly routing to the right file.
Final Thoughts
This kind of theme suggestion logic is perfect for sites that heavily rely on Views and want tailored control over their rendering. As always with Drupal, power comes with complexity—but this hook helps simplify your theming process once you understand it.
Comments
Add new comment