Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

More robust output for art-direction use cases #330

Open
MattWilcox opened this issue Apr 22, 2022 · 2 comments
Open

More robust output for art-direction use cases #330

MattWilcox opened this issue Apr 22, 2022 · 2 comments

Comments

@MattWilcox
Copy link

MattWilcox commented Apr 22, 2022

Is your feature request related to a problem? Please describe.

Best practice is to have width and height attributes on images, so that the browser can reserve layout space prior to asset download, decode, and render. That's fine as long as all <source> definitions deliver an image that's the same aspect ratio as the <img> - you can just plop the width and height on the <img> and call it done.

You need to do more when the sources are delivering differently cropped variants at different breakpoints - the width and height values on the img may be "wrong" for the source that is to be applied; resulting in the incorrect space being reserved for layout, and a resulting shift once the asset is loaded.

You'd want this sort of Picture behaviour when you're adapting an element in a design to do more than just scale objects at different breakpoints. e.g., shifting an image+text "card" so that the image is a thin strip running vertically on some views, but horizontally on others. etc.

source when used in picture supports both width and height properties to achieve mitigation of layout jank in these cases - Image Optimize doesn't seem to output this, or really offer a way to do this manually, from what I can see in the docs.

Describe the solution you would like

I want to be able to solve for art-directed transforms by being able to output markup along these lines:

<picture>
  <!-- prefer webp, list these first. Order matters, first media to match is what's rendered - opposite of CSS rules -->
  <source media="(max-width: 359px)" srcset="..." type="image/webp" width="370" height="370"><!-- square -->
  <source media="(min-width: 680px)" srcset="..." type="image/webp" width="960" height="540"><!-- very landscape -->
  <source media="(min-width: 360px)" srcset="..." type="image/webp" width="700" height="525"><!-- landscape -->

  <!-- jpg fallbacks -->
  <source media="(max-width: 359px)" srcset="..." type="image/jpeg" width="370" height="370">
  <source media="(min-width: 680px)" srcset="..." type="image/jpeg" width="960" height="540">
  <source media="(min-width: 360px)" srcset="..." type="image/jpeg" width="700" height="525">
															
  <img
    loading="lazy"
    decoding="async"
    src="..."
    width="960"
    height="540" 
    alt=""
  >
</picture>

I've been able to do this with Imager / ImagerX but can't see how in Image Optimize.

Further, as I'm not 100% sure what browsers are doing in order to actually achieve this, I have in the past been using generated CSS to force this behaviour, by looping through the transformed assets to create CSS rules that will apply the correct aspect-ratio before the picture element is loaded - which again, I can't see how to accomplish with Image Optimizer:

<style>
  /* We're in CSS now so order is opposite: last match is applied */
  @media screen and (min-width: 360px) { #image-20-3689108 img { aspect-ratio: 1.3333333333333; } }
  @media screen and (min-width: 680px) { #image-20-3689108 img { aspect-ratio: 1.7777777777778; } }
  @media screen and (max-width: 359px) { #image-20-3689108 img { aspect-ratio: 1; } }
</style>
  
<picture id="image-20-3689108">
  <!-- prefer webp, list these first. Order matters, first media to match is what's rendered - opposite of CSS rules -->
  <source media="(max-width: 359px)" srcset="..." type="image/webp" width="370" height="370"><!-- square -->
  <source media="(min-width: 680px)" srcset="..." type="image/webp" width="960" height="540"><!-- very landscape -->
  <source media="(min-width: 360px)" srcset="..." type="image/webp" width="700" height="525"><!-- landscape -->

  <!-- jpg fallbacks -->
  <source media="(max-width: 359px)" srcset="..." type="image/jpeg" width="370" height="370">
  <source media="(min-width: 680px)" srcset="..." type="image/jpeg" width="960" height="540">
  <source media="(min-width: 360px)" srcset="..." type="image/jpeg" width="700" height="525">
															
  <img
    loading="lazy"
    decoding="async"
    src="..." 
    width="960"
    height="540"
    alt=""
  />
</picture>
@S-n-d
Copy link

S-n-d commented Sep 8, 2022

This would be a great enhancement! You've made a clear description of the use case @MattWilcox. This will probably also help for lighthouse layout shift score? https://web.dev/cls/#layout-shift-score

@khalwat
Copy link
Contributor

khalwat commented Sep 9, 2022

So you can definitely this manually already with ImageOptimize, but I agree it'd be nice to have it done in a more automated way.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants