I wish to use an inline style to add a dynamically generated background image URL to a div, e.g.
$build[0] = [
'#type' => 'container',
'#attributes' => [
'id' => 'thumbnail-image',
// the example below is a YouTube thumbnail, to be cropped using other CSS
'style' => sprintf('background-image: url("https://img.youtube.com/vi/1234567890/sddefault.jpg");', $video),
]
];
return $build;
The XSS filtering silently drops style
attributes. Can I disable that for an individual render array, or otherwise work around it?
Note: this is generating output for a Field Formatter, used in a view.
The official advice is:
If your markup needs any of the tags not in this whitelist, then you can implement a theme hook and/or an asset library. Alternatively, you can use the key #allowed_tags to alter which tags are filtered.
Things tried:
1) using a theme hook and a template
Here's my template:
<div class="test" style="background-image:url('https://img.youtube.com/vi/{{ video_id }}/sddefault.jpg');">Sample output</div>
It's working, except the style attribute is still being stripped out.
2) #allowed_tags (but it's not a tag, it's an attribute):
'#allowed_tags' => array_merge(\Drupal\Component\Utility\Xss::getAdminTagList(), ['style']),
Successful workaround:
This code is in a field formatter for views, so I overrode the default views template. The views templates allowed a style
attribute to pass through as I would have expected.
Initially I made a template for one specific field, but the problem was I needed to access the values of a separate field too and it was proving hard/impossible to retrieve them with the row._entity
variable.
So then I decided to use views-view-fields.html.twig
instead, which gives access to all the fields. This took rather longer, but as my code had a couple of conditionals and some variables used more than once, on balance the end result is cleaner than doing everything in the UI. (It's worth leaving yourself a note in the view UI admin comment and any docs that the view field is overwritten.)