Skip to content

How to Add Dynamic Page Specific Body Class in Gatsby

Published: Updated:

Use case: you have a class option in your CMS that should be the class on your Gatsby site's <body> element. You want it to be added on build time instead of using useEffect on client side. This is how you add it!

Add the custom class on your gatsby-node.js file as a page context in your createPage function:

1query.data.pages.edges.forEach((loop) => {
2 createPage({
3 component: Page,
4 path: loop.node.slug,
5 context: {
6 slug: loop.node.slug,
7 custom_prop: 'hello-world'
8 },
9 })
10})

Notice the "custom_prop" on the context in the above code block. You probably want to use the actual CMS prop there instead of a static string (so something like loop.node.bodyClass in this context).

Now let's use this custom prop on gatsby-ssr.js file. If the file does not exist on your project, add it to your root folder (below the gatsby-node.js file).

1exports.onRenderBody = ({ pathname, setBodyAttributes , loadPageDataSync }) => {
2 if (process.env.NODE_ENV !== 'development') {
3 const { result: { pageContext: { custom_prop } }, } = loadPageDataSync(pathname);
4 setBodyAttributes({ className: custom_prop });
5 }
6}

Note: this will only run on production build (gatsby build), not development environment (gatsby develop).

If you are not familiar with gatsby-ssr file, don't worry, you don't need to add any other code inside it, that's the whole file you need.

Now your body class is being added on build time, which means that it should bring zero javascript to client side! The class exists in the initial HTML that your visitors will receive.

If you need the class on your development environment, you could try temporarily adding it via useEffect in addition. Here's how you can do that inside your page template:

1import React, { useEffect } from "react"
2
3const PageTemplate = ({ pageContext }) => {
4
5 useEffect(() => {
6 document.body.classList.add(pageContext.custom_prop);
7 }, []);
8
9 ...

This code uses the pageContext prop to add a body class via useEffect on client side. It runs once on every page load.

All of this should work in the latest Gatsby v5 version.