I have 16 images that I want to render out onto a website in a grid format.
I\'m using the following plugins for this:
gatsby-image
Despite the situation in currently asked question, where all of 16 images are inside the images folder which is then easy to just run a query to fetch all possible images. Like this (accepted answer):
{
allImageSharp {
edges {
node {
id
fluid(maxWidth: 200, maxHeight: 200) {
...GatsbyImageSharpFluid
}
}
}
}
}
But in most cases you'd like to have subfolders inside the images folder for arranging images according to requirement. (At least that was my case).
So in that case: (where you have images inside a subfolder let's say beach inside images you can follow this approach)
export const query = graphql`
query {
allFile(filter: { relativeDirectory: { eq: "beach" } }) {
edges {
node {
id
childImageSharp {
fluid {
...GatsbyImageSharpFluid_withWebp
}
}
}
}
}
}
`
This is a small egghead clip if you want to see in video.
Here is a simple example with TypeScript and SVG support:
Update gatsby-config.js
module.exports = {
plugins: [
{
resolve: `gatsby-source-filesystem`,
options: {
name: `images`,
path: `${__dirname}/src/assets/images`,
},
},
],
};
Create Image Component
import * as React from 'react';
import { FC } from 'react';
import { graphql, StaticQuery } from 'gatsby';
import Img from 'gatsby-image';
interface IProps {
name: string;
alt: string;
className?: string;
}
const Image: FC<IProps> = ({ name, alt, className }) => (
<StaticQuery
query={graphql`
query AllImages {
allImagesWithoutSVGExtension: allFile(
filter: {
sourceInstanceName: { eq: "images" }
extension: { regex: "/jpeg|jpg|png|gif/" }
}
) {
nodes {
publicURL
extension
sharp: childImageSharp {
fluid {
originalName
...GatsbyImageSharpFluid_withWebp
}
}
}
}
allImagesWithSVGExtension: allFile(
filter: {
sourceInstanceName: { eq: "images" }
extension: { eq: "svg" }
}
) {
nodes {
publicURL
extension
}
}
}
`}
render={({ allImagesWithoutSVGExtension, allImagesWithSVGExtension }) => {
const isNameWithSVGExtension = name.indexOf('svg') !== -1;
const renderImageWithSVGExtension = () => {
const image = allImagesWithSVGExtension.nodes.find(
({ publicURL }) => publicURL && publicURL.indexOf(name) !== -1
);
return image ? (
<img
className={className}
src={image.publicURL}
alt={alt}
width={100}
height={100}
/>
) : null;
};
const renderImageWithoutSVGExtension = () => {
const image = allImagesWithoutSVGExtension.nodes.find(
({ publicURL }) => publicURL && publicURL.indexOf(name) !== -1
);
return image && image.sharp && image.sharp.fluid ? (
<Img className={className} fluid={image.sharp.fluid} alt={alt} />
) : null;
};
return isNameWithSVGExtension
? renderImageWithSVGExtension()
: renderImageWithoutSVGExtension();
}}
/>
);
export { Image };
Use Image component as
<Image name="logo.svg" alt="compony logo" />
or
<Image name="logo.png" alt="compony logo" />
The easiest way is to create an image provider:
import React from 'react'
import { graphql, useStaticQuery } from 'gatsby'
import Img from 'gatsby-image'
const Image = ({ fileName, alt, style }) => {
const { allImageSharp } = useStaticQuery(graphql`
query {
allImageSharp {
nodes {
fluid(maxWidth: 1600) {
originalName
...GatsbyImageSharpFluid_withWebp
}
}
}
}
`)
const fluid = allImageSharp.nodes.find(n => n.fluid.originalName === fileName)
.fluid
return (
<figure>
<Img fluid={fluid} alt={alt} style={style} />
</figure>
)
}
export default Image;
And then, after importing, easily insert the image which you need:
<Image fileName="yourImage.jpg" style={{ width: '100%' }} alt="" />
Having a poke around in GraphiQL should help you, especially the Explorer. Although remember that Gatsby fragments won't work in GraphiQL.
{
allImageSharp {
edges {
node {
id
fluid(maxWidth: 200, maxHeight: 200) {
...GatsbyImageSharpFluid
}
}
}
}
}
So the above should be equal to something like the following query which will work in GraphiQL
{
allImageSharp {
edges {
node {
id
fluid(maxHeight: 200, maxWidth: 200) {
src
srcSet
base64
aspectRatio
originalImg
sizes
}
}
}
}
}
Then your component can use this same query and render the results like this:
import React from "react"
import { graphql } from "gatsby"
import Img from "gatsby-image"
const imgGridStyle = {
display: 'grid',
gridTemplateColumns: `repeat(auto-fill, 200px)`
};
export default ({ data }) => (
<div>
<h1>Hello gatsby-image</h1>
<div style={imgGridStyle}>
{data.allImageSharp.edges.map(edge =>
<Img fluid={edge.node.fluid} />
)}
</div>
</div>
)
export const query = graphql`
query {
allImageSharp {
edges {
node {
id
fluid(maxWidth: 200, maxHeight: 200) {
...GatsbyImageSharpFluid
}
}
}
}
}
`
You can easily loop over the resulting array of imageSharp nodes returned from the query in data.allImageSharp.edges.map
. Then pass each node's fluid
property, as the fluid
prop to gatsby-image
.
Note: This renders every imageSharp node in your project, which may or may not be what you want to achieve.
To filter the query by folder name, you could adjust the query like this:
{
allImageSharp(filter: {fileAbsolutePath: {regex: "/(myFolder)/" }}) {
edges {
node {
id
fluid(maxWidth: 200, maxHeight: 200) {
...GatsbyImageSharpFluid
}
}
}
}
}
Have a look at the gatsby graphql reference for filter as to how you might perform other kinds of filters on the query.