Stopping Layout Shift: Implementing Gatsby's Image Pipeline
Learn how to eliminate Cumulative Layout Shift (CLS) in Gatsby by shifting image processing to the build step using gatsby-plugin-image and GraphQL.
13 Oct 2025, 21:06 UTC

The Cost of the Standard <img> Tag
When a browser encounters a standard HTML <img> tag without explicit width and height attributes, it doesn't know how much space to reserve. As the image eventually downloads and renders, the surrounding text and elements suddenly jump to make room. This is known as Cumulative Layout Shift (CLS), a core metric in Google's Core Web Vitals that directly impacts user experience and SEO rankings.
The solution isn't just adding dimensions manually; it's shifting the image processing from the user's browser to the build step. By using gatsby-plugin-image, you can automate the creation of responsive assets and placeholders, ensuring the page layout remains stable while the high-resolution image loads.
How the Gatsby Image Pipeline Works
Gatsby handles image optimization during the Static Site Generation (SSG) process. Instead of serving one giant JPEG to every device, the pipeline uses a library called sharp (a high-performance Node.js image processing module) to perform several tasks at compile time:
- Multi-resolution Generation: It creates a
srcset, which is a list of different sized versions of the same image. The browser then automatically chooses the smallest file that will look crisp on the user's specific screen density. - Format Conversion: It generates modern formats like WebP and AVIF, which offer superior compression over JPEG or PNG without losing visible quality.
- Placeholder Creation: It generates a tiny, blurred version of the image (or a dominant color SVG) that loads instantly, filling the space and preventing layout shift before the main asset arrives.
From Static Tags to GatsbyImage
To move from a standard image to an optimized one, you must first query the image data via GraphQL. This allows Gatsby to calculate the dimensions and generate the necessary source sets before the page is ever served.
Implementation Example
Assuming you have an image located in your src/images folder, replace your static HTML with a GraphQL query and the GatsbyImage component.
# 1. The GraphQL Query (usually in a page query or useStaticQuery hook)
query {
file(relativePath: { eq: "hero-banner.jpg" }) {
childImageSharp {
gatsbyImageData(
width: 800,
placeholder: BLURRED,
formats: [AUTO, WEBP, AVIF]
)
}
}
}
# 2. The Component Implementation
import { GatsbyImage, getImage } from "gatsby-plugin-image";
const Hero = ({ data }) => {
const image = getImage(data.file.childImageSharp.gatsbyImageData);
return (
<GatsbyImage
image={image}
alt="A descriptive alt text for accessibility"
/>
);
};
Execution Details
- Where to run: These changes are made in your React components and GraphQL queries within the Gatsby project directory.
- Permissions: Standard project contributor permissions; however, the build environment (CI/CD) must have the necessary binaries to run
sharp. - Expected Result: The rendered HTML will no longer contain a simple
<img>tag, but a complex set of<picture>and<source>tags.
The Build-Time Trade-off
The primary limitation of this approach is build duration. Because Gatsby processes every image into multiple sizes and formats at compile time, your build time increases linearly with your asset library. If you have a site with thousands of high-resolution images, your CI/CD pipeline may become prohibitively slow.
For sites with massive image libraries, consider using a Gatsby source plugin for a Digital Asset Manager (DAM) or a cloud-based image CDN (like Cloudinary or Imgix) to move the processing from the build step to the request step.
Verifying the Optimization
To confirm the pipeline is working correctly, perform these two checks:
- Inspect the DOM: Right-click the image in your browser and select "Inspect." Look for the
srcsetattribute. You should see multiple URLs pointing to different widths of the image. - Network Analysis: Open Chrome DevTools, go to the Network tab, and filter by "Img." Refresh the page. Check the "Type" column; you should see
webporavifbeing served instead of the originaljpgorpng.
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.