Performant Images with <Img> and <Source>
- Mitchell Christ
Serving images efficiently can get pretty complex.
This starter template comes included with an <Img>
component to help serve your Sanity CDN images efficiently, without having to deal with all the complexity.
Benefits
- Stupid simple setup.
- Excellent resolution AND performance.
- Art direction is as simple as adding
<picture>
and<Source>
.
How to use
Basic usage
<Img image={image} /> // `alt` can be included in the image object
<Img
// π required props
image={image}
// π recommended props
imageWidth={600} // max width (in pixels) to display image
className="max-w-[450px]"
// π other optional props
imageSizes={[...]} // number[]; override the generated `srcset` values
alt="..."
loading="eager"
draggable={false}
options={{ imageBuilder: (b) => b.blur(10) }} // Sanity image builder methods
/>
Which will output:
<img
src="https://cdn.sanity.io/images/<...>.png?w=600&auto=format"
srcset="
https://cdn.sanity.io/images/<...>.jpg?w=120&auto=format 120w,
https://cdn.sanity.io/images/<...>.jpg?w=160&auto=format 160w,
https://cdn.sanity.io/images/<...>.jpg?w=200&auto=format 200w,
https://cdn.sanity.io/images/<...>.jpg?w=240&auto=format 240w,
https://cdn.sanity.io/images/<...>.jpg?w=320&auto=format 320w,
https://cdn.sanity.io/images/<...>.jpg?w=400&auto=format 400w,
https://cdn.sanity.io/images/<...>.jpg?w=480&auto=format 480w,
https://cdn.sanity.io/images/<...>.jpg?w=520&auto=format 520w,
https://cdn.sanity.io/images/<...>.jpg?w=560&auto=format 560w,
https://cdn.sanity.io/images/<...>.jpg?w=600&auto=format 600w
"
width="600" // based on `imageWidth` prop
height="533" // automatically calculated
alt="..."
loading="eager"
decoding="async"
class="max-w-[450px]"
>
Art direction
Have a landscape (wide) image, but want to swap with a portrait (tall) image on mobile?
Voila πͺ
<picture>
<Source
image={imageMobile}
imageWidth={1200}
// π optional
media="..." // default: '(max-width: 768px)'
/>
<Img
image={image}
imageWidth={1800}
/>
</picture>
In the above example, image
will be displayed by default, until the viewport becomes smaller than 768px where it then gets swapped with imageMobile
.
Performance, Performance, Performance
<Img>
is able to serve your Sanity CDN images at high resolution without impacting performance (and vice versa), largely thanks to the srcset
attribute.
It is highly recommended to set imageWidth
with a value just largerβperhaps 1.5xβthan the width you'd want to display your images (in pixels), along with setting a max-width
value with CSS.
For example, for an image to be displayed at 450px wide, set as follows:
className="max-w-[450px]"
imageWidth={600}
The <Img>
component, along with other code best practices, helps contribute to SanityPress's 98+/100 lighthouse scores.
Under the hood
The source code for both <Img>
and <Source>
can be found within the Next.js frontend, where you'll see the code relies on a couple of functions, courtesy of the following dependencies: