Preventing image jank with Sanity images in Gatsby (gatsby-image vs @sanity/image-url)

9 replies
Last updated: Nov 27, 2020
how do I achieve this same result and avoid this content jankiness (image pushing down content) in Sanity? https://css-tricks.com/do-this-to-improve-image-loading-on-your-website/
I am currently editing
Blog with Gatsby
template but so far dumbfounded on how to solve this with sanity (gatsby-image seems to do it for you). Do I modify in this file here? https://github.com/ajmalafif/afif.dev/blob/develop/web/src/lib/image-url.js
or somehow I can achieve this “lazy-loading” effect by combining both
gatsby-image
and
sanity/image-url
? https://github.com/sanity-io/gatsby-source-sanity#fluid
AI Update

Looking at the CSS Tricks article you linked, it's about preventing content layout shift (CLS) when images load by reserving the proper space with aspect ratio. The good news is that gatsby-plugin-image handles this automatically when you use it with Sanity images through gatsby-source-sanity!

The modern approach with gatsby-source-sanity and gatsby-plugin-image gives you lazy loading, proper aspect ratios, and prevents content jank out of the box. Here's how to set it up:

Use the gatsbyImageData field in your GraphQL queries. This automatically includes dimensions and generates the proper placeholder:

import {GatsbyImage} from 'gatsby-plugin-image'

export const query = graphql`
  query {
    sanityPost {
      mainImage {
        asset {
          gatsbyImageData(
            width: 800
            placeholder: BLURRED
            fit: FILLMAX
          )
        }
      }
    }
  }
`

function BlogPost({data}) {
  return (
    <GatsbyImage 
      image={data.sanityPost.mainImage.asset.gatsbyImageData} 
      alt="Blog post image"
    />
  )
}

The GatsbyImage component automatically:

  • Reserves space using the image's aspect ratio (preventing layout shift)
  • Lazy loads images as they enter the viewport
  • Shows a blurred placeholder while loading
  • Generates responsive srcsets

If You're Using image-url.js Directly

If you need to use @sanity/image-url outside of GraphQL (like in your image-url.js file), you can still prevent jank by:

  1. Query the image dimensions from Sanity and use them to set aspect ratio CSS:
// In your GraphQL query, get dimensions
mainImage {
  asset {
    _id
    metadata {
      dimensions {
        width
        height
        aspectRatio
      }
    }
  }
}
  1. Apply aspect ratio styling to reserve space:
<div style={{
  aspectRatio: `${width} / ${height}`,
  position: 'relative'
}}>
  <img 
    src={imageUrlBuilder.image(imageRef).width(800).url()}
    loading="lazy"
    style={{
      position: 'absolute',
      width: '100%',
      height: '100%',
      objectFit: 'cover'
    }}
  />
</div>

For Portable Text / Block Content

If you're rendering images inside Portable Text, use the @portabletext/react serializer with GatsbyImage:

import {PortableText} from '@portabletext/react'
import {GatsbyImage} from 'gatsby-plugin-image'
import {getGatsbyImageData} from 'gatsby-source-sanity'

const sanityConfig = {projectId: 'your-id', dataset: 'production'}

const components = {
  types: {
    image: ({value}) => {
      const imageData = getGatsbyImageData(
        value.asset._ref,
        {maxWidth: 800},
        sanityConfig
      )
      return <GatsbyImage image={imageData} alt={value.alt || ''} />
    }
  }
}

<PortableText value={portableTextContent} components={components} />

Don't Modify image-url.js - Use gatsbyImageData Instead

The key insight is that you don't need to combine gatsby-image and @sanity/image-url. The gatsby-source-sanity plugin already integrates with gatsby-plugin-image through the gatsbyImageData field, giving you all the performance benefits including preventing layout shift automatically.

Your image-url.js file should only be used for cases where you need direct URL manipulation (like social media meta tags), not for rendering images in your components. For component rendering, always prefer the gatsbyImageData approach which handles aspect ratios, lazy loading, and placeholder generation automatically.

Show original thread
9 replies
it seems from observation and this is anecdotal, seems like Gatsby solution do something like this to avoid the content jump https://css-tricks.com/preventing-content-reflow-from-lazy-loaded-images/
will investigate how can I figure this out for sanity on gatstby
I just published gatsby-plugin-sanity-image to provide an easy way to handle this. Use the
ImageWithPreview
version to avoid the CLS issue.
shout out to
user L
now I have a solid base to start figuring this jank-free content layout. With
Slow 3G
network on devtools I have
lqip
right away!
kinda looks this with
gatsby-image
from the markup it seems like it does something differently
You can get those thumbnails to scale up and keep your content from jumping around by putting the image in a container sized how you want, then setting the CSS on the image to
display: block; width: 100%
. Unless you are cropping the image, the LQIP should be the same aspect ratio. If you are cropping the image, you can instead set the absolute dimensions on the img element and use
object-fit: cover
on it.
again
user L
to the rescue! thanks that’s a really good pointer
user L
is there a way to enable discussion tab on https://github.com/coreyward/gatsby-plugin-sanity-image/ since I encounter difficulties on resizing the
lqip
which I am not sure if it’s a bug (hence i dont think i should create an issue ticket) but I also want to ask how since I tried and failed
figured it out by setting the CSS for
[data-lqip]
and its all worked out now! highly recommend this plugin! Now I know how to make the site jank-free 🥳

Sanity – Build the way you think, not the way your CMS thinks

Sanity is the developer-first content operating system that gives you complete control. Schema-as-code, GROQ queries, and real-time APIs mean no more workarounds or waiting for deployments. Free to start, scale as you grow.

Was this answer helpful?