Because the post Gatsby descrete notes is too long, I write a separate post just for images in Gatsby.
- Static images (icon, logo, favicon): just
import
and useimg
.
svg
cannot be used withchildImageSharp
, just use<img>
with itspublicURL
.
png
,jpg
can be used with<Img>
andchildImageSharp
.
- Data can be used:
json
oryaml
, cannot usejs
for images.
- List of images are get up to
edges
. Afteredges
, there are a loop ofnode
s.
query
components must placed in<StaticQuery />
.
- Different screen solution: use
fixed
.
- Different screen size: use
fluid
.
- Use http://localhost:8000/___graphql to check the
query
.
- Use
{condition && condition && output}
instead of usingif..else...
- The relative path of images is compared with the path of data file where the urls are indicated.
Read this post from CSS-Tricks to know which images should be processed, which ones should not.
- No processing required: "static images", icons and logos, favicons 👉 We can
import
and use<img>
to directly import them.
- Process required: PNG, JPG files, gallery, ...
Install stuffs following this doc
1npm install --save gatsby-image gatsby-plugin-sharp gatsby-transformer-sharp
1import avatar from "src/images/site/avatar.jpg"
2function Header() {
3 return <img src={logo} alt="Logo" />
4}
5export default Header
So that we can have the lazing loading / resizing / blur-up (traced placeholder) effects.
1npm install --save gatsby-image gatsby-transformer-sharp gatsby-plugin-sharp
Below technique is just for single photos.
1// gatsby-config.js
2module.exports = {
3 plugins: [
4 ...
5 'gatsby-plugin-sharp',
6 'gatsby-transformer-sharp',
7 {
8 resolve: 'gatsby-source-filesystem',
9 options: {
10 name: 'images',
11 path: path.join(__dirname, `src`, `images`),
12 },
13 },
14 ],
15}
1// src/components/Header.js
2import { StaticQuery, graphql } from 'gatsby';
3import Img from 'gatsby-image';
4
5const Header = ({ data }) => (
6 <header>
7 <Img fluid={data.myAvatar.childImageSharp.fluid} />
8 </header>
9)
10
11// src/images/avatar.png
12export default props => (
13 <StaticQuery
14 query={graphql`
15 query {
16 myAvatar: file(relativePath: { eq: "avatar.png" }) {
17 childImageSharp {
18 fluid(maxWidth: 150) {
19 ...GatsbyImageSharpFluid
20 }
21 }
22 }
23 }
24 `}
25 render={data => <Header data={data} {...props} />}
26 />
27)
👉 Most of tutorials like this or this don't talk about
StaticQuery
(Gatsby v2). I followed them but it didn't work, we have to use StaticQuery
to make things work! 👉 The reason is that the (old) page query can only be added to page components (in my try, I add in Header.js
component). StaticQuery
can be used as a replacement of page query, it can be added to any component. (ref)👉 There are 2 types:
fixed
: has a set width and height and is for supporting different screen resolutions. It acceptswidth
andheight
.
fluid
: has a max-width and sometimes a max-height, and will create multiple images for supporting different screen sizes. It acceptsmaxWidth
andmaxHeight
.
You need to use them with fragments like
GatsbyImageSharpFixed_tracedSVG
or GatsbyImageSharpFluid
(more).If you want to query to an image in
/src/images/example.png
, you can use,1export const query = graphql`
2 query {
3 file(absolutePath: {
4 regex: "/\\\\/src\\\\/images\\\\/example\\\\.png/"
5 }) {
6 childImageSharp {
7 fixed(width: 800) {
8 ...GatsbyImageSharpFixed
9 }
10 }
11 }
12 }
13`
gatsby-plugin-sharp
/ gatsby-image
doesn't handle SVGs or GIFs. If you want to use your svg you, e.g. could import / use it like import yourSVG from './logo_large.svg'
. (ref)Put
favicon.png
in src/images
and then change gatsby-config.js
1{
2 resolve: `gatsby-plugin-manifest`,
3 options: {
4 // other stuffs
5 icon: `src/images/favicon.png`,
6 },
7},
You need to restart
gastby
to see the result!Suppose that we store some images in
/src/images/
and we indicate them in a json file like this,1// File /data/AccountItem.json
2[
3 {
4 "name": "Github",
5 "icon": "./github.svg",
6 },
7 {
8 "name": "LinkedIn",
9 "icon": "./linkedin.svg",
10 },
11 {
12 "name": "Math2IT",
13 "icon": "./math2it.png",
14 }
15]
Images (
github.svg
, linkedin.svg
, math2it.png
) are stored in the same folder of your json file, that why we put ./
before them!❓ There are both
png
and svg
files in the list. We cannot use childImageSharp
for svg files. How can we "loop" through each item and consider differently svg and png files?💡 Read this tutorial to read data from a json file.
- Having a json file, in this example, it's
/data/AccountItem.json
(you can name it whatwever you want but its name is really important for using later!!!)
- Install
1npm install gatsby-transformer-json gatsby-source-filesystem --save
- Inside
/gatsby-config.js
, add following (direction inpath
is the direction to the folder containing your json file),
1`gatsby-transformer-json`,
2{
3 resolve: 'gatsby-source-filesystem',
4 options: {
5 name: 'data',
6 path: `${__dirname}/data/`,
7 },
8}
- Suppose that we wanna load images in a component
/src/components/ListAccount.js
. Put in it, (ref)
1import { StaticQuery, graphql } from 'gatsby';
2import Img from 'gatsby-image'
3
4const ListAccount = ( {accounts} ) => (
5 <div>
6 {accounts.map(account => (
7 <div className="item">
8 <div className="img">
9 {!account.node.icon.childImageSharp
10 && (account.node.icon.extension === 'svg')
11 && <img src={account.node.icon.publicURL} />
12 }
13 {account.node.icon.extension !== 'svg'
14 && <Img fixed={account.node.icon.childImageSharp.fixed} />
15 }
16 </div>
17 </div>
18 ))}
19 </div>
20)
21//
22export default props => (
23 <StaticQuery
24 query={graphql`
25 query AccountItemsQuery {
26 allAccountItemsJson{
27 edges{
28 node{
29 name
30 icon{
31 childImageSharp {
32 fixed(width: 150, height: 150) {
33 ...GatsbyImageSharpFixed_tracedSVG
34 }
35 }
36 extension
37 publicURL
38 }
39 }
40 }
41 }
42 }
43 `}
44 render={data => <ListAccount accounts={data.allAccountItemsJson.edges} {...props} />}
45 />
46)
Explaination:
- We have to put
extension
andpublicURL
insideicon
because there aresvg
files!
- For more intuition, look at http://localhost:8000/___graphql.
- In
edges
, there are manynode
s, each of them is relating to the item insideAccountItem.json
. That's why the input data for<ListAccount />
must bedata.allAccountItemsJson.edges
.
- For each
account
inaccounts
, we have to passaccount.node
before each attributename
,icon
.
{condition && condition && output}
is a trick for not usingif...else
.
👉 In the case you store images in a different folder, let's say
/src/images/accounts/
, you have to indicate it in /data/AccountItems.json
:1[
2 {
3 "icon": "../src/images/accounts/github.svg",
4 }
5]
Suppose our
yaml
file,1// File /data/AccountItem.yaml
2
3- name: Github
4 icon: ./github.svg
5- name: LinkedIn
6 icon: ./linkedin.svg
7- name: Math2IT
8 icon: ./math2it.png
The same technique as in the case of
json
file. In this case, we need to install gatsby-transformer-yaml
1npm install --save gatsby-transformer-yaml
In your
gatsby-config.js
1`gatsby-transformer-yaml`,
2{
3 resolve: `gatsby-source-filesystem`,
4 options: {
5 name: 'data',
6 path: `${__dirname}/data/`,
7 },
8},
In the previous step,
query
is considered inside the component file. What if you wanna query data and then pass it in a JSX components? (check index.js
for an example)There is a data file
/data/MostProudOfItems.yaml
.1// in /src/pages/index.js
2
3import ShortcutListing from "../components/ShortcutListing"
4
5const indexPage = (props) => (
6 <ShortcutListing
7 shortcuts={props.data.allMostProudOfItemsYaml.edges}
8 nShortcutsPerRow='3' />
9)
10
11export default IndexPage
12
13export const pageQuery = graphql`
14 query IndexQuery {
15 allMostProudOfItemsYaml{
16 edges {
17 node {
18 title
19 img {
20 childImageSharp {
21 fixed(width: 100, height: 100) {
22 ...GatsbyImageSharpFixed_tracedSVG
23 }
24 }
25 extension
26 publicURL
27 }
28 url
29 }
30 }
31 },
32 anotherYaml{
33 ....
34 }
35 }
36`
1// in /src/components/ShortcutListing
2
3const ListShortcut = ({shortcuts, nShortcutsPerRow}) => (
4 // ...
5)
6
7export default ListShortcut
👉 This is also a way you use the
name
indicate in gatsby-config.js
.Suppose that you wanna show all images in
/sketches/
. (ref)1// In /gatsby-config.js
2{
3 resolve: "gatsby-source-filesystem",
4 options: {
5 path: `${__dirname}/sketches/`,
6 name: "sketchFolder",
7 },
8},
1export const pageQuery = graphql`
2 query IndexQuery {
3 allFile(filter: {
4 extension: {regex: "/(jpg)|(jpeg)|(png)/"},
5 sourceInstanceName: {eq: "sketchFolder"}})
6 {
7 edges {
8 node {
9 childImageSharp {
10 fluid {
11 originalName
12 }
13 }
14 absolutePath
15 }
16 }
17 }
18 }
19`
💢 Above method is only works with
/sketches
(folder locates at the root of site). It doesn't work with /src/images/sketches
, for example. I don't know why!👉 If you want to get all images from a folder (without using
sourceInstanceName
) you can use relativeDirectory
in the query
. Suppose that we have 2 folders with the same name sketches
, one is in /content/sketches
, one is in /src/images/sketches
. The following code will load all images in these two folders!1// In /gatsby-config.js
2{
3 resolve: "gatsby-source-filesystem",
4 options: {
5 path: `${__dirname}/content/`,
6 name: "content",
7 },
8},
9{
10 resolve: "gatsby-source-filesystem",
11 options: {
12 path: `${__dirname}/src/images`,
13 name: "images",
14 },
15},
1export const pageQuery = graphql`
2 query IndexQuery {
3 allFile(filter: {
4 extension: {regex: "/(jpg)|(jpeg)|(png)/"},
5 relativeDirectory: {eq: "sketches"}})
6 {
7 edges {
8 node {
9 childImageSharp {
10 fluid {
11 originalName
12 }
13 }
14 absolutePath
15 }
16 }
17 }
18 }
19`
20
💢 Make sure the name of your folder is unique if you don't want to load images from a wrong location.
- A comprehensive guide to images in Gatsby by James Allardice.