Note: This post is part of Learning Decoupling Gatsby WordPress series. This learning post is still in active development and updated regularly.
In the previous Part 1 of Learning Decoupling Gatsby WordPress series, installation of WordPress and Gatsby Source WordPress starter sites, required dependent plugins WPGraphQL, WP Gatsby installation and exposing WordPress data endpoint to Gatsby site by updating gatsby-config.js
were discussed.
The objective of this part 2 of the three-parts series is to expand the Gatsby site by update its global components, namely Layout, refactoring Header and adding Footer components. We will also install and configure Gatsby plugin Sass and add basic global layout with CSS Module.
Part 1: Site Set Up and Installation
Part 2: Working with Global Layout and Site Header and Basic Styling (this post)
Part 3: Working with Posts and Pages
Part 2: Extending the Starter With Sass Plugin
As the name suggests, the starter is a skeleton only project with limitations and known issues. Nevertheless, it has the basic elements of a WordPress powered gatsby site and designed to be modified and extended functionality as desired.
As outlined in the objectives, in this guide our focus will be to extending its styling options with Sass and CSS module and refactoring its global components like Header, Layout and add a missing Footer component.
Working with Global Components
For the site styling, the starter uses chakra UI and very basic styling. In this section, we will extend its styling of pages, posts, images styling using Gatsby plugin Sass and CSS module. First, lets install the Sass plugin and add to the configuration.js
file.
Step 1: Install Sass Plugin
Just like styling gatsby sites with external style.css
, the gatsby-plugin-sass
provide support of SASS/SCSS style sheets too.
#! install node-sass & gatsby-sass
yarn add node-sass gatsby-plugin-sass
#! or with npm
npm install --save node-sass gatsby-plugin-sass
Take a note that while installing the gatsby-plugin-sass
, its required dependencies node-sass
should also be installed.
Step 2: Add the plugin & configure gatsby-config.js
file
Lets add the gatsby-plugin-sass
plugin in the gatsby-config.js
file as shown below.
// include in gatsby-config.js
module.exports = {
siteMetadata: {
// ..
},
// ..
},
{
plugins [
{
// ...
},
// options can be included
`gatsby-plugin-sass`
// include options
],
}
Step 3: Create styles in .scss
files and use by import or require methods
// using import to component
import("./src/styles/global.scss")
//require in gatsby-browser.js file
require('./src/styles/global.scss')
In the example above, the global.scss
is imported to a component file or it can also be added in gatsby-browser.js
with require statement.
Step 4: Sass Structure
The SCSS files can be structured in several different ways. In this project, we elected to use under a /src/styles
sub-directory as shown below:
#! style directory (partial)
├── src
│ └── styles
│ └── base
│ └── resets.css
│ └── variables.css
│ └── scss
│ └── elements.css
│ └── footer.module.css
│ └── header.module.css
│ └── mainNav.module.css
│ └── site.module.css
│ └── ...
│ └── main.scss
Because this project is not being about Sass setting up variables and using Sass syntax are not discussed in this post. They could be found in this Sass guide.
Additional Information: SASS Basics | Learn Sass
Step 5: Adding Common Styles to Layout Component with CSS Module
To add a css module into a component, lets create a file named src/styles/scss/site.module.scss
and paste the following CSS rules:
/* src/styles/scss/site.module.css */
.site_main {
background-color: whiteSmoke;
}
.site_content {
padding: 3rem 1rem 1rem;
img {
display: block;
width: 100vw;
}
}
@media screen and (min-width: 600px) {
.site_content {
padding: 1em;
width: 780px;
margin: 0 auto;
font-size: 1.125rem;
img {
display: block;
width: inherit;
}
}
}
I will also make use a simple <Layout />
component that was created previously and being used in most of my other projects. To style components with CSS module, style a component using CSS Modules described in Gatsby Doc was followed.
// src/components/layout.js
import React from "react"
import Header from "./header"
import Footer from "./footer"
import styles from "../styles/scss/site.module.css"
import "../styles/main.css"
const Layout = ({ children }) => (
<section>
<Header />
<div className={styles.site_main}>
<div className={styles.site_content}>
{children}
</div>
</div>
<Footer />
</section>
)
export default Layout
In the layout.js
components, the chakra-UI styling elements were removed and replaced with common HTML
markup as shown above. The site.module.css
rules were imported to the <Layout />
component by giving variable name styles
(line 5) and the variable name is referenced to style site_main
and site_content
elements (lines: 11-12).
Refactoring Header Component
The default header.js
component is very basic with Gatsby logo (line 12) and a title (line 12). In the starter, the menu.js
component is not part of the header.js
component but layout.js
component.
// header.js from the starter
import React from "react"
import { Heading, Box, Grid } from "@chakra-ui/core"
import { Link } from "gatsby"
import GatsbyLogo from "../assets/svg/gatsby.inline.svg"
export default () => (
<Heading as="h1">
<Link to="/">
<Grid gridTemplateColumns="50px 1fr" gridGap="20px">
<Box maxW={50}>
<GatsbyLogo />
</Box>
<span
style={{
transform: `translateY(5px)`,
display: `inline-block`,
}}
>
Gatsby Source WordPress V4 demo
</span>
</Grid>
</Link>
</Heading>
)
In this guide project, we will refactor the header.js
component to include site title and description from the WordPress endpoint settings and also include menu.js
(the top navigation) component in header component.
// refactored header component
import React from "react"
import { graphql, Link, useStaticQuery } from "gatsby"
import Menu from "./menu"
import style from "../styles/scss/header.module.css"
import logo from '../images/gatsby-icon.png'
const Header = ( ) => {
const { wp } = useStaticQuery(graphql`
{
wp {
generalSettings {
title
description
}
}
}
`)
return (
<header className={style.header_wrapper}>
<div className={style.brand}>
<Link to="/">
<img src={logo} alt="logo" width="100" height="100" display="inline-block"
marginBottom= "0" className={style.site_logo} />
</Link>
<div className={style.site_header} >
<div className={style.site_title}>
<Link
to="/"
dangerouslySetInnerHTML={{ __html: wp.generalSettings.title }} />
</div>
<div className={style.site_description}
dangerouslySetInnerHTML={{
__html: wp.generalSettings.description }} />
</div>
</div>
<Menu />
</header>
)
}
export default Header
For styling Header.js
components, I borrowed the following CSS rules described by Morten Rand-Henriksen in his recent LinkedIn Learning Gatsby course applied using CSS module, as described in the previous section.
/* src/styles/scss/header.module.css */
.header_wrapper {
padding: 1rem;
font-size: 84%;
font-family: var(--highlight-font);
text-align: center;
background-color: white;
}
.site_logo {
margin: 1rem auto;
max-width: 6rem;
}
.brand {
color: var(--rich-black);
}
.brand a {
color: inherit;
text-decoration: none;
}
.site_description {
margin-bottom: 0;
font-size: 80%;
font-weight: normal;
font-style: italic;
}
.site_header {
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
}
.site_title {
font-size: 120%;
font-weight: bold;
}
@media screen and (min-width: 40rem) {
.header_wrapper {
display: flex;
padding: 1rem 2rem;
text-align: left;
}
.brand a {
display: grid;
gap: 0 1rem;
align-items: center;
text-align: none;
}
.site_header {
display: flex;
flex-direction: column;
justify-content: center;
align-items: flex-start;
}
.site_logo {
grid-row: span 2;
margin: inherit;
margin-right: 15px;
}
.brand,
.navigation {
display: flex;
flex: 1 1 50%;
}
.navigation {
align-self: center;
}
}
Refactoring Menu.js Component
The menu.js
component used in the header.js
component requires some refactoring too, mostly for styling purposes. Lets refactor the menu.js
by replacing chakra-ui rules with HTML markup and CSS modules, as shown below.
// src/components/menu.js
import React from "react"
import { Link, useStaticQuery, graphql } from "gatsby"
import style from "../styles/scss/mainNav.module.css"
import { normalizePath } from "../utils/get-url-path"
const Menu = () => {
const { wpMenu } = useStaticQuery(graphql`
{
wpMenu(slug: { eq: "main-menu" }) {
name
menuItems {
nodes {
label
url
parentId
connectedNode {
node {
... on WpContentNode {
uri
}
}
}
}
}
}
}
`)
if (!!wpMenu && !!wpMenu.menuItems && !!wpMenu.menuItems.nodes === 0) return null
return (
<nav className={style.navigation} >
<ul>
{wpMenu.menuItems.nodes.map((menuItem, i) => {
if (menuItem.parentId) {
return null
}
const path = menuItem?.connectedNode?.node?.uri ?? menuItem.url
return (
<li>
<Link key={i + menuItem.url}
to={normalizePath(path)}
>
{menuItem.label}
</Link>
</li>
)
})}
</ul>
</nav>
)
}
export default Menu
Now lets add CSS rules for the navigation from Morten’s Learn Gatsby tutorial.
/* src/styles/scss/mainNav.module.css */
.navigation ul {
display: flex;
justify-content: center;
flex-wrap: wrap;
margin: 1rem;
padding: 0;
}
.navigation li {
margin: 0 0.5rem;
list-style-type: none;
font-size: 1.1rem;
}
.navigation a {
display: block;
line-height: 2;
text-decoration: none;
color: #414141;
font-size: 1rem;
}
.navigation li a:focus,
.navigation li a:hover {
border-bottom: 2px solid #414141;
}
@media screen and (max-width: 40rem) {
.navigation::before,
.navigation::after {
display: block;
width: 1rem;
margin: 1rem auto;
content: "";
border-bottom: 1px solid currentColor;
}
}
@media screen and (min-width: 40rem) {
.navigation {
display: flex;
align-items: center;
justify-content: flex-end;
font-size: 1rem;
}
.navigation ul {
margin: 0;
justify-content: flex-end;
}
.navigation li {
margin-right: 0;
margin-left: 2rem;
font-size: 1.25rem;
}
}
Let’s view the fully styled, responsive header with navigation in a browser.
View in a Browser
After starting over the development server, view the newly created header & navigation menu at http://localhost:8000
, the following header with top navigation with header logo, site title, site description should be displayed (as shown below).

Adding Footer Component
Let’s add a simple footer.js
component inside /src/components/
folder as shown below:
// src/components/footer.js
import React from "react"
import style from "../styles/scss/footer.module.css"
export default () => (
<footer className={style.footer}>
<p> © {new Date().getFullYear()} | This site is Powered by {' ' }
<a href="https://www.gatsbyjs.org"> GatsbyJS</a> {' and '}
<a href="https://www.wordpress.org">WordPress</a>
</p>
</footer>
)
Please a note that for styling, a simple css module styling rule is imported (line 3) and applied (line 6) as described in the previous section. When viewed in a browser, the following footer should be displayed.

Wrapping Up
In this Part 2 tutorial, the starter plugin was extended by refactoring its header, adding footer and applying global styling rules using Gatsby plugin Sass. In the next part, we will refactor and style posts and pages of the starter.
Credits: This post was inspired by the Morten Rand-Henriksen’s recent LinkedIn course Learning Gatsby and styling code snippets are used from its exercise file.
NEXT: Working with Posts and Pages
Useful Resources
While preparing this post, I have referred the following references extensively. Please refer to original posts for more detailed information.
- Installation & Getting Started Guide | GitHub
- Creating a new site from scratch | GitHub