Progressive Image
A Progressive Image improves the user's perceived page load time by deferring the loading of large images. Each Progressive Image contains both a low-res placeholder image that is part of the initial HTML, plus a second, full-resolution image that loads at a later time.
Playground
React Usage
ProgressiveImage
has two important props:
placeholder
, which holds the URL of the placeholder imagesrc
, which holds the URL for the full image.
ProgressiveImage
requires as a child a function with input args image
and isLoading
. It should return an ReactElement
, typically ResponsiveImage
or FluidImage
- this way you can control how the image is rendered.
The trigger
prop on the component can then control what triggers the component to load the full image:
trigger inView
Giving the trigger
prop a value of inView
makes the component only load the full image when it scrolls into the viewport. This is the default behavior.
When using inView
option, you can specify also options for intersection observer, using intersectionOptions
.
Intersection options are:
root
rootMargin
threshold
More information about the options and defaults: https://developer.mozilla.org/en-US/docs/Web/API/Intersection_Observer_API
<ProgressiveImageplaceholder="https://via.placeholder.com/50x10?text=50x10"src="https://via.placeholder.com/500x100?text=500x100"trigger="inView"intersectionOptions={{ threshold: 1 }}>{(image, isLoading) => (<FluidImage src={image.src} alt="Progressive Image with inView trigger" />)}</ProgressiveImage>
trigger Immediate
Giving the trigger
prop a value of immediate
makes the page load the full image as soon as possible, when the image is rendered. This is useful for images "above the fold" at the top of the page.
<ProgressiveImageplaceholder="https://via.placeholder.com/50x10?text=50x10"src="https://via.placeholder.com/500x100?text=500x100"trigger="immediate">{(image, isLoading) => (<FluidImagesrc={image.src}alt="Progressive Image with immediate trigger"srcSet={image.srcSet}sizes={image.sizes}/>)}</ProgressiveImage>
trigger number
Giving the trigger
prop a value that is a number will delay the loading of the image by that number of milliseconds.
srcSet and sizes options
ProgressiveImage
can also use srcSet
and sizes
props, which function the same as those properties of the HTML <img>
tag. By default, both options are empty strings.
<ProgressiveImageplaceholder="https://via.placeholder.com/50x10?text=50x10"src="https://via.placeholder.com/500x100?text=500x100"srcSet="https://via.placeholder.com/500x100?text=500x100 500w, https://via.placeholder.com/1000x200?text=1000x200 1000w, https://via.placeholder.com/1500x300?text=1500x300 1500w, https://via.placeholder.com/10000x2000?text=10000x2000 10000w"sizes="(min-width: 768px) 500px, 100vw"trigger="immediate">{(image, isLoading) => (<FluidImagesrc={image.src}alt="Progressive Image with immediate trigger, srcSet and sizes"srcSet={image.srcSet}sizes={image.sizes}/>)}</ProgressiveImage>
Using isLoading
You can use isLoading
to respond to whether the image is yet loading. For instance, this example uses isLoading
with the style
property to give the image an opacity of 0.1 (and thus will make it very translucent) until it begins to load:
<ProgressiveImageplaceholder="https://via.placeholder.com/50x10?text=50x10"src="https://via.placeholder.com/500x100?text=500x100"intersectionOptions={{ threshold: 1 }}>{(image, isLoading) => (<FluidImagestyle={{ opacity: isLoading ? 0.1 : 1 }}src={image.src}alt="Image with loading effect"/>)}</ProgressiveImage>
Vanilla usage
The vanilla JS component puts the class progressive-image
onto an <img>
tag. This <img>
can (and likely should!) also be a Responsive Image or Fluid Image.
The src
attribute for the <img>
represents the placeholder version, which the page will load immediately. The data-src
attribute holds the URL for the full-sized image.
<!-- you can (and should) use this on/with a Responsive or Fluid Image --><imgclass="progressive-image"src="my-image-placeholder.jpg"data-src="my-image-full.jpg"alt="My example progressive image"/>
The vanilla component comes in three variations:
the default version, which loads only when it scrolls into the viewport.
the "immediate" version, which makes the page load the full image as soon as possible, typically at the DOMready event. This is useful for images "above the fold" at the top of the page.
the "eager" version, which makes the page load the full image as soon as the page reaches the "load" event. This is useful for images that are near the top of the page.
<imgclass="fluid-image progressive-image progressive-image-immediate"src="my-image-placeholder.jpg"data-src="my-image-full.jpg"alt="Example immediate image"/><imgclass="fluid-image progressive-image progressive-image-eager"src="my-image-placeholder.jpg"data-src="my-image-full.jpg"alt="Example eager image"/>
Components
ProgressiveImage
Prop | Type | Default | Description |
---|---|---|---|
onError | (errorEvent: Event) => void | Error event handler when loading image failed. | |
trigger | number | "immediate" | "inView" | "inView" | Switch defining how progressive image will load full resolution image.
|
intersectionOptions | IntersectionOptions | Options for Intersection Observer.
|
All other props are forwarded to the element specified in thecomponent
prop(default: <div/>
)
Guidelines
Developer Guidelines
Progessive Image can (and should) be used with other image types such as Responsive Image and Fluid Image. Progressive Image controls when and how the image loads, while Responsive and Fluid Image control how the image displays.
The vanilla JS version of this component will attempt to run at the DOM load event, which can occur before some React components are ready, especially if you are using Gatsby. Pages using React should use the React version of this component instead.