Preprocessing and modifying attributes in the .theme file
As in Drupal 7, you can influence the output of specific HTML using preprocess functions. For example, if you want to add a class to a menu and prefer to do it at the PHP level, you can. This is a good way to alter theme-related markup, but if you're making changes unrelated to the theme, it's better to write a custom module.
(Note: For documentation purposes here, “mytheme” is your theme’s machine name; for example, “bartik” is the machine name for the Bartik theme.)
To work with preprocess functions:
1. Create or edit a file in your theme’s directory called mytheme.theme
2. Create a function like mytheme_preprocess_HOOK, where HOOK refers to the element you want to target*
3. Write your changes and save
4. Rebuild cache so your changes take effect (if you have Drush installed, run drush cr
in the command line)
* HOOK names follow the Twig template naming conventions. To create a hook for page.html.twig, write mytheme_preprocess_page
. To create a hook for a node – article.html.twig, use mytheme_preprocess_node__article
(replacing dashes with underscores). To find hook names, see the section on Finding template files using debugging.
Let’s assume we want to add a my-menu
class to all menus on your site. Assuming your theme is called “mytheme”, you’d write the following function:
/** * Implements hook_preprocess_HOOK() for menu.html.twig. */ function mytheme_preprocess_menu(&$variables) { // If there is not an existing class array, create an empty array. if (!isset($variables['attributes']['class'])) { $variables['attributes']['class'] = []; } // Merge with any classes that may have been set by other hook_preprocess_menu invocations $variables['attributes']['class'] = array_merge($variables['attributes']['class'], ['my-menu']); }
This is very similar to Drupal 7 and helpful if you want to customize a targeted menu.
You can check the $variables
object conditionally to determine which menu you’re working with. Items inside $variables
become available in Twig after the theme preprocess runs.
Now to extend our example, let’s say we want to add a my-main-menu
class specifically to the main menu on your site. This would be the function:
/** * Implements hook_preprocess_HOOK() for menu.html.twig. */ function mytheme_preprocess_menu(&$variables) { if ($variables['menu_name'] == 'main') { if (!isset($variables['attributes']['class'])) { $variables['attributes']['class'] = []; } $variables['attributes']['class'] = array_merge($variables['attributes']['class'], ['my-main-menu']); } }
Differences from Drupal 7
The template.php file no longer exists. It has been replaced by mytheme.theme. However, it still functions in much the same way, allowing hooks to alter output.