In the previous section, we've learned some of the Gatsby fundamentals and started developing our Gatsby site.
Now, we have a decent amount of content spread across pages on our site. So, we need to work on the look and feel by adding styles.
In this section, you will learn how to easily style your Gatsby site using CSS.
Along the way, you will also learn how to set up a Gatsby plugin to enable SASS. You will be able to take advantage of all its great features and further customize your site.
Note: If you are not comfortable with SASS, feel free to use the regular CSS styles.
So let’s get started.
Go inside the src
directory and create a new folder called styles
. In this folder, create a file called style.css
and add the following base styles:
* {
box-sizing: border-box;
}
body {
color: #464646;
font-size: 100%;
margin: 0;
line-height: 1.4283;
font-family: 'Segoe UI', Roboto, Verdana, 'Helvetica Neue',
sans-serif;
}
h1,
h2,
h3 {
font-weight: 400;
}
a {
color: #f44f18;
text-decoration: none;
}
After that, import the CSS file in the Layout
component like so:
import '../styles/style.css';
The reason for the
Layout
component is that it is used in every pages’ files.
Save your files and see your styles applied in the frontend. That is a great starting point.
You now have a stylesheet loaded in your Gatsby site. You can write all your styles right inside of this single file. But in this tutorial, we are not going to do that.
As I mentioned, we will be using sass to speed up our site customization. This is also a great moment to learn how to integrate sass in a Gatsby project and install your very first Gatsby plugin.
So let’s do that.
Installing and Configuring gatsby-plugin-sass
As you may have known, website plugins add functionalities to the website. And Gatsby provides a whole lot of plugins built by its team as well as the third-party plugins developed by the members of its community.
You can search for these plugins by visiting the Gatsby site and navigating to the Plugins page.
Now, the sass plugin we will install is called gatsby-plugin-sass
. So let’s stop the development server with CTRL + C
or CMD + C
depending on your operating system and then run:
C:\Users\Your Name\ ibaslogic-gatsby-tutorial > npm install gatsby-plugin-sass node-sass
node-sass
allows us to compile .scss
files to regular css
. While gatsby-plugin-sass
allows us to do that in a Gatsby project.
Once the installation is done, you need to configure your Gatsby site to use the Gatsby plugin. So, open the gatsby-config.js
file in the root directory and add this:
module.exports = {
plugins: ['gatsby-plugin-sass'],
};
Save the file and start your development server by running gatsby develop
.
Next, rename the style.css
file to style.scss
and update the import
in the layout.js
file to reflect the .scss
extension like so:
import '../styles/style.scss';
Save your file. You should still have your styles applied in the frontend. Now you can use sass in your project.
Let’s confirm that it’s working by adding sass variables in our scss
file. Update the file so you have:
$primaryColor: #464646;
$secondaryColor: #f44f18;
$mainWhite: #fff;
* {
box-sizing: border-box;
}
body {
color: $primaryColor;
font-size: 100%;
margin: 0;
line-height: 1.4283;
font-family: "Segoe UI", Roboto, Verdana, "Helvetica Neue", sans-serif;
}
h1,
h2,
h3 {
font-weight: 400;
}
a {
color: $secondaryColor;
text-decoration: none;
}
Save the file. Yeah, it works!
Styling Gatsby Site with CSS Modules
In order to add some sort of global styles in our Gatsby site, we added a stylesheet in a shared Layout
component.
Though this stylesheet file can hold all of your site styles, it is recommended to limit this file to your global styles and scope your component styles locally using the CSS Module.
CSS Modules are supported by default in a Gatsby project and they eliminate the risk of name conflicts with the css selector or some other issues related to the global scope styling.
For instance, if you add a CSS Module for the Header
component, the styles applied will be scoped only to that component. This way, you can use the same class names in different components without worrying about conflicts with the css selector.
That is what we want.
Starting with the Header
component. Let’s go inside the src/components
directory and create a file called header.module.scss
. Then, add the following styles:
.header {
position: relative;
height: 326px;
text-shadow: 0 1px 2px rgba(0, 0, 0, 0.4);
}
.hero-content {
position: absolute;
top: 35%;
margin: 0;
text-align: center;
width: 100%;
text-transform: uppercase;
}
.brand {
margin: 0;
padding: 0 0 10px;
font-size: 48px;
font-weight: 300;
line-height: 1.2;
letter-spacing: 5.5px;
a {
color: #fff;
}
}
.description {
margin: 0;
padding: 0 0 10px;
font-size: 12px;
font-weight: 500;
line-height: 1.5;
letter-spacing: 3.5px;
opacity: 0.7;
color: #fff;
}
.nav-container {
position: absolute;
bottom: 0;
left: 0;
right: 0;
background: rgba(255, 255, 255, 0.1);
border-top: 1px solid rgba(255, 255, 255, 0.1);
}
.nav-list {
margin: 0;
display: flex;
flex-flow: wrap;
justify-content: center;
padding: 0;
list-style: none;
li {
letter-spacing: 0.05em;
background: none;
padding: 7px 14px 10px;
}
a {
text-transform: uppercase;
color: #fff;
font-size: 12px;
opacity: 0.7;
&:hover {
text-decoration: underline;
}
}
}
Please note that you’ll append
.module.css
to your file name if you are writing in the.css
file. Also note that we are indenting css selector and the pseudo-class (:hover
) inside another selector in the.scss
file. This will not work in a.css
file.
After that, go inside the header.js
file and import the .scss
file like so:
import headerStyles from './header.module.scss';
Then, update the markup within the return
statement to include the class names:
return (
<header className={headerStyles.header}>
<div className={headerStyles.heroContent}>
<p className={headerStyles.brand}>
<Link to="/">Ibas Majid</Link>
</p>
<p className={headerStyles.description}>
I teach JavaScript, React, GraphQL and Gatsby
</p>
</div>
<nav className={headerStyles.navContainer}>
<ul className={headerStyles.navList}>...</ul>
</nav>
</header>
);
Save your files and check the frontend.
We need to add a background image to the header section. So go inside the src
directory and create a folder called images
. Inside this folder, add a background image and name it header-image.jpg
.
Feel free to use any image on your hard drive. Or check my GitHub repo and download the same header image used in this project.
Then update the .header
class selector in the header.module.scss
file so you have:
.header {
position: relative;
height: 326px;
text-shadow: 0 1px 2px rgba(0, 0, 0, 0.4);
background-position: center center;
background-repeat: no-repeat;
background-size: cover;
background-image: url("../images/header-image.jpg");
}
Before you save the file, let’s add an overlay to the background image. In the header.js
file, add this div
immediately after the <header>
opening tag:
<div className="{headerStyles.overlay}"></div>
Then update the header.module.scss
file to include the following styles:
.overlay {
content: '';
position: absolute;
top: 0;
right: 0;
bottom: 0;
left: 0;
background-color: #000;
opacity: 0.5;
}
Now save all your files. Your frontend should look like this:
So what did we do?
First, we tell Gatsby to process the SCSS file as a CSS module by appending to the file .module.scss
. This module is then imported in the header.js
file and declared as a JavaScript object called headerStyles
.
This object holds all the class selector in the .scss
file, and we referenced them in the JSX className
attribute with headerStyles.classSelector
(for instance, headerStyles.header
).
Please note,
You can name the
headerStyles
object anything you want. Also, any selector that has a hyphen ( – ) can be referenced with its camelCase version in the.js
file. For instance, the.hero-content
in the.scss
file turned toheroContent
when we referenced it in theclassName
attribute inside the.js
file.
If you inspect the header
element in your browser developer tools, you’ll see that the CSS module generates unique class names as seen in the image below. With this, you don’t have to worry about selector name conflicts.
Before we go ahead and style the other components, let’s style the active navigation menu item. This will tell the site users which page is currently being viewed.
To do this, go inside the header.js
file and update the <Link />
components to include the activeClassName
attribute.
<ul className={headerStyles.navList}>
<li>
<Link to="/" activeClassName={headerStyles.activeMenuItem}>
Home
</Link>
</li>
<li>
<Link to="/blog/" activeClassName={headerStyles.activeMenuItem}>
Blog
</Link>
</li>
<li>
<Link
to="/contact/"
activeClassName={headerStyles.activeMenuItem}
>
Contact
</Link>
</li>
<li>
<Link to="/about/" activeClassName={headerStyles.activeMenuItem}>
About
</Link>
</li>
</ul>
The activeClassName
attribute gets applied to the Link
when the current item is active. And as you can see in the code, it’s referencing the .activeMenuItem
class selector. So go inside the header.module.scss
file and add this style:
.active-menu-item {
text-decoration: underline;
}
Save your files and see the styles applied in the frontend.
Now that you know how the CSS module works, let’s go ahead and add some styling to the body and footer sections. We always want the footer to stay at the bottom of the page. For that, we will set up a sticky footer.
This is very simple!
Update the layout.js
file so it looks like this:
...
import "../styles/style.scss"
import layoutStyles from "./layout.module.scss"
const Layout = props => {
return (
<div className={layoutStyles.container}>
<div className={layoutStyles.content}>
<Header />
<div className={layoutStyles.mainContent}>{props.children}</div>
</div>
<Footer />
</div>
)
}
...
The markup in the return
statement is a common structure for the sticky footer. Where the header and the main content are placed in a div
container while the footer is placed outside of it.
You’ll notice we imported a css module file named layout.module.scss
. So you need to create that file. In the same src/components
directory, create a layout.module.scss
file and add the following:
.container {
display: flex;
flex-direction: column;
min-height: 100vh;
}
.content {
flex-grow: 1;
}
.main-content {
margin: 0 auto;
max-width: 750px;
padding: 3rem 1rem 4rem;
}
Save the files.
In the same way, update the footer.js
file so you have:
import React from 'react';
import footerStyles from './footer.module.scss';
const Footer = () => {
return (
<footer className={footerStyles.siteFooter}>
<div className={footerStyles.container}>
<p>
Site developed by Ibaslogic ©{' '}
{new Date().getFullYear().toString()}{' '}
</p>
</div>
</footer>
);
};
export default Footer;
Then create footer.module.scss
file in the components
directory and add the following:
.site-footer {
background-color: #000;
color: #515151;
}
.container {
margin: 0 auto;
max-width: 750px;
padding: 1rem;
}
Save your files and check the frontend. Your page should look like this:
Looks good.
Now you know how to add styles to your Gatsby site. Depending on what you want, you can decide to add a global style or locally scope your style to your component. Besides, you also learned how to implement SASS in a Gatsby site.
In the next section, we will start working on getting dynamic data to our site.
Next part: Sourcing data in gatsby
continue