22

I have a question about getting a path to an image in a Twig template. The image is not assigned to a field or something. Just a static image which is stored in "MYTHEME/image/icon/my-icon.png".

In Drupal 7 I get the path in my node.template with the following code:

<img src="<?php print base_path() . path_to_theme(); ?>/image/icons">/my-icon.png

How does it work with in Drupal 8? I tried to pass a variable in template_preprocess_node().

MYTHEME.theme:

$variables['images_path'] = \Drupal::theme()->getActiveTheme()->getPath() . '/image/';

Twig template:

<img src="{{ images_path  ~ 'icons/' ~ 'my-icon.png' }}">

It doesn't work. There is no PHP error, but the path is wrongly said to be http://localhost/node/themes/template/image/icons/my-icon.png.

  • "the path is wrong" - that's not very helpful :) Also you should do the preprocessing in the theme's theme file, not in the global tmeplate_preprocess_hook function and you should use drupal_get_path('theme', 'yourtheme'). – user21641 Dec 16 '15 at 10:26
  • @user21641 drupal_get_path is for D7 :) – Chapabu Dec 16 '15 at 11:30
  • 1
    It's for 8 too @Chapabu ... – Clive Dec 16 '15 at 11:43
  • Well blow me down with a feather! Colour me corrected :) – Chapabu Dec 16 '15 at 12:04
  • It is indeed for D8 as well. I've used it likes this : $themePath = Url::fromUserInput('/' . drupal_get_path('theme', '[themename]') – Vodde Dec 17 '15 at 14:56
51

you can use {{ base_path ~ directory }} which will fix the absolute problem, no need to do any preprocessing, both of these variables are included by core.

For example

<img src="{{ base_path ~ directory }}/images/logo.png" alt="My Logo" />

PS. the ~ helper in twig is concatenate.

Edit: at least in the page*.html.twig templates base_path variable is included, possibly you will need to do preprocessing for other templates, you can easily check with {{ dump() }} if the variables are present

// File: THEMENAME.theme in your theme's root directory
function THEMENAME_preprocess(&$variables, $hook)
{
    $variables['base_path'] = base_path();
}
  • 2
    Thanks for sharing your solution. One quick comment: I had to explicitly add $variables['base_path'] = base_path(); to my THEME_preprocess_html theme hook to make it available to the html.html.twig template file. – Marcos Buarque Feb 23 '17 at 9:53
  • Be careful about using {{ directory }} Twig variable in a theme that you intend to use as a base theme and create sub-themes for: drupal.stackexchange.com/questions/277278 – JamesWilson Mar 4 at 20:45
  • The twig template suggestions module provides {{ base_bath }} to every template; otherwise for some templates you'll have to do as Marcos Buarque did in the above comment, or Matoeil did in drupal.stackexchange.com/a/238535/4195 – mlncn 12 hours ago
8

There is by default a {{ directory }} variable that you can use that points to your theme directory. The problem is, it's not absolute, just like the one you added. I think that's a bug in core because it should include the base path, but changing that would of course break existing sites that use it.

So you need to add a / in front of it; this would break if Drupal is installed in a subfolder. You can either hardcode that in your template or keep using base_path() as you did in 7.x in a custom variable.

  • How to use image from /sites/default/files/MyFolder ? I have a image MyImage.jpg in MyFolder. Now, in twig template if i wrote <img src={{ url }} alt={{ text }}> Here url variable has the path /MyFolder/MyImage.jpg but, it is not working. – Jasodeep Chatterjee May 27 '16 at 9:29
  • 2
    As Berdir wrote: one can simply use <img src="/{{ directory }}/path/to/image"/> to get an absolute path. – daniels May 11 '17 at 20:38
6
<img src="/{{ directory }}/images/logo.png"/> 

worked for me when

<img src="{{ base_path ~ directory }}/images/logo.png" alt="My Logo" />

did not

for content template, i had to use in .module

   function hook_preprocess(&$variables, $hook) {

  $module_handler = Drupal::service('module_handler');
  $path = $module_handler->getModule('myModuleName')->getPath();

  if(isset($variables['region']) && $variables['region'] == 'content'){
    $variables['module_path'] = $path;
    $variables['http_host'] = $_SERVER['HTTP_HOST'];

and

  <img src="{{ module_path }}/images/error404.png" />
  <img src="//{{ http_host }}/{{ module_path }}/images/error403.png" />
  • 3
    This answer should be marked as correct instead – Jignesh Rawal Oct 8 '18 at 15:18

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.