Gatsby gatsbyImageData: Build-Time Responsive Images Explained
Replace manual srcset construction in Gatsby with the gatsbyImageData resolver, which generates WebP, AVIF, and resized variants during gatsby build.
02 Dec 2025, 18:30 UTC

Stop hand-writing srcset: let Gatsby build it
Manually maintaining srcset and sizes attributes in a Gatsby site is error-prone and quickly becomes stale when design breakpoints change. The gatsbyImageData GraphQL resolver removes that burden by generating every responsive variant during gatsby build. Your template requests a single field, and Gatsby returns a structured payload that the GatsbyImage component renders into a standards-compliant, lazy-loading <img> tag.
How the resolver and component fit together
gatsby-plugin-image exposes the gatsbyImageData resolver, which runs at build time through sharp. Instead of shipping one oversized JPEG, Gatsby produces resized widths, modern formats such as WebP and AVIF, and a tiny base64 placeholder. The resolver returns an object with images.sources (an array of AVIF and WebP candidates), a fallback srcSet, width, height, and a placeholderDataURI when requested. When your page renders, GatsbyImage reads these fields and emits a single <img> element with the correct srcset, sizes, and inline placeholder styling.
Because transformation happens during the build, the runtime cost is low, but the build cost is real: every large source image is decoded, resized, and re-encoded. Pre-optimizing source assets before committing them remains necessary.
A worked configuration and query
Required plugins
Add the image plugins to gatsby-config.js and point gatsby-source-filesystem at your image directory. Run all commands from your project root; no elevated permissions are required.
// gatsby-config.js
module.exports = {
plugins: [
`gatsby-plugin-sharp`,
`gatsby-transformer-sharp`,
`gatsby-plugin-image`,
{
resolve: `gatsby-source-filesystem`,
options: {
name: `images`,
path: `${__dirname}/src/images`,
},
},
],
}
Query the File node directly
In a page query, request gatsbyImageData on the File node itself. The following example asks for an 800-pixel constrained image with a blurred placeholder and automatic format selection:
query BlogPostQuery {
file(relativePath: { eq: "blog/hero.jpg" }) {
gatsbyImageData(
width: 800
layout: CONSTRAINED
placeholder: BLURRED
formats: [AUTO, WEBP, AVIF]
)
}
}
Pass the result to the component:
import { GatsbyImage } from "gatsby-plugin-image"
export default function BlogPost({ data }) {
return (
<GatsbyImage
image={data.file.gatsbyImageData}
alt="A developer workstation with dual monitors"
/>
)
}
The layout argument controls CSS behavior. CONSTRAINED scales down but never exceeds natural width, suiting inline content. FIXED locks width and height for avatars or thumbnails. FULL_WIDTH stretches to the viewport for hero banners. Choosing the wrong layout leads to unexpected cropping or oversized downloads on mobile devices.
StaticImage vs. GatsbyImage: when to use which
Gatsby ships two components. StaticImage accepts a local import and analyzes the file at build time, but it cannot accept GraphQL data. GatsbyImage requires the gatsbyImageData payload from a query. Mixing both in one codebase is valid, but a consistent rule prevents confusion: use StaticImage for hard-coded assets such as logos and icons, and GatsbyImage for content-driven images.
| Scenario | Component | Data source |
|---|---|---|
| Logo imported directly in a component | StaticImage |
Local import statement |
| Hero image from a CMS or Markdown frontmatter | GatsbyImage |
gatsbyImageData resolver |
Limits and build-time costs
- Build duration and memory:
sharpprocesses images duringgatsby build. Adding many high-resolution sources increases both time and memory usage. - AVIF compatibility: Although Gatsby falls back to WebP and the original format automatically, older Safari versions may need testing if you enable AVIF.
- Version alignment: Gatsby v5 changed some plugin defaults. Verify that your installed
gatsby-plugin-imageversion matches your Gatsby major version. - Unsourced files: Querying
gatsbyImageDataon a node thatgatsby-source-filesystemdoes not cover returnsnull.
Common mistakes
- Missing transformer plugins: Forgetting
gatsby-plugin-sharporgatsby-transformer-sharpleaves the resolver unavailable. - Wrong query path: Querying
childImageSharpinstead of theFilenode'sgatsbyImageDatafield returns an unexpected shape ornull. - No placeholder: Omitting the
placeholderoption disables the blur-up effect, causing layout shift as images load. - Unoptimized sources: Committing multi-megabyte TIFFs or PNGs assumes
sharpwill fix everything; it will not reduce the build cost of decoding them.
Verifying the output
Run gatsby develop from your project root and open the page in a browser. Inspect the rendered <img> element for a srcset attribute listing multiple widths, a sizes attribute, and a base64 data URI used for the placeholder. If any of these are missing, confirm that the query returned data and that the image path in gatsby-source-filesystem is correct.
To confirm that transformation occurred, inspect the .cache/caches/images directory or the public folder after a build for resized variants and WebP files alongside the original. For timing and transformation logs, run gatsby build --verbose in your project root and review the sharp processing messages.
If the build fails or runs out of memory on image-heavy sites, reduce the number of formats, lower the maximum width requested, or pre-resize source assets before committing them. These changes affect build output, so re-run gatsby build and verify the generated public folder before deploying.
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.