3

I want to render my gatsby-image conditionally: I want to have different images for mobile & desktop. So I need to swap them out.

Right now I am doing this:

<Desktop>
  {heroImage && (
      <MyGatsbyImage
        img={heroImage}
      />
  )}
</Desktop>
<Mobile>
  {heroImageXS && (
      <MyGatsbyImage
        img={heroImageXS}
      />
  )}
</Mobile>

where <Desktop> & <Mobile> are styled components with media-queries that have display: block / display:none depending on the viewport.

However: Is this the most effective solution here? Is my solution always loading both images in the background?

Without gatsby-image, I would do is this:

<picture>
   <source 
      media="(min-width: 650px)"
      srcset="images/img1.png">
   <source 
      media="(min-width: 465px)"
      srcset="images/img2.png">
   <img src="images/img-default.png" 
   alt="a cute kitten">
</picture>

...but that would mean to not use gatsby-image here - which I do want to use.

R. Kohlisch
  • 2,823
  • 6
  • 29
  • 59

1 Answers1

11

What you are referring to is called art direction. Using the method in your question will likely result in the browser downloading both images.

gatsby-image has support for art direction and give a great example on how to apply it in the documentation:

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

export default ({ data }) => {
  // Set up the array of image data and `media` keys.
  // You can have as many entries as you'd like.
  const sources = [
    data.mobileImage.childImageSharp.fluid,
    {
      ...data.desktopImage.childImageSharp.fluid,
      media: `(min-width: 768px)`,
    },
  ]

  return (
    <div>
      <h1>Hello art-directed gatsby-image</h1>
      <Img fluid={sources} />
    </div>
  )
}

export const query = graphql`
  query {
    mobileImage: file(relativePath: { eq: "blog/avatars/kyle-mathews.jpeg" }) {
      childImageSharp {
        fluid(maxWidth: 1000, quality: 100) {
          ...GatsbyImageSharpFluid
        }
      }
    }
    desktopImage: file(
      relativePath: { eq: "blog/avatars/kyle-mathews-desktop.jpeg" }
    ) {
      childImageSharp {
        fluid(maxWidth: 2000, quality: 100) {
          ...GatsbyImageSharpFluid
        }
      }
    }
  }
`
epsilon42
  • 1,863
  • 13
  • 26
  • You also could use `GatsbyImageSharpSizes` instead of `GatsbyImageSharpFluid`... Though, it's all dated now as the `gatsby-image` package is now deprecated in favour of [gatsby-plugin-image](https://www.gatsbyjs.com/docs/reference/built-in-components/gatsby-plugin-image/), which has a different syntax. – Alex Klaus Sep 14 '21 at 10:57