Skip to content

Gatsby Image Plugin — Optimized Images with gatsby-plugin-image

DodaTech Updated 2026-06-28 4 min read

In this tutorial, you will learn about Gatsby Image Plugin. We cover key concepts, practical examples, and best practices to help you master this topic.

Learn gatsby-plugin-image for optimized images with Lazy Loading, responsive sizes, AVIF/WebP formats, and blurred placeholders in Gatsby.

In this lesson, you'll understand the Gatsby Image plugin components: StaticImage, GatsbyImage, and how they optimize images automatically.

What You'll Learn

How to use StaticImage for simple images, GatsbyImage for dynamic images from Graphql, configure image formats, and understand image fragment patterns.

Why It Matters

Images are the largest performance bottleneck on most websites. Gatsby's image plugin automatically optimizes images, reducing load times by 40-60%.

flowchart LR
    A[Source Image] --> B[Sharp Processing]
    B --> C[Resize to Multiple Sizes]
    B --> D[Convert to AVIF/WebP]
    B --> E[Generate Blurred Placeholder]
    C --> F[Responsive srcSet]
    D --> G[Modern Format]
    E --> H[Lazy Loading Placeholder]
    style B fill:#639,color:#fff

Static Image

For images known at build time:

import { StaticImage } from 'gatsby-plugin-image';
import React from 'react';

function Logo() {
  return (
    <StaticImage
      src="../images/logo.png"
      alt="Company Logo"
      width={200}
      height={50}
      placeholder="blurred"
      layout="fixed"
    />
  );
}

Output: The image is optimized at build time: resized to 200x50, converted to WebP/AVIF, with a blurred placeholder. The component renders a responsive <picture> element.

GatsbyImage with GraphQL

For dynamic images sourced from filesystem:

query {
  file(relativePath: { eq: "hero.jpg" }) {
    childImageSharp {
      gatsbyImageData(
        width: 1200
        aspectRatio: 1.5
        placeholder: BLURRED
        formats: [AVIF, WEBP, AUTO]
        layout: constrained
      )
    }
  }
}
import { graphql, useStaticQuery } from 'gatsby';
import { GatsbyImage, getImage } from 'gatsby-plugin-image';
import React from 'react';

function Hero() {
  const data = useStaticQuery(graphql`
    query {
      file(relativePath: { eq: "hero.jpg" }) {
        childImageSharp {
          gatsbyImageData(
            width: 1200
            placeholder: BLURRED
            formats: [AVIF, WEBP, AUTO]
          )
        }
      }
    }
  `);

  const image = getImage(data.file);
  return <GatsbyImage image={image} alt="Hero image" />;
}

Output: The image is fetched via GraphQL, optimized with the specified options, and rendered with lazy loading and modern formats.

Image Layouts

Choose the right layout for your design:

// Fixed — exact pixel dimensions, no stretching
<StaticImage src="icon.png" width={50} height={50} layout="fixed" />

// Constrained — responsive within bounds, maintains aspect ratio
<StaticImage src="photo.jpg" width={800} layout="constrained" />

// Full width — always fills container width, height scales
<StaticImage src="banner.jpg" layout="fullWidth" />

Output: fixed keeps exact dimensions. constrained grows up to the specified width. fullWidth always fills the container with responsive sizes.

Placeholder Options

Control the loading experience:

// Blurred — show a 20x20 blurred version while loading (default)
<StaticImage src="large.jpg" placeholder="blurred" />

// Dominant color — show solid background color
<StaticImage src="large.jpg" placeholder="dominantColor" />

// Traced SVG — show a low-fidelity SVG outline
<StaticImage src="large.jpg" placeholder="tracedSVG" />

// None — show nothing while loading
<StaticImage src="large.jpg" placeholder="none" />

Output: The placeholder appears instantly while the full image loads. blurred provides the best visual result. none is fastest for unimportant images.

Image Fragment

Create reusable GraphQL fragments:

// gatsby-fragments.js
import { graphql } from 'gatsby';

export const HeroImage = graphql`
  fragment HeroImage on File {
    childImageSharp {
      gatsbyImageData(
        width: 1200
        placeholder: BLURRED
        formats: [AVIF, WEBP, AUTO]
      )
    }
  }
`
import { graphql, useStaticQuery } from 'gatsby';

function Hero() {
  const data = useStaticQuery(graphql`
    query {
      file(relativePath: { eq: "hero.jpg" }) {
        ...HeroImage
      }
    }
  `);
}

Output: The fragment defines the image query once and can be reused across components, ensuring consistent image configuration.

Common Mistakes

  1. Using StaticImage with dynamic src: StaticImage requires a static string path. Dynamic paths like src={imagePath} won't work. Use GatsbyImage with GraphQL instead.
  2. Not querying childImageSharp: The childImageSharp field only exists if images are processed. Ensure gatsby-plugin-sharp and gatsby-transformer-sharp are configured.
  3. Forgetting getImage() helper: The getImage() function safely extracts the gatsbyImageData object. Accessing data.file.childImageSharp.gatsbyImageData directly may error.
  4. Using layout="fixed" for responsive images: Fixed layout doesn't resize in responsive layouts. Use constrained or fullWidth for responsive designs.
  5. Over-optimizing unimportant images: Not every image needs WebP/AVIF. Apply full optimization to hero and content images, but simple images can use basic formats.

Practice Questions

  1. What is the difference between StaticImage and GatsbyImage? Answer: StaticImage is for images known at build time with a static path. GatsbyImage is for dynamic images queried via GraphQL.

  2. What image formats does gatsby-plugin-image generate? Answer: AVIF, WebP, and fallback PNG/JPEG. The browser loads the best supported format.

  3. What does layout="fullWidth" do? Answer: The image always fills its container width and generates many responsive sizes from 100vw down to very small.

  4. How does blurred placeholder work? Answer: A 20px-wide version of the image is generated, blurred, and base64-encoded as a CSS background. It's replaced by the full image once loaded.

Challenge

Create a responsive image grid with 9 images using GatsbyImage. Each image should use layout="constrained" with different aspect ratios (portrait, landscape, square). Use a GraphQL fragment for the image query.

Mini Project

Build a product gallery page with a hero image, thumbnail strip, and zoomable main image. Use GatsbyImage for the main image and StaticImage for thumbnails. Implement click-to-select thumbnails.

FAQ

Does gatsby-plugin-image work with remote images?

: Yes. Use gatsby-plugin-image with remote data by passing image URLs from CMS or API queries.

Can I use gatsby-plugin-image with GIFs?

: GIFs are not optimized. The plugin outputs static image formats. For animated content, use video or a GIF component.

How does the plugin handle alt text?

: The alt prop is required on both StaticImage and GatsbyImage. It's passed directly to the <img> element.

Does gatsby-plugin-image support art direction?

: Yes. Use the media prop on <StaticImage> to load different images at different breakpoints.

What's Next

Learn about Gatsby GraphQL Data Layer to understand how Gatsby collects and exposes data through GraphQL.

Built by the developers of DodaTech

Doda Browser, DodaZIP & Durga Antivirus Pro