How to Display Thumbnails in Markdown Posts in Gatsby.js
Thank you for your continued support.
This article contains advertisements that help fund our operations.
Table Of Contents
⇨ Table of contents for React articles is here
This article summarizes how to set up thumbnails for posts written in Markdown in Gatsby.js.
Introduction
There are two methods introduced here.
One is a simple method of placing an image and specifying its absolute path, and the other is a method using GraphQL to compress and optimize the image.
Also, note that the plugin for images has changed from gatsby-image
to gatsby-plugin-image
, and the way you write the code will vary depending on the plugin used.
Simple Method to Set Thumbnails
Required Plugin
You may already have it installed, but you need the following plugin:
npm install gatsby-source-filesystem
Where to Place Images
Place images under the /static/
directory.
For example, place the image at /static/images/sample.png
.
Check gatsby-config.js
Depending on your project setup, the following entry may or may not be present. If it is present, you're good to go. If not, add it to the plugins:[]
array in the module.exports
.
{
resolve: `gatsby-source-filesystem`,
options: {
name: `media`,
path: `${__dirname}/static`,
},
},
Add to gatsby-node.js
Add a string for the thumbnail's absolute path to the schema's Frontmatter
.
exports.createSchemaCustomization = ({ actions }) => {
const { createTypes } = actions
createTypes(
//~~~snip
`
type Frontmatter {
title: String,
thumbnail: String, //← Add this
}
`
)
//~~~snip
}
Write the Thumbnail Path in the Markdown
---
title: How to display thumbnails in Gatsby
thumbnail: "/images/sample.png"
---
Call It in the GraphQL Query of the Page
export const query = graphql`
query PostBySlug($slug: String!) {
post: markdownRemark(
fields: { slug: { eq: $slug }}
) {
id
html
frontmatter {
title
thumbnail // ← Add this to frontmatter
}
}
}
`
Display the Image
<img src="{edge.node.frontmatter.thumbnail}" />
That's the simple method.
Method Using GraphQL to Compress and Optimize the Image
Install Required Plugins
npm install gatsby-plugin-image gatsby-transformer-sharp gatsby-plugin-sharp gatsby-source-filesystem
Where to Place the File
This time, you can't specify the absolute path, so place the image in a directory that is easy to reference with a relative path from the Markdown file.
├── content
│ ├── blog
│ └── slug
│ └── ja.md //記事ファイル
└── thumbnail
└── sample.png
The relative path from the article file is ../../thumbnail/sample.png
.
Add to gatsby-config.js
Add the following three items to the plugins:[]
array in the module.exports
.
Be careful as some of the same content may already be written.
`gatsby-plugin-image`,
`gatsby-transformer-sharp`,
{
resolve: `gatsby-source-filesystem`,
options: {
name: `thumbnail`,
path: `${__dirname}/content/thumbnail`,
},
},
Add to gatsby-node.js
Frontmatter
exports.createSchemaCustomization = ({ actions }) => {
const { createTypes } = actions
createTypes(
//~~~snip
`
type Frontmatter {
title: String,
thumbnail: File @fileByRelativePath,
}
`
)
//~~~snip
}
This outputs the File
type, and @fileByRelativePath
allows you to specify the relative path.
Check GraphQL
Go to http://localhost:8000/___graphql
and confirm that thumbnail
in Frontmatter
outputs several fields.
Retrieve Data in the Page
Now that you know many fields are output, you will use the gatsbyImageData
field to display an optimized image.
export const pageQuery = graphql`
{
allMarkdownRemark() {
edges {
node {
frontmatter {
title
thumbnail {
childImageSharp {
gatsbyImageData
}
}
}
}
}
}
}
`
Display the Thumbnail Image
Use GatsbyImage
from gatsby-plugin-image
to display the image.
import { GatsbyImage } from "gatsby-plugin-image"
const Posts = ({ data }) => {
const edges = data.allMarkdownRemark.edges
return (
<div>
{edges.map(edge => (
<GatsbyImage
image={
edge.node.frontmatter.thumbnail?.childImageSharp.gatsbyImageData
}
alt=""
height="140"
/>
))}
</div>
)
}
export default Posts
export const pageQuery = graphql`
{
allMarkdownRemark() {
edges {
node {
frontmatter {
title
thumbnail {
childImageSharp {
gatsbyImageData
}
}
}
}
}
}
}
`
Check the Output
Here's what the output looks like in HTML.
<picture>
<source
type="image/avif"
srcset="
/static/638be90904f9f9248d3c69cb2992c562/5e601/react.avif 320w,
/static/638be90904f9f9248d3c69cb2992c562/14473/react.avif 640w,
/static/638be90904f9f9248d3c69cb2992c562/1f487/react.avif 1280w
"
sizes="(min-width: 1280px) 1280px, 100vw" />
<source
type="image/webp"
srcset="
/static/638be90904f9f9248d3c69cb2992c562/a0615/react.webp 320w,
/static/638be90904f9f9248d3c69cb2992c562/6789b/react.webp 640w,
/static/638be90904f9f9248d3c69cb2992c562/3602f/react.webp 1280w
"
sizes="(min-width: 1280px) 1280px, 100vw" />
<img
height="905"
width="1280"
src="/static/638be90904f9f9248d3c69cb2992c562/eed66/react.png"
alt=""
loading="lazy"
decoding="async"
sizes="(min-width: 1280px) 1280px, 100vw"
srcset="
/static/638be90904f9f9248d3c69cb2992c562/aaddb/react.png 320w,
/static/638be90904f9f9248d3c69cb2992c562/94304/react.png 640w,
/static/638be90904f9f9248d3c69cb2992c562/eed66/react.png 1280w
"
/></picture>
You can also pass className as props to easily style with CSS.
<GatsbyImage
className="object-cover h-36 hover:opacity-70 duration-200"
image={edge.node.frontmatter.socialImage?.childImageSharp.gatsbyImageData}
alt=""
height="140"
/>
How to Use gatsby-plugin-images
If Using the Old gatsby-image
GraphQL Query Changes
In the older version, you would retrieve the fluid
data to display images.
export const pageQuery = graphql`
query {
allMarkdownRemark() {
nodes {
frontmatter {
title
thumbnail {
childImageSharp {
fluid(maxWidth: 1280) {
...GatsbyImageSharpFluid
}
}
}
}
}
}
}
`
How to Display
The props will now use fluid
.
import Image from "gatsby-image"
const BlogIndex = ({ data, location }) => {
const posts = data.allMarkdownRemark.nodes
return (
<div>
{posts.map(post => {
const thumbnail = post.frontmatter.thumbnail?.childImageSharp.fluid
return (
<div>
<Image fluid={thumbnail} alt="" />
</div>
)
})}
</div>
)
}
export default BlogIndex
Conclusion
That's all.
I hope this helps someone.