Problem/Motivation
Core's Responsive Image styles can be configured to generate a single <img srcset>
element with multiple image URLs in the srcset
attribute (instead of generating a <picture>
with multiple <source>
elements.)
This is handy if you just want the browser to pick the best image based on resolution, rather than explicitly telling the browser exactly which image to use at a certain breakpoint (e.g., for "art direction" style crops).
Unfortunately, Media Contextual Crop doesn't set the `img_element` attributes properly in this case, so the contextual URLs are never used. This means contextual settings don't ever get applied when the images are viewed.
Steps to reproduce
1. In your theme's mytheme.breakpoints.yml file, create a "Viewport" breakpoint that doesn't use a media query:
mytheme.viewport:
label: Viewport
mediaQuery: ''
weight: -1
multipliers:
- 1x
2. Configure a Responsive Image style that only uses the Viewport option.
2a. For that option, choose "Select multiple image styles and use the sizes attribute"
2b. Specify multiple focal point and crop image styles.
3. Configure a content type with a media contextual crop field.
3b. In the full content display, use the Responsive Image formatter and set it to render using your newly created Responsive Image style in step 2.
4. Create a node, add an image, and view the source of the page.
You'll see something like this:
<img loading="lazy" srcset="/sites/default/files/styles/3x4__focal_point_scale_and_crop__sm/public/2025-01/test__png/123456.png?itok=abc, /sites/default/files/styles/3x4__focal_point_scale_and_crop__md/public/2025-01/test__png/123456.png?itok=def, /sites/default/files/styles/3x4__focal_point_scale_and_crop__lg/public/2025-01/test__png/123456.png?itok=ghi" alt="">
The URLs should have `contextual` in them, like: /sites/default/files/contextual/styles/3x4__focal_point_scale_and_crop__sm/public/2025-01/test__png/123456.png?itok=abc
Proposed resolution
The patch simply makes sure that the newly generated URLs are set on $variables['img_element']['#attributes']['srcset']
, overwriting the original URLs.
Not entirely sure if this will have negative side effects. It works in my testing.