Search code examples
htmlcssreactjsresponsive-designgatsby-image

Gatsby-Image: Different images for Mobile / Desktop?


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.


Solution

  • 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
            }
          }
        }
      }
    `