24

I want to render an image as a background image via an inline style in twig. I created a field called bg_image and attached it to the standard plain page.

After fiddling around for hours I was able to get the Image URL in node.html.twig

{{ file_url(node.field_bg_image.0.entity.uri.value) }}

but I could not get it to work inside field--field-bg_image.html.twig

Can I get the node from there anyhow, so I can then get the image?

How can I get the image URL to use as inline style? I thought maybe I can pass a variable from field--field-bg_image.html.twig to image.html.twig and then just render

{{ uri }}

instead of

<img{{ attributes.addClass(classes) }} />

but I could not get it to pass the variable there unless I use includes

{% include 'image.html.twig' with {'image': image, 'isFromField': isFromField} %}

(isFromField is true, when it comes from the field--field-bg_image.html.twig) But that didn't work either. The Image was never rendered that way.

Would be very glad if you can help - my php knowledge is very basic. Thanks

1

7 Answers 7

36

The variable node is only preloaded in the node template (and the page template, if the url contains the node). Now if you want to access node fields in a field template you have to look in a different place:

field.html.twig:

{{ file_url(element['#object'].field_image.0.entity.uri.value) }}

element['#object'] is the parent entity in a field template and you can access any field from this entity (in your case the node).

If you want to access raw values from the actual field, it's better to follow the logic of the field twig and access the value inside of the items loop directly from the field item object #item:

{% for item in items %}
  {{ file_url(item.content['#item'].entity.uri.value) }}
{% endfor %}

Edit: Get the url of an image style

Install the module Twig Tweak and you can use the uri to get the url of an image style:

{% for item in items %}
  {{ item.content['#item'].entity.uri.value | image_style('thumbnail') }}
{% endfor %}
2
  • Great that works! Thank you. Is it also possible, to get it in a specific image style? (large or thumbnail) Commented Dec 29, 2015 at 17:00
  • Thanks! I looked everywhere for how to do this. I am new to Drupal - It boggles the mind why this property is not more easily accessible Commented Feb 7, 2020 at 18:46
32

Just to mention that if you want to do the same in one of the new custom blocks this works:

{{ file_url(content.field_image['#items'].entity.uri.value) }}
4
  • This works for block field.
    – Alex
    Commented May 5, 2016 at 14:24
  • 4
    And also this code works for image paragraph field in paragraph's twig template. Commented Mar 13, 2018 at 16:24
  • Yes! Thanks. This works when you're trying to get the image url from the content image field on paragraph templates as well.
    – Robb Davis
    Commented Apr 3, 2018 at 16:09
  • Does not work for views Commented Oct 10, 2018 at 6:44
3

I use this code in my .theme file:

function THEMENAME_preprocess_node(&$variables) {

  if ($variables['node']->field_image->entity) {
      $variables['image_url'] = $url = entity_load('image_style', 'medium')->buildUrl($variables['node']->field_image->entity->getFileUri());
  }
}

It could be improved. I'm checking for the image field, and loading its url with an image style.

Then in my node--page.html.twig file I have this:

{% if image_url is not empty %}
    <div class="featured-thumb">
        <img src="{{ image_url }}"/>
    </div>
{% endif %}

<div>{{ content.body|without('field_image') }}</div>

Again, that could use some improvement. thanks

1
  • 1
    This works for a regular image upload field. But it does not work for a entity reference image field. Commented Sep 22, 2017 at 11:30
1

I'd do it another way. In your node preprocess function :

use Drupal\image\Entity\ImageStyle; // Don't forget this use.

function THEMENAME_preprocess_node__NODETYPE(&$variables){
    $node = $variables['node'];

    if(isset($node->get('field_image')->entity)){
        $image_style = 'large'; // Or whatever your image style's machine name is.
        $style = ImageStyle::load($style);
        $variables['image'] = $style->buildUrl($node->get('field_image')->entity->getFileUri()); // Generates file url.
    }
}

Then, in your template (node--NODETYPE.html.twig), just render the image that way :

{% if image %}
    <img src="{{ image }}" />
{% endif %}

Although, if you ever have to render a big amount of images, I'd advise you to load the styles in an array before you loop on each images. I'm saying that because I've ran into serious load time problems because I had to load over 300 images and for each image, I was loading the style individually instead of loading them all before, here's an example, same base as above :

use Drupal\image\Entity\ImageStyle; // Don't forget this use.

function THEMENAME_preprocess_node__NODETYPE(&$variables){
    $node = $variables['node'];

    if(isset(node->get('field_images')[0]->entity)){ // Notice how, this time, I check if the FIRST image is set (if it's true, then u'll allow the loop for at least 1 element)
        $images_styles = [
            'large' => ImageStyle::load('large'),
            'thumbnail' => ImageStyle::load('thumbnail')
        ];
        $count = 0;

        foreach($node->get('field_images') as $image){
            $variables['images'][$count]['large'] = $images_styles['large']->buildUrl($image->getFileUri());
            $variables['images'][$count]['thumbnail'] = $images_styles['thumbnail']->buildUrl($image->getFileUri());
            $count++;
        }
    }
}

Then again, in your template (node--NODETYPE.html.twig), just render the images that way :

{% if images %}
    <ul>
        {% for image in images %}
            <li>
                <img src="{{ image.large }}" /> // Large image url.
                <img src="{{ image.thumbnail }}" /> // Thumbnail image url.
            </li>   
        {% endfor %}
    </ul>
{% endif %}

I haven't really tested it and I'm getting all this out of my head so it might contain errors, feel free to warn me so I'll correct this :-).

0

For maintainability, I'd recommend using preprocess function for this. For Drupal 8, 9 & 10:

function template_preprocess_node(array &$variables) {
  foreach (Element::children($variables['elements']) as $key) {
    if ($variables['elements']['node']->field_image->entity) {
      $style = \Drupal::entityTypeManager()->getStorage('image_style')->load('medium');
      $variables['image'] = $style->buildUrl($variables['elements']['node']->field_image->entity->getFileUri());
    }
  }
}

Then, in Twig:

{{ image }} // prints https://mysite.com/sites/default/files/styles/medium/public/image.jpg

Source: https://stefvanlooveren.me/blog/get-url-image-drupal-9-10-image-style-twig

0

After spending two days I found some answer to my similar code. With including and excluding some fields.

{%
set classes = [
'block',
'block-' ~ configuration.provider|clean_class,
'block-' ~ plugin_id|clean_class,
'cover-image',
]
%}

{% set background_image = file_url(content.field_banner_image['#items'].entity.uri.value) %}

<div{{ attributes.addClass(classes) }} style="background-image: 
url({{background_image}})">

<div class="block-inner">
{{ title_prefix }}
{% if label %}
<h2{{ title_attributes }}>{{ label }}</h2>
{% endif %}
{{ title_suffix }}
{% block content %}
{{ content.field_media_image }}
<div class="summary">
{{ content|without('field_banner_image') }}
</div>
{% endblock %}
</div>
</div>

fine name in theme block--bundle--banner-block.html.twig This code is for custom block with images.

Another Example for simple file. not Pesting whole code, but only essential.

<a href="{{file_url(node.field_attachment1.entity.uri.value)  }}" ><h3> 
{{content.field_short_information}} </h3></a>

This code snippets for node node--all_notice.html.twig. All things currently working in drupal 8.8.3

below code work in Drupal 9 for getting image url

{{file_url(node.field_auditreport.entity.field_obsimg.entity.uri.value)}}
-2

I've had some success using the Background Image Module when the use case allows for it. I use one of these code options when I need a customized DOM structure.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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