{{ directory }} in Twig template resolves the directory of the child theme rather than that of the parent theme

Created on 19 April 2019, over 5 years ago
Updated 26 January 2023, almost 2 years ago

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.

  1. 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.

  2. Set default theme to childtheme.
  3. 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') }}
🐛 Bug report
Status

Active

Version

10.1

Component
Theme 

Last updated 4 days ago

Created by

🇪🇨Ecuador jwilson3

Live updates comments and jobs are added and updated live.
Sign in to follow issues

Comments & Activities

Not all content is available!

It's likely this issue predates Contrib.social: some issue and comment data are missing.

  • 🇨🇦Canada lolcode

    I think that there is a documentation or missing API issue. I can use namespaces to include other templates.
    However, I can't seem to find a Twig function to resolve a namespaced path so that I can print an image link.
    For example in my base theme I want to do this:

    <img
      src="@mytheme/library/01-atoms/file-type-icons/images/{{ extension }}.png" alt="{{ extension }} file format"
      class="{{ classes|join(' ') }}">
  • 🇮🇳India phpsubbarao

    @mytheme/ is the best on in twig file.

  • 🇪🇨Ecuador jwilson3

    Updated issue summary to describe both workarounds.

Production build 0.71.5 2024