Gatsby background image example

Last update: October 10, 2019

One of the many selling points of Gatsby is the ability to handle images. It does this with the sharp image processing library and with the gatsby-image component. I’ve talked in the past about image processing in Gatsby if you want to know more.

Today you’ll see how to use the gatsby-image component as a background-image. You’ll use the object-fit property and code from this GitHub issue.

Project setup

Create a new project with the gatsby-cli and the default starter. After the installation completes, open the folder, and start the development server:

gatsby new gatsby-background-image
cd gatsby-background-image
gatsby develop

Next, install styled-components to make the component styling a bit easier. You’ll have to install the following 3 packages:

yarn add gatsby-plugin-styled-components styled-components babel-plugin-styled-components

Don’t forget to open your gatsby-config.js, and add the highlighted line:

// gatsby-config.js

module.exports = {
  siteMetadata: {
    // site metadata
  },
  plugins: [
    // other plugins...
    `gatsby-plugin-styled-components`  ]
};

Component definition

After that, create a new file called BgImage.jsx inside the src/components folder. I’ll explain what happens here after the code:

If you prefer emotion over styled-components, here’s an example with emotion and theme-ui and here’s how to set up the project for theme-ui.

// src/components/BgImage.jsx

import React from "react";
import PropTypes from "prop-types";
import Img from "gatsby-image";
import styled from "styled-components";

const Parent = styled.div`
  position: relative;
  background-color: ${({ bc }) => bc};
`;

const FakeBgImage = styled(Img)`
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: ${({ height }) => height};
  z-index: -1;

  & > img {
    object-fit: cover !important;
    object-position: 0% 0% !important;
    font-family: "object-fit: cover !important; object-position: 0% 0% !important;";
  }

  @media screen and (max-width: 600px) {
    height: ${({ mobileHeight }) => mobileHeight};
  }
`;

const Content = styled.div`
  position: absolute;
  top: 0;
  height: 100%;
  width: 100%;
`;

const BgImage = ({
  fluid,
  title,
  height,
  mobileHeight,
  overlayColor,
  children,
  className
}) => (
  <Parent bc={overlayColor}>
    <FakeBgImage
      fluid={fluid}
      title={title}
      height={height}
      mobileHeight={mobileHeight}
    />
    <Content className={className}>{children}</Content>
  </Parent>
);
BgImage.propTypes = {
  fluid: PropTypes.object.isRequired,
  title: PropTypes.string.isRequired,
  height: PropTypes.string,
  mobileHeight: PropTypes.string,
  overlayColor: PropTypes.string,
  children: PropTypes.node,
  className: PropTypes.string
};
BgImage.defaultProps = {
  height: null,
  mobileHeight: null,
  overlayColor: "transparent",
  children: null,
  className: null
};

export default BgImage;

First of all, there is some prop validation going on at the end of the file with prop-types. There are some default props as well.

We have a Parent component—that’s used as a container—with position: relative;. Parent has 2 children: the FakeBgImage and the Content. Both of those components have position: absolute;.

FakeBgImage is a regular gatsby-image component—that’s why it takes fluid and title as props. fluid and title props are the only props required by the BgImage component. It’s styled with the object-fit CSS property, and it has a height property (desktop) and a mobileHeight property.

* Tip: You must be careful when you set the height because the content may overflow the container. Always check how your background image looks in mobile and adjust the mobileHeight.

If you want to position the image differently, check the object-fit documentation.

The Content component is positioned absolute and takes the whole space of the parent div. Additionally, the children of the parent BgImage component are rendered inside the Content component. Another thing to note is that we pass to the Content the className prop. That means that if you extend the BgImage with styled(BgImage), the styles will be applied to the Content component.

Now let’s see how you can use that component:

Usage

Open the file for the home page which is located at src/pages/index.js. You’ll use the gatsby-astronaut.png that lives in the src/images folder. Of course, you can try it with any image you like.

The first thing you want to do is to write a GraphQL query to get the image. Then, import BgImage, and use it as shown below:

// src/pages/index.js
import React from "react";
import { Link, graphql } from "gatsby";
import Layout from "../components/layout";
import Image from "../components/image";
import SEO from "../components/seo";
import BgImage from "../components/BgImage";
const IndexPage = ({ data }) => (  <Layout>
    <SEO title="Home" keywords={[`gatsby`, `application`, `react`]} />
    <h1>Hi people</h1>
    <p>Welcome to your new Gatsby site.</p>
    <p>Now go build something great.</p>
    <div style={{ maxWidth: `300px`, marginBottom: `1.45rem` }}>
      <Image />
    </div>
    <BgImage      title="astronaut"      fluid={data.astronaut.childImageSharp.fluid}      overlayColor="#04040454"    >      <h2 style={{ color: "white" }}>Look at me!</h2>    </BgImage>    <Link to="/page-2/">Go to page 2</Link>
  </Layout>
);

export const query = graphql`  query {    astronaut: file(relativePath: { eq: "gatsby-astronaut.png" }) {      childImageSharp {        fluid(maxWidth: 300) {          ...GatsbyImageSharpFluid        }      }    }  }`;
export default IndexPage;

That’s it! Note that I’m using a transparent black color as an overlay to make the text inside the image more readable. You can add whatever color you like to create an effect, but remember to pass a transparent color.

You can check more examples in a Gatsby starter I set up.

This example was a quick way to take advantage of the benefits gatsby-image offers, and use it as a background image in a Gatsby application.

Other things to read

Popular notes

Other posts