The picture element is a solution that makes it easy to provide assets that are adapted to the medium they are view on. It allows to define multiple assets to be used under specific circumstances. For example, you can define different assets at different viewport breakpoints or pixel ratios. The obvious benefit is that assets of the proper dimension are served, which can end up saving a lot of bandwidth.
Here’s an example of the markup for the picture element:
<picture> <source srcset="small.jpg, small2x.jpg 2x" media="(max-width: 639px)"> <source srcset="medium.jpg, medium2x.jpg 2x" media="(min-width: 640px) and (max-width: 1023px)"> <source srcset="large.jpg, large2x.jpg 2x" media="(min-width: 1024px)"> <img src="my-image.jpg" alt="My image" srcset="my-image2x.jpg 2x"> </picture>
Here are a few key pointers:
- You define a traditional img element last, for browsers that don’t support the picture or source elements.
- The source element’s srcset attribute can take any number of comma-separated resource urls and each resource url can have a pixel ratio provided after the url (1x, 2x, 3x).
- The img element also supports srcset in browsers that support the source element.
- The source element’s media attribute can take any media query, formatted in the same way as in CSS.
The picture element is good not only to save on bandwidth and make your pages load faster, but it can also be a good help if the assets should look different on different devices. For example, if an image has a lot of small details, perhaps a simpler version would be more appropriate on smaller displays.
If you’re on a desktop computer, try it out by resizing your browser to see the automatic image replacement:
— Sorry to interrupt this program! 📺
Are you interested in learning Vue.js? If so, I highly recommend you try The Vue.js Master Class course by Vue School. Learning from a premium resource like that is a serious investment in yourself.
Plus, this is an affiliate link, so if you purchase the course you help Alligator.io continue to exist at the same time! 🙏
Sizes and Type
Two additional attributes can be used on the source elements: sizes and type.
Sizes tells the browser how much of the viewport is going to be covered by the image, and then the browser makes a decision about which image is most appropriate. Sizes is used if width dimension descriptors are provided with srcset instead of pixel ratio values (200w instead of 2x for example).
The width descriptors provided with srcset is the width of the images and the value provided for sizes is a measure in viewport units (vw) of the amount of space that the image will occupy in the layout. These values give tips to the browser as to which image to use:
<picture> <source srcset="small-200.jpg 200w" sizes="(max-width: 639px) 100vw"> <source srcset="medium-650.jpg 650w" sizes="(min-width: 640px) and (max-width: 1023px) 50vw"> <source srcset="large-850.jpg 850w" sizes="(min-width: 1024px) 25vw"> <img src="my-image.jpg" alt="My image"> </picture>
Type defines the format for the provided image. The browser loads the first source that is of a supported type:
<picture> <source srcset="alligator.svg" type="image/svg+xml"> <source srcset="alligator.webp" type="image/webp"> <img src="alligator.png" alt="Alligator Logo"> </picture>
If what you want to accomplish is simply provide different versions of the same image for different display sizes, using srcset on the img element without the picture or source elements might be all you need:
<img src="default.jpg" alt="My image" srcset="medium.jpg 2x, large.jpg 3x">
The browser does the job of figuring out which image should be used, given the display size and pixel ratio. Keep in mind that srcset values are just suggestions and the browser doesn’t necessarily have to follow them.
The sizes attribute along with srcset values that provide width valu descriptors (ex: 200w) can also be used on the img element directly:
<img src="default.jpg" alt="My image" srcset="small.jpg 400w, medium.jpg 600w, large.jpg 850w" sizes="(min-width: 1024px) 25vw, (min-width: 640px) and (max-width: 1023px) 50vw, (max-width: 639px) 100vw">