Support `<picture>` with multiple sources
See original GitHub issueIt seems the picture tag implementation in the nuxt/image package is lacking basic picture tag features.
The picture tag and its sources (who act like regular images - with srcset and sizes, but with the addition of the “media” attribute) is meant to be able to show a different image for different matches in that media attribute.
Currently one source is added in the code which acts as a normal image tag with srcset and sizes. However, there is no mention of the media attribute in the implementation. see: https://github.com/nuxt/image/blob/main/src/runtime/components/nuxt-picture.vue
A picture tag is mainly used in a more “Art Direction” way and not “Resolution Switching”.
<picture>
is capable of handling resolution switching, however you shouldn’t use it if that’s all you need. In such cases stick with a regular element plus
srcset
and sizes
.
Example of average picture tag usage:
- On landscape devices I show an image in a 22:9 aspect ratio and a specific crop.
- On portrait devices I show an image in 1:1 ratio and with a crop on the face.
These two images are different. Not just their width/height, they are actually different files with different aspects ratios and compositions. Each one is a source
in the picture tag. Each of these <source />
tags also has a srcset
and a sizes
attribute so they behave like a normal image nuxt image would. They have an additional media
attribute which defines when they are shown. This field has a media query in it that tells the browser in which context to show the source.
An HTML example:
<picture>
<source
media="(orientation: landscape)"
srcset="image-small.png 320w,
image-medium.png 800w,
image-large.png 1200w"
sizes="(min-width: 60rem) 80vw,
(min-width: 40rem) 90vw,
100vw">
<source
media="(orientation: portrait)"
srcset="image-small-portrait.png 160w,
image-medium-portrait.png 400w,
image-large-portrait.png 600w"
sizes="(min-width: 60rem) 80vw,
(min-width: 40rem) 90vw,
100vw">
<img src="image-small.png" alt="Image description">
</picture>
You can of course also use the picture
tag for file type support etc
<picture>
<source type="image/webp" srcset="illustration.webp">
<img src="illustration.png" alt="A hand-made illustration">
</picture>
With the above in mind we should be able to add multiple images into the nuxt picture tag so sources can be generated with media
attributes.
See image for differences:
Issue Analytics
- State:
- Created 2 years ago
- Reactions:27
- Comments:8 (3 by maintainers)
With the current
nuxt-picture
, one cannot use different versions of image/src with media selectors but is simply animg
replacement with the ability for serving modern formats alongside legacy support.As @Atinux mentioned, It is possible to directly use
$img
and$img.getSizes
API creating any structure likemedia
variable sources. We can also create a shortcut like<nuxt-source>
to make it sexier:POC: https://codesandbox.io/s/intelligent-water-nbikw?file=/pages/index.vue
In addition, we probably support scoped slots for
nuxt-picuture
, this way we can make it more minimalistic. (subject to discuss when added)One alternative would be supporting more complex syntax for
sizes
prop. Combining source and sizes. We had it in previous versions but removed it due to complexities for simpler usecases and implementation.img
tags insidepicture
unless checking parent for conditional rendering (which is anti-pattern)I guess best would be going with 2 (nuxt-source and slot) 🙈