How to optimize images in Gatsby with gatsby-image

Large and unoptimized images can dramatically slow down our site. Luckily, Gatsby has several useful plugins to opimize images on page components.

Using images in Gatsby requires the following plugins:

  • gatsby-source-filesystem plugin allows us to query files with GraphQL
  • gatsby-image plugin that automatically creates React components for optimized
  • gatsby-transformer-sharp
  • gatsby-plugin-sharp

I. Why should we use gatsby-image?

gatsby-image can:

  • resize large images to the size needed
  • generate multiple sizes of image so the browser can select the most suitable one for a specific screen size
  • lazy load images to speed initial page load and save bandwidth
  • hold an image’s position so the page doesn’t jump around as images load
  • use the “blur-up” technique or a ”traced placeholder” SVG to show a preview of the image while it loads

II. Install

1. Install plugins

Before installing gatsby-image plugin, make sure you have installed a source plugin, so your images are available in graphql queries.

To install gatsby-image plugin:

npm install gatsby-image

Depending on our starter theme, we may need to include gatsby-transformer-sharp and gatsby-plugin-sharp plugins as well.

gatsby-transformer-sharp and gatsby-plugin-sharp help to transform and process our images.

npm install gatsby-transformer-sharp gatsby-plugin-sharp

2. Edit gatsby-config.js

We then add the newly installed plugins to gatsby-config.js

module.exports = {
  plugins: [
    {
      resolve: `gatsby-source-filesystem`,
      options: {
        name: `images`,
        path: path.join(__dirname, `src`, `images`),
      },
    },
    `gatsby-plugin-sharp`,
    `gatsby-transformer-sharp`,
  ],
};

III. How to use gatsby-image

We can use gatsby-image in the following steps:

  • We import Img component from “gatsby-image”
  • We pass <Img /> component where we want to render the image
  • The image component can have a fluid props (if the image is responsive) or fixed props (if the image has fixed size)
  • In the props, add the data as the result from GraphQl image query

Example We have a fixed field

import React from "react"
import { graphql } from "gatsby"
import Img from "gatsby-image"

export default ({ data }) => (
  <div>
    <h1>Hello gatsby-image</h1>
    <Img fixed={data.file.childImageSharp.fixed} />
  </div>
)

export const query = graphql`
  query {
    file(relativePath: { eq: "image-1.jpeg" }) {
      childImageSharp {
        fixed(width: 125, height: 125) {
          ...GatsbyImageSharpFixed
        }
      }
    }
  }
`

IV. Fragments

Gatsby provides query fragments which are reuseable fields.

gatsby-image currently include the fragments for gatsby-transformer-sharp, gatsby-source-contentful, gatsby-source-datocms and gatsby-source-sanity.

gatsby-transformer-sharp

  • GatsbyImageSharpFixed
  • GatsbyImageSharpFixed_noBase64
  • GatsbyImageSharpFixed_tracedSVG
  • GatsbyImageSharpFixed_withWebp
  • GatsbyImageSharpFixed_withWebp_noBase64
  • GatsbyImageSharpFixed_withWebp_tracedSVG
  • GatsbyImageSharpFluid
  • GatsbyImageSharpFluid_noBase64
  • GatsbyImageSharpFluid_tracedSVG
  • GatsbyImageSharpFluid_withWebp
  • GatsbyImageSharpFluid_withWebp_noBase64
  • GatsbyImageSharpFluid_withWebp_tracedSVG
  • GatsbyImageSharpFluidLimitPresentationSize

gatsby-source-contentful

  • GatsbyContentfulFixed
  • GatsbyContentfulFixed_noBase64
  • GatsbyContentfulFixed_tracedSVG
  • GatsbyContentfulFixed_withWebp
  • GatsbyContentfulFixed_withWebp_noBase64
  • GatsbyContentfulFluid
  • GatsbyContentfulFluid_noBase64
  • GatsbyContentfulFluid_tracedSVG
  • GatsbyContentfulFluid_withWebp
  • GatsbyContentfulFluid_withWebp_noBase64

Example: If we have a fixed image, we have the following options:

  • GatsbyImageSharpFixed
  • GatsbyImageSharpFixed_noBase64
  • GatsbyImageSharpFixed_tracedSVG
  • GatsbyImageSharpFixed_withWebp
  • GatsbyImageSharpFixed_withWebp_noBase64
  • GatsbyImageSharpFixed_withWebp_tracedSVG

We can display our image depending on the fragment

V. gatsby-image query

Here is an example for fixed and fluid image query

{
  fixed: file(relativePath: {eq: "image-1.jpg"}) {
    childImageSharp {
      fixed(width: 400, grayscale: true) {
        ...GatsbyImageSharpFixed
      }
    }
  }
  fluid: file(relativePath: {eq: "image-2.jpg"}) {
    childImageSharp {
      fluid {
        ...GatsbyImageSharpFluid
      }
    }
  }
}

VI. Image example

import React from 'react'
import { useStaticQuery, graphql } from "gatsby"
import img from "../images/image-1.jpg"
import Img from "gatsby-image"

const getImages = graphql`
{
  fixed: file(relativePath: {eq: "image-1.jpg"}) {
    childImageSharp {
      fixed(width: 400, grayscale: true) {
        ...GatsbyImageSharpFixed
      }
    }
  }
  fluid: file(relativePath: {eq: "image-2.jpg"}) {
    childImageSharp {
      fluid {
        ...GatsbyImageSharpFluid
      }
    }
  }
}
`

const Images = () => {
    const data = useStaticQuery(getImages)

    return (
        <section className="images">
            <article className="single-image">
                <h3>Basic image</h3>
                <img src={img} width="30%" alt="beach" />
            </article>
            <article className="single-image">
                <h3>Fixed image / Blur</h3>
                <Img fixed={data.fixed.childImageSharp.fixed} />
            </article>
            <article className="single-image">
                <h3>Fluid image</h3>
                <Img fluid={data.fluid.childImageSharp.fluid} />
            </article>
        </section>
    )
}

export default Images

Parent container will control the width of the fluid image

VII. maxWidth

maxWidth is one of the parameters of fluid field, and it controls the size of images that will be generated using gatsby-image

For example, if we indicate the maxWidth to be 200px but our container is 800px, we will have a blury image because it has to stretch to fix the container.

{
  fluid: file(relativePath: {eq: "image-2.jpg"}) {
    childImageSharp {
      fluid (maxWidth: 200) {
        ...GatsbyImageSharpFluid
      }
    }
  }
}