|
| 1 | +--- |
| 2 | +title: Working with Images in Markdown & MDX |
| 3 | +--- |
| 4 | + |
| 5 | +When building Gatsby sites composed primarily of [markdown](/docs/how-to/routing/adding-markdown-pages/) or [MDX](/docs/how-to/routing/mdx/), insertion of images can enhance the content. You can add images in multiple ways which will be explained below. If you're new to Gatsby we recommend checking out the [main tutorial](/docs/tutorial/) first. The instructions also assume that you already have an existing Gatsby site running with either markdown or MDX. |
| 6 | + |
| 7 | +## Prerequisites |
| 8 | + |
| 9 | +- A Gatsby project set up. (Need help creating one? Follow the [Quick Start](/docs/quick-start/)) |
| 10 | +- Either markdown or MDX support added to your site. Follow the [MDX instructions](/docs/how-to/routing/mdx/) or [markdown instructions](/docs/how-to/routing/adding-markdown-pages/). |
| 11 | + |
| 12 | +## Featured images with frontmatter metadata |
| 13 | + |
| 14 | +In sites like a blog, you may want to include a featured image that appears at the top of a page. One way to do this is to grab the image filename from a frontmatter field and then transform it with `gatsby-plugin-sharp` in a GraphQL query. |
| 15 | + |
| 16 | +If you want to have a very detailed explanation of this, head to [part 7 of the Gatsby tutorial](/docs/tutorial/part-7/). The tutorial uses MDX, the instructions below will use markdown for the most part. It more or less behaves the same though. |
| 17 | + |
| 18 | +To start out, install the necessary plugins for [gatsby-plugin-image](/docs/how-to/images-and-media/using-gatsby-plugin-image/). |
| 19 | + |
| 20 | +```shell |
| 21 | +npm install gatsby-plugin-image gatsby-plugin-sharp gatsby-source-filesystem gatsby-transformer-sharp |
| 22 | +``` |
| 23 | + |
| 24 | +Then, configure the various plugins in the `gatsby-config` file. |
| 25 | + |
| 26 | +### Configuring for images and posts in the same directory |
| 27 | + |
| 28 | +If your images are in the same directory as the markdown files, sourcing and resolving the images can be done in one configuration. For example, if your markdown files and images are located together in a `src/content` directory, both content types will be automatically picked up by GraphQL as part of Gatsby's data layer. |
| 29 | + |
| 30 | +```js:title=gatsby-config.js |
| 31 | +module.exports = { |
| 32 | + plugins: [ |
| 33 | + `gatsby-plugin-sharp`, |
| 34 | + `gatsby-transformer-sharp`, |
| 35 | + `gatsby-transformer-remark`, |
| 36 | + `gatsby-plugin-image`, |
| 37 | + { |
| 38 | + resolve: `gatsby-source-filesystem`, |
| 39 | + options: { |
| 40 | + path: `${__dirname}/src/content`, // highlight-line |
| 41 | + }, |
| 42 | + }, |
| 43 | + ], |
| 44 | +} |
| 45 | +``` |
| 46 | + |
| 47 | +Then, in an example markdown file, add a field called `featuredImage`: |
| 48 | + |
| 49 | +```markdown:title=src/content/my-favorite-doggos.md |
| 50 | +--- |
| 51 | +title: My Favorite Doggos |
| 52 | +featuredImage: pupperino.png |
| 53 | +--- |
| 54 | +
|
| 55 | +Content goes here! |
| 56 | +``` |
| 57 | + |
| 58 | +The next step will be to incorporate the data into a template with a GraphQL query, which can be found later in this guide. |
| 59 | + |
| 60 | +### Configuring for images and posts in different directories |
| 61 | + |
| 62 | +There are also occasions when you may want to source images from a different directory than where your markdown posts or pages are located, such as in an external `/images` folder. You can set this up by specifying two distinct sources, one for the markdown files and the other for images: |
| 63 | + |
| 64 | +```js:title=gatsby-config.js |
| 65 | +module.exports = { |
| 66 | + plugins: [ |
| 67 | + `gatsby-plugin-sharp`, |
| 68 | + `gatsby-transformer-sharp`, |
| 69 | + `gatsby-transformer-remark`, |
| 70 | + `gatsby-plugin-image`, |
| 71 | + { |
| 72 | + resolve: `gatsby-source-filesystem`, |
| 73 | + options: { |
| 74 | + path: `${__dirname}/src/content`, // highlight-line |
| 75 | + }, |
| 76 | + }, |
| 77 | + { |
| 78 | + resolve: `gatsby-source-filesystem`, |
| 79 | + options: { |
| 80 | + path: `${__dirname}/src/images`, // highlight-line |
| 81 | + }, |
| 82 | + }, |
| 83 | + ], |
| 84 | +} |
| 85 | +``` |
| 86 | + |
| 87 | +Then, in a markdown file, the path to a `featuredImage` would be relative to the page file (in this case, in an `/images` directory up a level): |
| 88 | + |
| 89 | +```markdown:title=src/content/about.md |
| 90 | +--- |
| 91 | +title: About |
| 92 | +featuredImage: ../images/team-cat.png |
| 93 | +--- |
| 94 | +
|
| 95 | +Content goes here! |
| 96 | +``` |
| 97 | + |
| 98 | +### Querying for images from frontmatter |
| 99 | + |
| 100 | +Now that you've sourced markdown and image data, you can query for featured images in GraphQL. If a filepath points to an actual image, it will be transformed into a `File` node in GraphQL and then you can get the image data out of it by using the `childImageSharp` field. |
| 101 | + |
| 102 | +This can be added to the GraphQL query in a markdown template file. In this example, a [Dynamic image](/docs/how-to/images-and-media/using-gatsby-plugin-image/#dynamic-images) is used to make a responsive image. The query below might be different to what you have in your blog post template, however the highlighted section will be relevant nevertheless: |
| 103 | + |
| 104 | +```jsx:title=src/templates/blog-post.jsx |
| 105 | +export const query = graphql` |
| 106 | + query PostQuery($id: String) { |
| 107 | + markdownRemark(id: { eq: $id }) { |
| 108 | + html |
| 109 | + frontmatter { |
| 110 | + title |
| 111 | + // highlight-start |
| 112 | + featuredImage { |
| 113 | + childImageSharp { |
| 114 | + gatsbyImageData(width: 800) |
| 115 | + } |
| 116 | + } |
| 117 | + // highlight-end |
| 118 | + } |
| 119 | + } |
| 120 | + } |
| 121 | +` |
| 122 | +``` |
| 123 | + |
| 124 | +In the blog post template, import the `gatsby-plugin-image` package and pass the results of the GraphQL query into an `<GatsbyImage />` component. |
| 125 | + |
| 126 | +```jsx:title=src/templates/blog-post.jsx |
| 127 | +import * as React from "react" |
| 128 | +import { graphql } from "gatsby" |
| 129 | +// highlight-start |
| 130 | +import { GatsbyImage, getImage } from "gatsby-plugin-image" |
| 131 | +// highlight-end |
| 132 | + |
| 133 | +export default function BlogPost({ data }) { |
| 134 | + let post = data.markdownRemark |
| 135 | + |
| 136 | + // highlight-start |
| 137 | + let featuredImg = getImage(post.frontmatter.featuredImage?.childImageSharp?.gatsbyImageData) |
| 138 | + // highlight-end |
| 139 | + |
| 140 | + return ( |
| 141 | + <main> |
| 142 | + <h1>{post.frontmatter.title}</h1> |
| 143 | + // highlight-start |
| 144 | + <GatsbyImage image={featuredImg} /> |
| 145 | + // highlight-end |
| 146 | + <div dangerouslySetInnerHTML={{ __html: post.html }} /> |
| 147 | + </main> |
| 148 | + ) |
| 149 | +} |
| 150 | + |
| 151 | +export const query = graphql` |
| 152 | + query PostQuery($id: String) { |
| 153 | + markdownRemark(id: { eq: $id }) { |
| 154 | + html |
| 155 | + frontmatter { |
| 156 | + title |
| 157 | + featuredImage { |
| 158 | + childImageSharp { |
| 159 | + gatsbyImageData(width: 800) |
| 160 | + } |
| 161 | + } |
| 162 | + } |
| 163 | + } |
| 164 | + } |
| 165 | +` |
| 166 | +``` |
| 167 | +
|
| 168 | +The code example above is just an example, adjust the `<GatsbyImage />` portion to how you'd want to use it in your template. |
| 169 | +
|
| 170 | +## Inline images with `gatsby-remark-images` |
| 171 | +
|
| 172 | +You may also include images in the markdown/MDX body itself. The plugin [gatsby-remark-images](/plugins/gatsby-remark-images) comes in handy for this. |
| 173 | +
|
| 174 | +Start out by installing `gatsby-remark-images`: |
| 175 | +
|
| 176 | +```shell |
| 177 | +npm install gatsby-remark-images |
| 178 | +``` |
| 179 | +
|
| 180 | +Configure the plugins in your `gatsby-config` file. As with the previous example, either markdown or MDX can be used. |
| 181 | +
|
| 182 | +### Using `gatsby-transformer-remark` |
| 183 | +
|
| 184 | +Put the `gatsby-remark-images` plugin within the `plugins` option field of `gatsby-transformer-remark`. |
| 185 | +
|
| 186 | +```js:title=gatsby-config.js |
| 187 | +module.exports = { |
| 188 | + plugins: [ |
| 189 | + // Rest of the plugins... |
| 190 | + { |
| 191 | + resolve: `gatsby-transformer-remark`, |
| 192 | + options: { |
| 193 | + plugins: [ |
| 194 | + { |
| 195 | + resolve: `gatsby-remark-images`, |
| 196 | + options: { |
| 197 | + maxWidth: 800, |
| 198 | + }, |
| 199 | + }, |
| 200 | + ], |
| 201 | + }, |
| 202 | + }, |
| 203 | + ], |
| 204 | +} |
| 205 | +``` |
| 206 | +
|
| 207 | +### Using `gatsby-plugin-mdx` |
| 208 | +
|
| 209 | +`gatsby-remark-images` needs to be a sub-plugin of `gatsby-plugin-mdx`, included in the `gatsbyRemarkPlugins` array. |
| 210 | +
|
| 211 | +```js:title=gatsby-config.js |
| 212 | +module.exports = { |
| 213 | + plugins: [ |
| 214 | + // Rest of your plugins... |
| 215 | + { |
| 216 | + resolve: `gatsby-plugin-mdx`, |
| 217 | + options: { |
| 218 | + gatsbyRemarkPlugins: [ |
| 219 | + { |
| 220 | + resolve: `gatsby-remark-images`, |
| 221 | + options: { |
| 222 | + maxWidth: 1200, |
| 223 | + }, |
| 224 | + }, |
| 225 | + ], |
| 226 | + }, |
| 227 | + }, |
| 228 | + ], |
| 229 | +} |
| 230 | +``` |
| 231 | +
|
| 232 | +With the configurations above, you can use the default markdown syntax for images. They will be processed by sharp and appear as if you placed them in a `gatsby-plugin-image` component. |
| 233 | +
|
| 234 | +```markdown |
| 235 | + |
| 236 | +``` |
| 237 | +
|
| 238 | +## Additional Resources |
| 239 | +
|
| 240 | +- [Using gatsby-plugin-image](/docs/how-to/images-and-media/using-gatsby-plugin-image/) |
| 241 | +- [Adding MDX pages](/docs/how-to/routing/mdx/) |
| 242 | +- [Adding markdown pages](/docs/how-to/routing/adding-markdown-pages/) |
0 commit comments