21

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

28

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 %}
  • Great that works! Thank you. Is it also possible, to get it in a specific image style? (large or thumbnail) – Jannis Hell Dec 29 '15 at 17:00
24

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) }}
  • This works for block field. – Alex May 5 '16 at 14:24
  • And also this code works for image paragraph field in paragraph's twig template. – Vadim Sudarikov Mar 13 '18 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 Apr 3 '18 at 16:09
  • Does not work for views – Jignesh Rawal Oct 10 '18 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
    This works for a regular image upload field. But it does not work for a entity reference image field. – paulcap1 Sep 22 '17 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 :-).

-1

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, privacy policy and cookie policy

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