DEV Community

loading...
Cover image for Loading Gatsby Images Above the Fold

Loading Gatsby Images Above the Fold

arnonate profile image Nate Arnold ・2 min read

Gatbsy ships with a nice utility called gatsby-image (You can check out the API here). When using the <Img /> component in conjunction with gatbsy-image-sharp and gatbsy-transform-sharp you get a modern and graceful way to handle image loading and responsive image sizing.

The default loading prop on a Gatsby Image component is "lazy", however, and this can cause some flickering when navigating from page to page IF your image is above the fold.

Background on Gatsby Image

gatsby-image works by drawing on GraphQL fragments to generate a React component for handling your images. When the component loads it will load with a srcSet of different image qualities, sizes and types. Following a simple example, we query for a local project image using prepared GraphQL fragments:

file(relativePath: { eq: "images/default.jpg" }) {
  childImageSharp {
    fluid(maxWidth: 400) {
      ...GatsbyImageSharpFluid
    }
  }
}

This returns an object with the following interface:

export interface FluidObject {
  aspectRatio: number
  src: string
  srcSet: string
  sizes: string
  base64?: string
  tracedSVG?: string
  srcWebp?: string
  srcSetWebp?: string
  media?: string
}

The API is fairly robust and all the options can be found from the link above. You can use the data returned in a gatsby-image component:

<Img
  fluid={data.file.childImageSharp.fluid}
  alt="Gatsby Docs are awesome"
/>

The result is actually a <picture> element with a srcSet that will load lazily and only load the appropriate image (the image that is best suited for a user's browser).

<div class="gatsby-image-wrapper" style="position: relative; overflow: hidden;">
  <div aria-hidden="true" style="width: 100%; padding-bottom: 16%;"></div>
  <picture>
    <source type="image/webp" srcset="srcSet" sizes="sizes">
    <source srcset="srcSet" sizes="sizes">
    <img sizes="(max-width: 400px) 100vw, 400px" srcset="srcSet" src="src" alt="Gatsby Image" loading="lazy" style="position: absolute; top: 0px; left: 0px; width: 100%; height: 100%; object-fit: cover; object-position: center center; opacity: 1; transition: none 0s ease 0s;">
  </picture>
</div>

Gatbsy Image handles JPEGs, PNGs, WebP and Base64 and will output all of them if you tell it to. I really love this pattern.

Fixing the Flicker

Recently I developed a Gatsby/Wordpress starter repo and used Gatsby Image for the logo in the header. Clicking from page to page the content loads incredibly fast, but the logo image in the header would flicker every time I changed pages. The fix is incredibly simple. When using the <Img /> component above the fold override the default loading behavior.

This:

<Img
  fluid={data.file.childImageSharp.fluid}
  alt="Gatsby Docs are awesome"
/>

Becomes this:

<Img
  fluid={data.file.childImageSharp.fluid}
  alt="Gatsby Docs are awesome"
  loading="eager"
/>

I love simple solutions to slightly annoying UI bugs 😊. Check out my starter repo if you are thinking of starting a Gatsby/WP project soon: https://github.com/arnonate/gatbsy-wordpress-starter.

Discussion

pic
Editor guide