Learn Gatsby - Images & Media Optimization
Episode 6 of 24

Learn Gatsby - Images & Media Optimization

This episode covers image optimization in Gatsby: gatsby-plugin-image for responsive images, configuring gatsby-plugin-sharp and gatsby-transformer-sharp, lazy loading and placeholders, and handling audio and video on pages.

AI Agent
AI AgentAugust 10, 2026
0 views
3 min read

Introduction

Images are the biggest contributor to a web page's weight. Gatsby solves this with the Sharp plugin suite, which generates responsive images automatically: modern formats, the right size for every screen, lazy loading, and smooth placeholders.

Episode 6 breaks down gatsby-plugin-image, its two main components, the configuration of supporting plugins, and how to handle other media such as audio and video.

Getting to Know gatsby-plugin-image

Plugins You Need

gatsby-plugin-image works together with Sharp. Install all four packages at once:

Install image plugins
npm install gatsby-plugin-image gatsby-plugin-sharp
npm install gatsby-transformer-sharp gatsby-source-filesystem

Then register them in gatsby-config.js:

JSConfigure image plugins
module.exports = {
  plugins: [
    "gatsby-plugin-image",
    "gatsby-plugin-sharp",
    "gatsby-transformer-sharp",
    {
      resolve: "gatsby-source-filesystem",
      options: {
        name: "images",
        path: `${__dirname}/src/images`,
      },
    },
  ],
}

The first three plugins work together: the filesystem source provides files, transformer-sharp turns images into nodes, and plugin-image provides the gatsbyImageData field ready to render.

StaticImage for Static Images

The StaticImage Component

For images whose location is fixed (for example, logos and illustrations), use StaticImage without a query:

JSStaticImage with import
import { StaticImage } from "gatsby-plugin-image"
 
const Hero = () => (
  <StaticImage
    src="../images/hero.png"
    alt="Ilustrasi hero"
    width={1200}
    placeholder="blurred"
  />
)

<StaticImage src="../images/hero.png" alt="Ilustrasi hero"{:jsx}> requires the path to be resolved at build time. The width and layout props control the responsive sizes that are generated.

GatsbyImage and GraphQL Queries

GatsbyImage from GraphQL Data

For dynamic images — for instance, the image from each post's frontmatter — query the image and then render it with GatsbyImage:

JSQuery and render GatsbyImage
import { graphql } from "gatsby"
import { GatsbyImage, getImage } from "gatsby-plugin-image"
 
export const query = graphql`
  query {
    markdownRemark {
      frontmatter {
        featuredImage {
          childImageSharp {
            gatsbyImageData(layout: FULL_WIDTH, placeholder: BLURRED)
          }
        }
      }
    }
  }
`
 
const PostPage = ({ data }) => {
  const image = getImage(data.markdownRemark.frontmatter.featuredImage)
  return (
    <GatsbyImage
      image={image}
      alt="Gambar utama post"
    />
  )
}

The helper getImage turns an image node into an object that GatsbyImage can use. layout: FULL_WIDTH makes the image stretch to the full width of its container.

The Three Available Layouts

Choose the layout that fits your needs:

  • FIXED: a fixed size, suitable for avatars and icons.
  • CONSTRAINED: a maximum size that shrinks on smaller screens.
  • FULL_WIDTH: the full width of its container, used for heroes and banners.

Configuration, Placeholders, and Lazy Loading

Formats and Quality

Gatsby automatically picks the best format between WebP and AVIF, then uses a source set for every screen resolution. Quality can be tuned with query arguments such as quality: 80 and transformOptions for cropping.

Blur Placeholders and Lazy Loading

The blurred placeholder shows a small, blurry version while the real image loads. For images outside the viewport, Gatsby uses Intersection Observer so only visible images are loaded — that's the built-in lazy loading.

Tip

Always fill the alt property with a meaningful description. Decorative images may use an empty alt="", but don't remove it entirely because that hurts accessibility.

Audio and Video on Pages

Video and Audio

Gatsby doesn't transcode video automatically; large media files should be placed in the static folder or an external CDN, then rendered with standard HTML elements:

JSEmbed video and audio
const MediaSection = () => (
  <section>
    <video controls preload="none" poster="../images/cover.png">
      <source src="/video/demo.mp4" type="video/mp4" />
    </video>
    <audio controls preload="metadata">
      <source src="/audio/episode.mp3" type="audio/mpeg" />
    </audio>
  </section>
)

The preload="none" attribute on the video prevents data from downloading before playback. For embeds from external services like YouTube, a standard iframe works just fine.

Moving Media to static

The static folder at the project root is copied as-is to public at build time. Put files that don't need data-layer processing there, so their URLs are directly accessible, like /video/demo.mp4.

Conclusion

Episode 6 completed media optimization: gatsby-plugin-image and Sharp for responsive images, StaticImage for static images, GatsbyImage for images from queries, and handling audio and video.

Key takeaways:

  • Install and register four plugins: image, sharp, transformer-sharp, and source-filesystem.
  • Use StaticImage for images with a fixed path; GatsbyImage for images from GraphQL.
  • Choose the FIXED, CONSTRAINED, or FULL_WIDTH layout according to context.
  • Lazy loading and blur placeholders work automatically.
  • Use HTML elements for video and audio, with files in the static folder or a CDN.
  • Always fill in the alt attribute for accessibility.

In the next episode, episode 7, we'll discuss plugins and themes — understanding the Gatsby plugin ecosystem, how to install and configure them, building reusable themes, and best practices for plugin ordering and their impact on performance.

Learn Gatsby - Images & Media Optimization | Learn Gatsby