Skip to content

Image Lazy Loading in Gatsby

Gatsby/

Lazy loading is an optimization technique where assets, such as images, are not loaded immediately when a user opens a page. Instead, assets get loaded when the user actually sees them. For images, a blurred version is placed in the page initially, to prevent the content from jumping. When the user scrolls towards the image, the actual image gets loaded.

In this post you will learn how to set up lazy loading in Gatsby for static and dynamic images. You will also learn how to lazy load images from Markdown files.

Setting up Lazy Loading

To set up lazy loading in Gatsby, you can use gatsby-plugin-image plugin. It takes care of both static and dynamic images.

Lazy Loading Static Images

Static images are those that stay the same every time a component uses them. For example, a hero image on your home page, that stays the same every time you build your site, is a static image.

First, start by create a folder where you want to keep the images, for example, src/images.

Next, install the following packages.

npm install gatsby-plugin-image gatsby-plugin-sharp gatsby-source-filesystem

And then add the installed plugins to your gatsby-config.js.

module.exports = {
  plugins: ['gatsby-plugin-image', 'gatsby-plugin-sharp'],
};

Finally, import StaticImage component and use it whenever you would use img tag. The src of the image can either be a local path or a remote URL. When you use a remote URL, Gatsby will download the image at build time. If the image changes on the remote URL, it will still stay the same until the next time you rebuild your site.

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

export function Header() {
  return <StaticImage src="../images/background.jpg" alt="Forest" />;
}

You must provide alt attribute for the plugin to work. You can pass alt="" if you want to leave it empty.

Lazy Loading Dynamic Images

You should use another approach for images that change within a component. If a component loads a different image each time you reuse the component, it is a dynamic image. For example, if the image changes because it is coming from a data source like a CMS or Markdown files.

First, install the following package along the packages you installed for static images.

npm install gatsby-transformer-sharp

And add it to your gatsby-config.js

module.exports = {
  plugins: [
    // . . .
    'gatsby-transformer-sharp',
  ],
};

Now, let’s say you use Markdown for your blog posts and you want to add a header image. Place the image next to the .md file and add its path inside the Markdown file.

---
title: Blog Post Title
date: 2021-07-06T08:05:42.617Z
description: A short description
image: './header-image.jpg'
---

Gatsby creates a File node for the image at build time when it sources data.

You can now query the image by accessing the gatsbyImageData resolver within childImageSharp. You should pass it the max width of the image. The max width is the greatest possible width of your content.

Finally, use GatsbyImage component to lazy load the dynamic image.

// src/templates/post.js

import React from 'react';
import { graphql } from 'gatsby';
import { GatsbyImage, getImage } from 'gatsby-plugin-image';

const PostTemplate = ({ data }) => {
  const post = data.markdownRemark;
  const image = getImage(post.frontmatter.image);

  return (
    <article>
      <header>
        <h1>{post.frontmatter.title}</h1>
        <GatsbyImage image={image} alt="" />
      </header>
      <section dangerouslySetInnerHTML={{ __html: post.html }} />
    </article>
  );
};

export default PostTemplate;

export const pageQuery = graphql`
  query Post($id: String!) {
    markdownRemark(id: { eq: $id }) {
      html
      frontmatter {
        title
        image {
          childImageSharp {
            gatsbyImageData(width: 600)
          }
        }
      }
    }
  }
`;

You use the getImage helper function to get the final image from the File node. It takes a bit less code then grabbing the property by hand.

const image = post.frontmatter.image.childImageSharp.gatsbyImageData;

How to Lazy Load Images Coming From Markdown Files

To lazy load images you reference in Markdown content, you install gatsby-remark-images plugin. When using this plugin, you can keep images in the same folder as Markdown files.

Install the packages.

npm install gatsby-remark-images gatsby-plugin-sharp

Add the plugins to your gatasby-config.js. Notice, gatsby-remark-images needs to go under gatsby-transform-remark plugins property. You should also specify the max width of your content, so the plugin can resize your images to be only as wide as the content can get.

// gatsby-config.js

plugins: [
  'gatsby-plugin-sharp',
  {
    resolve: 'gatsby-transformer-remark',
    options: {
      plugins: [
        {
          resolve: 'gatsby-remark-images',
          options: {
            maxWidth: 600,
          },
        },
      ],
    },
  },
];

And you are done! Put your images next to the Markdown file and insert them in your content. The plugin should take care of setting up lazy loading.

Some text in your blog post about forests.

![Alt text goes here](./forest.jpg)

More text.

Summary

You learned how to lazy load both static and dynamic images. You also learned how to lazy load images used in Markdown content.

You should study documentations of the plugins to learn about available configuration options.

References