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

Eleventy Transform: transform <img> inside of <picture> with other sources. #214

Closed
zachleat opened this issue Feb 13, 2024 · 7 comments
Closed
Assignees
Labels
enhancement New feature or request

Comments

@zachleat
Copy link
Member

Or better: optimize and replace instances of <picture>.

#208

@zachleat zachleat added the enhancement New feature or request label Feb 13, 2024
@what1s1ove
Copy link

Hey @zachleat !

Could you please tell me if this will help solve the following problem:

Often, I need to have a picture element in advance to apply a class to it.

.intro__picture {}

But this leads to a nested picture element appearing in the markup after the plugin has processed it.

<picture class="intro__picture"> <!-- My picture element -->
  <picture> <!-- The picture element from 11ty plugin -->
    <img />
  </picture>
</picture>

As a result, I have to remove the picture element I wrote and rely on the one created by the plugin after it processes. However, writing styles in this case becomes difficult.

.intro picture {}

Sometimes, there is more than one image in a block, which means additional wrappers need to be created, etc. It seems to me that it would be good if the picture element that appears after the plugin is processed either took all the attributes from the current picture element, or if the plugin completely ignored creating a picture element if one already exists in the markup.

@ItsEthanH
Copy link

ItsEthanH commented Jun 12, 2024

Just bumping this up as I'm having the same issue @what1s1ove is.

If there was a way to add classes to the <picture>s generated from the Transform Plugin, it would make the usability of the plugin that much better.

I know this plugin does something similar:
https://github.com/saneef/eleventy-plugin-img2picture

Perhaps we can add a hoistClass option to the image config? Or maybe an attribute override, similar to eleventy:widths or eleventy:formats? Or both?

@zachleat zachleat added this to the Eleventy Image v6.0.0 milestone Dec 20, 2024
@zachleat zachleat changed the title Eleventy Transform: ignore <img> inside of <picture> with other sources. Eleventy Transform: transform <img> inside of <picture> with other sources. Dec 20, 2024
@zachleat zachleat self-assigned this Dec 20, 2024
@zachleat
Copy link
Member Author

zachleat commented Jan 2, 2025

Support for optimizing <picture> will ship in v6.0.0-beta.1, e.g.

<picture class="outer"><source type="image/webp" srcset="./bio-2017.webp 1280w"><img src="./bio-2017.jpg" alt="My ugly mug" class="inner"></picture>

transforms to (when more than one entry in formats is in play):

<picture class="outer"><source type="image/webp" srcset="/img/KkPMmHd3hP-1280.webp 1280w"><img src="/img/KkPMmHd3hP-1280.jpeg" alt="My ugly mug" class="inner" width="1280" height="853"></picture>

Note that attributes on picture and img are preserved.

When only one entry is in formats and picture is not needed, the above transforms to:

<img src="/img/KkPMmHd3hP-1280.jpeg" alt="My ugly mug" class="inner" width="1280" height="853">

(picture is discarded)

@dwkns
Copy link

dwkns commented Jan 8, 2025

With reference to #243 can you confirm that v6.0.0 doesn't add the ability to add a class to the generated <picture>, but rather it:

  • preserves the class on an existing <picture> if it's present; and
  • doesn't nest <picture> tags if one is present.

So

<picture class="outer">
   <img class="inner" src="some-image.jpg" >
</picture>

Transforms to:

<picture class="outer">
   <source type="image/webp" srcset ... >
   <img class="inner" src="some-image.jpg" ...>
</picture>

The new behaviour is no nested <picture> tags.

And that

   <img class="inner" src="some-image.jpg" >

Still transforms to:

<picture>
   <source type="image/webp" srcset ... >
   <img class="inner" src="some-image.jpg" ... >
</picture>

Which is the existing behaviour.

And that there is no new way of supplying a class to the <picture> tag?

Or am I missing something?

@zachleat
Copy link
Member Author

zachleat commented Jan 9, 2025

@dwkns both things should be true for the HTML Transform method (if this doesn’t match your experience, please let me know!). If you want to add an attribute to picture via the JavaScript API you can do so with htmlOptions.pictureAttributes: https://www.11ty.dev/docs/plugins/image/#return-type-and-html-options

@dwkns
Copy link

dwkns commented Jan 10, 2025

@zachleat I think I understand. There are a couple of quirks, though.
Quirk = I'm not sure if it's a bug or intended behaviour.

This is all assuming you are using eleventyImageTransformPlugin

  • If you don't have a class on your source <picture> htmlOptions.pictureAttributes works as expected and the class from your config is added.

  • If you do have an existing class on your source <picture> anything set in htmlOptions.pictureAttributes overwrites the value set in your template.

This is different behaviour from htmlOptions.imgAttributes which preserves values for loading= alt= or decoding= on the <img> tag in your template.

Secondy
Is there a way to pass htmlOptions.pictureAttributes from an <img> tag ?

I optimistically tried <img eleventy:pictureAttributes="{class:'picture-class'}" src=... and <img eleventy:htmlOptions.pictureAttributes="{class:'picture-class'}" src=... to no avail.

If you can't do this (and combined with the quirk above), you are in a situation where if you want to use htmlOptions.pictureAttributes then ALL your <picture> tags will have the same attribute values. Probably not what you want.

When an attribute in htmlOptions.pictureAttributes is set expected behaviour would be:

  • Existing attributes in a source <picture> are preserved (the way existing attributes on <img> are preserved.
  • eleventy:pictureAttributes="{class:'picture-class'}" (or similar) would allow you overide anything set in htmlOptions.pictureAttributes meaning you have control over the class on every <picture> individually.

I hope this makes sense. If not I can open a new ticket and create a example repo to try and explain better.

@zachleat
Copy link
Member Author

There is more to digest there but this is just a quick reply to say that you can hoist attributes to <picture> from <img> with any eleventy:pictureattr:ATTR_NAME attributes. <img eleventy:pictureattr:class="outer"> would generate <picture class="outer"><img>. Somehow this is missing from the docs, sorry about that!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

No branches or pull requests

4 participants