DEV Community

loading...
Cover image for How To Query Gatsby Images with GraphQL

How To Query Gatsby Images with GraphQL

lukekyl profile image Kyle Luke ・4 min read

When learning new tools, often times the most challenging parts will lead to the coolest features and benefits. This was the case for me when learning to use Gatsby, and how GraphQL works. I struggled hard at figuring out how to use the gatsby-image plugin, and how to query GraphQL assets to display individual images on in the correct spot.

So why Gatsby (and why Gatsby Image)?

For many reasons React developers are choosing to use static site generator such as Gatsby or Next.js. Static site generators create blazing fast single page applications, and also allow for a quicker and simplified development process with multiple available plugins. One plugin that Gatsby does very well is Gatsby-images. Gatsby-images is a react component that lazy-loads images with a blur-up effect, speeding up page loading times dramatically and holding image positions until loaded. The benefits of using Gatsby Images were a major benefit for my portfolio site, so I opted to learn how querying in GraphQL works so I would then be able to individually place a fast loading Gatsby Image on demand.

Traditional React Image Example

The original way to import an image into React is through

import example from '../images/example.jpg'
<img className="example" src={example}/>
Enter fullscreen mode Exit fullscreen mode

and produces an image that slowly loads from the top down before displaying.

Gatsby Image Example

Gatsby Images are lazy-loaded, starting with the full image visible and a blur effect applied. As the browser has time to download, the image scales up until full resolution.


Image from CSS Tricks: Ways to Organize and Prepare Images for a Blur-Up Effect Using Gatsby

Pretty cool, huh!?

How To Query Gatsby Images with GraphQL

1. Install the Gatsby Image plugin

npm install gatsby-image gatsby-transformer-sharp gatsby-plugin-sharp
Enter fullscreen mode Exit fullscreen mode

2. Add Gatsby Image plugin to Gatsby Config file

plugins: [ 
{
resolve: `gatsby-source-filesystem`,
options: { name: `images`,    
path: `${__dirname}/src/images`,
},    
},    
`gatsby-transformer-sharp`,    
`gatsby-plugin-sharp`
, ...additionalplugins 
]
Enter fullscreen mode Exit fullscreen mode

3. Add your images to /src/images folder

The images folder will be mapped in our query later on to select individual images for conversion and import.

4. Import Gatsby Image component and GraphQL into Gatsby page file

import { graphql } from "gatsby"
import Img from "gatsby-image"
Enter fullscreen mode Exit fullscreen mode

5. Query GraphQL to select image/images and convert to Gatsby Images

export const fluidImage = graphql`
    fragment fluidImage on File {
        childImageSharp {
          fluid(maxWidth: 1600) {
            ...GatsbyImageSharpFluid
          }
          original {
            width
          }
        }
    }
`;

export const pageQuery = graphql`
     query {
       projectHero: file(
         relativePath: { eq: "exampleHero.jpg" }
       ) {
         ...fluidImage
       }
       imageOne: file(
         relativePath: { eq: "examplephoto-1.jpg" }
       ) {
         ...fluidImage
       }
       imageTwo: file(
         relativePath: { eq: "examplephoto-2.jpg" }
       ) {
         ...fluidImage
       }
       imageThree: file(
         relativePath: { eq: "examplephoto-3.jpg" }
       ) {
         ...fluidImage
       }
       imageFour: file(
         relativePath: { eq: "examplephoto-4.jpg" }
       ) {
         ...fluidImage
       }
     }
`;
Enter fullscreen mode Exit fullscreen mode

6. Import Gatsby Image tag into page and position/style with CSS

<Img fluid={props.data.file.childImageSharp.fluid} />
Enter fullscreen mode Exit fullscreen mode

Full Component Example

import React, { Component } from "react"
import Layout from "../components/layout"
import SEO from "../components/seo"

import { graphql } from 'gatsby';
import Img from 'gatsby-image';

const pageId="example"

export const fluidImage = graphql`
    fragment fluidImage on File {
        childImageSharp {
          fluid(maxWidth: 1600) {
            ...GatsbyImageSharpFluid
          }
          original {
            width
          }
        }
    }
`;

export const pageQuery = graphql`
     query {
       projectHero: file(
         relativePath: { eq: "exampleHero.jpg" }
       ) {
         ...fluidImage
       }
       imageOne: file(
         relativePath: { eq: "examplephoto-1.jpg" }
       ) {
         ...fluidImage
       }
       imageTwo: file(
         relativePath: { eq: "examplephoto-2.jpg" }
       ) {
         ...fluidImage
       }
       imageThree: file(
         relativePath: { eq: "examplephoto-3.jpg" }
       ) {
         ...fluidImage
       }
       imageFour: file(
         relativePath: { eq: "examplephoto-4.jpg" }
       ) {
         ...fluidImage
       }
     }
`;


class Example extends Component {

  render() {
    return (
      <Layout>
        <SEO title={pageId} />
        <div
          className="hero project-hero d-flex align-items-center"
          style={{
            backgroundSize: "cover",
            backgroundPosition: "50% 65%",
            overflow: "hidden",
          }}
        >
          <Img
            fluid={this.props.data.projectHero.childImageSharp.fluid}
            imgStyle={{ objectFit: "cover" }}
            alt="Example project hero image."
          />
        </div>
            <Card className="no-radius">
              <Img
                fluid={this.props.data.imageOne.childImageSharp.fluid}
                imgStyle={{ objectFit: "cover" }}
                alt="Example project example image."
              />
              <Img
                fluid={this.props.data.imageTwo.childImageSharp.fluid}
                imgStyle={{ objectFit: "cover" }}
                alt="Example project example image."
              />
              <Img
                fluid={this.props.data.imageThree.childImageSharp.fluid}
                imgStyle={{ objectFit: "cover" }}
                alt="Example project example image."
              />
              <Img
                fluid={this.props.data.imageFour.childImageSharp.fluid}
                imgStyle={{ objectFit: "cover" }}
                alt="Example project example image."
              />
            </Card>
      </Layout>
)}}
export default Example
Enter fullscreen mode Exit fullscreen mode

Other Thoughts

Making Gatsby Image a component, and passing URL path as props.

To consolidate and DRY up multiple pages that might put into use the same Gatsby Image queries, you can create a component with the Gatsby Image query, and pass URL paths as props.

Using Flexbox vs Float (Float breaks Gatsby Image)

One issue developers might notice while implementing Gatsby Images is that they break with the use of CSS float properties. To overcome this issue, many developers make use of Flexbox instead of float, to shape and align images on the page.
https://dev.to/steelvoltage/struggling-with-gatsby-images-1ao5

Run Gatsby Development Server and view GraphQL Playground

The Gatsby GraphQL playground is particularly fun to play around with and test your queries. It will help you identify what is being held in your GraphQL data and how to get to it, and doing some digging around will help you understand how GraphQL queries work.
To view the playground, run your Gatsby development server and visit: http://localhost:8000/___graphql

Making it Work

I got stuck several times during the process of trying to query through my images with GraphQL, and then again displaying them correctly as Gatsby Images. Hopefully this post guides you through querying GraphQL for your own Gatsby project, and how to display images correctly using the benefits of Gatsby Images.

Did you find this helpful? If you have used Gatsby Image, what got YOU stuck while learning?

Additional Resources

Discussion (0)

pic
Editor guide