It can be time-consuming to ensure that users have an excellent experience with images on the web.
With Gatsby, we can take advantage of the capabilities of gatsby-plugin-image
to achieve the best performance with little setup and a complete toolkit. Gatsby Image plugin handles the challenging aspects of creating images in various sizes and formats.
This article will teach us how to dynamically access local images in Gatsby applications by using the GatsbyImage
component of the gatsby-plugin-image
module and GraphQL. GatsbyImage
differing from StaticImage
(in the same gatsby-plugin-image module) is used when the image source is variable or computed.
Sandbox
We completed this project in a Codesandbox. To get started quickly, fork the Codesandbox or run the project.
GitHub Repository:
https://github.com/Olanetsoft/dynamic-image-with-gatsby-plugin-image
Prerequisite
The following are required to complete this post for a better understanding:
- Knowledge of JavaScript and React.js
- Knowledge of Gatsby.js is not required but preferred
- Gatsby CLI should be installed globally. Learn how to install it here
Getting Started with Gatsby
Gatsby is an open-source static site generator (SSG). Gatsby uses efficient pre-configuration for rapid page loads, code splitting, server-side rendering, intelligent image loading, asset optimization, and data prefetching.
Gatsby uses webpack, GraphQL and React.js to build and render high-performance web apps. Gatsby can also be used to create progressive web apps that adhere to current web standards and are designed for speed and security.
Creating a new project and Installing Dependencies
To create a new project, use the gatsby new <project name>
command to scaffold a new project.
This command creates a new Gatsby project for us.
To start our application, we run the following command.
1cd <project name>2 npm run devevelop
Once the app is initialized, and the dependencies are installed, we will see a message with instructions for navigating to our site and running it locally.
Gatsby will start a hot-reloading development environment accessible by default at http://localhost:8000
Building our project
In the previous step, we installed and started our application, and now we can use the GatsbyImage
component in our Gatsby site like we would use an <img>
element in HTML. gatsby-plugin-image
ships with the default Gatsby starter we installed.
We download sample images to our computer and save it inside src/images
in our project folder as shown below:
Next, to create a blank home page with a title, we update pages/index.js
file with the following code snippet:
1import * as React from "react";2 import { GatsbyImage, getImage } from "gatsby-plugin-image";3 import { graphql } from "gatsby";45 // styles6 const pageStyles = {7 display: "flex",8 flexDirection: "column",9 alignItems: "center",10 justifyContent: "center",11 };1213 // title14 const titleStyles = {15 fontSize: "2rem",16 fontWeight: "bold",17 marginBottom: "1rem",18 };1920 // name21 const nameStyle = {22 fontSize: "1.5rem",23 fontWeight: "bold",24 marginBottom: "1rem",25 };2627 // markup28 const IndexPage = (props) => {29 return (30 <div style={pageStyles}>31 <h1 style={titleStyles}>Using dynamic image in gatsby-plugin-image</h1>32 //...33 </div>34 );35 };3637 export default IndexPage;
We should have something similar to this below:
When we rebuild our application, the images we added locally are included in Gatsby’s data layer and we can retrieve them using Graphql. Subsequently, we will use the GatsbyImage
component to dynamically render these images.
Adding images to our page query
Using sharp
, Gatsby creates a childImageSharp
node in it’s Graphql data layer for all local image. We will query the image data from this node and depending on our data source, the actual file node structure may differ. In the page query of src/pages/index.js
we have:
1query {2 photos: allFile(3 sort: { fields: base, order: ASC }4 filter: { extension: { regex: "/(jpeg)/" } }5 ) {6 edges {7 node {8 id9 base10 childImageSharp {11 gatsbyImageData(12 width: 60013 )14 fluid {15 ...GatsbyImageSharpFluid_withWebp16 }17 }18 }19 }20 }21 }
Configuring our Images
By providing arguments to the gatsbyImageData
resolver, we can customize the image. When lazy loading, we can additionally adjust the size, layout, and placeholder type used.
1query {2 photos: allFile(3 sort: { fields: base, order: ASC }4 filter: { extension: { regex: "/(jpeg)/" } }5 ) {6 edges {7 node {8 id9 base10 childImageSharp {11 gatsbyImageData(12 placeholder: DOMINANT_COLOR13 height: 40014 formats: AUTO15 width: 60016 )17 fluid {18 ...GatsbyImageSharpFluid_withWebp19 }20 }21 }22 }23 }24 }
Advanced image processing techniques are also available. The API documentation contains a complete list of options.
Displaying our Images
We will update src/pages/index.js
with the following code snippet:
1import * as React from "react";2 import { GatsbyImage, getImage } from "gatsby-plugin-image";3 import { graphql } from "gatsby";45 //...67 // markup8 const IndexPage = (props) => {9 return (10 <div style={pageStyles}>11 <h1 style={titleStyles}>Using dynamic image in gatsby-plugin-image</h1>12 {props.data.photos.edges.map((img) => (13 <div key={img.node.id}>14 <GatsbyImage15 fluid={img.node.childImageSharp.fluid}16 alt={img.node.base.split("-").join(" ").split(".")[0]}17 image={getImage(img.node)}18 />19 <h2 style={nameStyle}>20 {img.node.base.charAt(0).toUpperCase() +21 img.node.base.substr(1).split("-").join(" ").split(".")[0]}22 </h2>23 </div>24 ))}25 </div>26 );27 };2829 export const pageQuery = graphql`30 query {31 photos: allFile(32 sort: { fields: base, order: ASC }33 filter: { extension: { regex: "/(jpeg)/" } }34 ) {35 edges {36 node {37 id38 base39 childImageSharp {40 gatsbyImageData(41 placeholder: DOMINANT_COLOR42 height: 40043 formats: AUTO44 width: 60045 )46 fluid {47 ...GatsbyImageSharpFluid_withWebp48 }49 }50 }51 }52 }53 }54 `;55 export default IndexPage;
In the code snippet above,
- To display the image on the page, we utilize the
GatsbyImage
component. - We used the getImage() function as an optional utility to make the code cleaner.
- The
GatsbyImage
component accepts a File provided viagetImage()
and outputsfile.childImageSharp.gatsbyImageData
.
Testing our application we should have something similar to what is shown in the screenshot below:
https://www.loom.com/share/8ce45062f15c44ad9ae0f89d66bf0724
Customizing gatsbyImageData
With our GatsbyImage instance, we can customize placeholders, formats, transformations, quality, height etc.
Let us update the page query in src/pages/index.js
to the following:
1//...23 // markup4 const IndexPage = (props) => {5 return (6 <div style={pageStyles}>7 // ...8 </div>9 );10 };1112 export const pageQuery = graphql`13 query {14 photos: allFile(15 sort: { fields: base, order: ASC }16 filter: { extension: { regex: "/(jpeg)/" } }17 ) {18 edges {19 node {20 id21 base22 childImageSharp {23 gatsbyImageData(24 placeholder: BLURRED25 height: 40026 formats: AUTO27 width: 60028 quality: 70 # 50 by default29 transformOptions: { grayscale: true }30 )31 fluid {32 ...GatsbyImageSharpFluid_withWebp33 }34 }35 }36 }37 }38 }39 `;40 export default IndexPage;
The following is an example of what our application should look like:
https://www.loom.com/share/b1967767a22e4189bf5288b644dcca35
Conclusion
In this article, we learned how to use the GatsbyImage
component of the gatsby-plugin-image
module. We also learned how to apply optimizations and transformations to the rendered image.