Install with:
npm i container-picture-element
or use the package manager of your choice.
Then just import it into your project:
import "container-picture-element";
Or directly include the script in dist/container-picture.global.js
in your HTML page.
The script will register a custom element you can then use in your HTML:
<container-picture>
<source
srcset="./682.jpg"
container="(min-width: 682px)"
width="682"
height="453"
/>
<source
srcset="./473.jpg"
container="(min-width: 473px)"
width="473"
height="314"
/>
<img alt="A nice poppy flower" src="./258.jpg" width="258" height="171" />
</container-picture>
You can use the container
attribute on the source
element to define container queries (like proposed here and here).
The usage of the img
element is intended for SEO and accessibility reasons.
The problem is that it will be parsed by the browser speculative parsing too and will cause the browser to download the image defined in the src
attribute before any JavaScript can be executed.
This can cause the browser to download another image when the JavaScript will be executed, the one that effectively correspond to the size of the container.
Adding the loading="lazy"
attribute can help to prevent this behavior.
In that case, depending on the loading of the elements in your page, the execution of the JavaScript and the position of the image relative to the viewport, it can prevent the downloading of the img
src
image.
But this will not work in all situations.
That's why we recommend to always put the image that's intended for mobile devices at the end.
In that case:
- mobile devices will only download the mobile image
- other devices will download:
- in the best scenario: only their image (when using
loading="lazy"
) - in the worst scenario: both the mobile image and their image (fortunately the mobile image is often less heavy)
- in the best scenario: only their image (when using
If you really don't want this behavior, you can replace the img
element by another source
element:
<container-picture>
<source
srcset="./682.jpg"
container="(min-width: 682px)"
width="682"
height="453"
/>
<source
srcset="./473.jpg"
container="(min-width: 473px)"
width="473"
height="314"
/>
<source srcset="./258.jpg" width="258" height="171" />
</container-picture>
In that case the browser won't download anything until the JavaScript is executed, but you also lose some SEO and accessibility for that image (that's fine if you use this for some decoration image).
You can check the embedded demo by cloning or downloading the project and running:
npm i
npm run dev