Given a base theme called parenttheme
that is a child of stable
, and a sub-theme called childtheme
whose base theme is parenttheme
, a Twig template implemented in the parenttheme
theme renders the wrong value for the {{ directory }}
variable.
-
In the parent theme, add a node.html.twig template with the following content:
{# contents of parenttheme/templates/node.html.twig #}
file is themes/custom/parenttheme/templates/content/node.html.twig<br>
directory is: {{ directory }}
Leave node.html.twig
unimplemented in child theme, so that it inherits from parent.
-
Set default theme to
childtheme
.
-
Visiting node/1 will print:
file is themes/custom/parenttheme/templates/content/node.html.twig
directory is themes/custom/childtheme
In theory, step 3 should produce a value of themes/custom/parenttheme
for the directory variable, otherwise, how can you depend on that variable to reference URLs of additional assets from the parent theme?
In actuality, {{ directory }}
is acting exactly like {{ active_theme_path() }}
.
As I understand it, this basically means that you cannot use {{ directory }}
to reference any static assets in a base or parent theme, such as the path to an image icon, or using the {{ source() }}
Twig function to insert an inline SVG. In my case, I'm trying to do just this:
{{ source(directory ~ '/images/fluffy.svg') }}
But when I create my subtheme and visit the page, I get: Twig_Error_Loader: Template "themes/custom/childtheme/images/fluffy.svg" is not defined. Obviously, the fluffy.svg file only exists in the parent theme, next to the location of the node.html.twig template that references it. There is no reason fluffy.svg should need to be copied to the subtheme.
I initially wrote this up as a question on Stack Overflow to see if anyone had any input, but no one answered. In the end I found my own workaround.
Workaround
The workaround is to implement hook_preprocess() and set a global template variable called themename_directory
that points to the parent theme path.
// @file parenttheme.theme
/**
* Prepares global variables for all templates.
*/
function parenttheme_preprocess(&$variables) {
$handler = \Drupal::service('theme_handler');
$variables['parenttheme_directory'] = $handler->getTheme('parenttheme')->getPath();
}
{# @file parenttheme/templates/node.html.twig #}
{{ source( parenttheme_directory ~ 'images/fluffy.svg') }}