How to optimize images in Gatsby Image

Large and unoptimized images can dramatically slow down our site. Luckily, Gatsby has several useful plugins to optimize 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 an 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 the gatsby-image plugin, ensure you have installed a source plugin, so your images are available in graphQl queries.

To install the 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.

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 the 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 fluid props (if the image is responsive) or fixed props (if the image has a fixed size).
  • In the props, add the data as a 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 that are reusable 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 of 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

The parent container will control the width of the fluid image.

VII. maxWidth

maxWidth is one of the parameters of the 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 blurry image because it has to stretch to fix the container.

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