Styling Gatsby Site with Typography & Sass Plugins

Note: This is part 2 of five-parts adding functionality to Gatsby site series. This learning post is still in active development and updated regularly.

In a previous post, Understanding Gatsby Building Blocks, adding basic styling in Gatsby site with traditional single style sheet (eg. style.css) and Gatsbyjs recommended CSS module were discussed briefly.

Gatsby developers and its users community prefer to use inline styling CSS-in-JS and CSS modules methods. The Gatsby official starter blog and theme include typography.js for global styling and inline CSS-in-JS libraries (eg. Emotion) for the component styling.

Learning series
Part 1: Adding Syntax highlighter with Prismjs
Part 2: Styling Gatsby Site with Typography & Sass Plugins (this post)
Part 3: Learning to Work With Images in Gatsby Sites
Part 4: Adding Tags to Gatsby Site
Part 5: Adding Pagination to Gatsby Site

In this part 2 of five-parts series we will overview other popular JavaScript-based styling methods and deep dive into Typography.js and Sass as an use case example.

Styling in Gatsby – A brief overview

Styling in Gatsby site is similar to styling React components. This can be achieved by using classic single (global) CSS style sheet or with component scoped (local) CSS modules or CSS-in-JavaScript, commonly referred as CSS-in-JS.

One of the biggest limitation of using global style sheet is “the risk of name conflicts and side effects like unintended inheritance “. This problem can be resolved using locally scoped CSS like CSS modules and CSS-in-JS.

Using Global Styling & CSS Modules

In previous post Understanding Building Blocks, very basic use of global css style sheet and CSS modules to style components were discussed with very simple use case examples.

CSS-in-JS

To quote from Gatsby Docs: “CSS-in-JS is a component-oriented styling approach. Most generally, it is a pattern where CSS is composed inline using JavaScript“. There are following two popular CSS-in-JS libraries that are commonly used in most Gatsby themes & popular among Gatsby user community:

Emotion: The Gatsby Docs describes this as a “performant and flexible CSS-in-JS library that allows to style React Apps with string or object styles. It has predictable composition to avoid CSS specificity issues“.
Additional Information: Emotion

Styled Components: This allows actual CSS use inside a React component. Because traditional CSS rules are global in nature, styled components avoids this problem because they are scoped within the components level only.
Additional information: Styled Components

CSS Libraries & Frameworks

There are CSS libraries and frameworks like Typography.js, Sass, JSS, Stylus, PostCSS, Bulma etc., to style Gatsby sites. These libraries or frameworks can be added using Gatsby plugins.

Additional Information: CSS Libraries & Frameworks

More detailed discussion on the use of CSS-in-JS in Gatsby site is outside the scope of this post. Though a opinionated approach, it is popular among JS developer community and will be revisited in a separate learning-note post.

Styling with Typography & SASS Plugins

The goal of this learning-note post is to explore the use of Typographic.js library & CSS processor like SASS to add google fonts or typefaces packages in styling Gatsby sites.

Global Styling with Typography.js Plugin

The Typography.js library, created by Kyle Mathews, is designed for use in Gatsby sites as global CSS layer. According to Mathews, it is an “opinionated toolkit for building websites with beautiful typography“. It allows to define custom fonts and the typography of Gatsby sites including pre-existing typographic themes.

Step 1: Installation of Plugin

Install the gatsby-plugin-typography and its dependencies as shown below:

#! inpm install
npm install --save gatsby-plugin-typography 
npm install --save  react-typography typography

#! yarn install
yarn add gatsby-plugin-typography 
yarn add react-typography typography
Step 2: Configuration of plugin in gatsby-config.js file
// gatsby-config.js 
module.exports = {
  siteMetadata: {
   // ..
  },
  // ..
  },
  {
    plugins [
    {
     // ...
    },
    {
      resolve: `gatsby-plugin-typography`,
      options: {
        pathToConfigModule: `src/utils/typography`,
      },
    },
    // ...
  ],
}

The plugin takes two options: pathToConfigModule (a string) is which is essential, or else it will not work. The other option omitGoogleFont (a boolean) should be set to false.

Step 3: Configuration of Typography.js

The Typography.js requires configuration file. Lets create utils sub-directory in src folder and create a file named typography.js.

Figure: Screenshot showing typography.js component (left) and its added style in document head (right) viewed with inspector in a Firefox browser.

In the example above, the typography.js file was configured as described in this documentation and Justin Formentin‘s Gatsby guide post.

Self-hosting Fonts with typefaces

To improve performance, fonts typefaces can be installed from the GitHub typefaces packages.

Each typeface package ships with all the necessary font files and CSS to self-host an open source typeface. All Google Fonts have been added as well as a small but growing list of other open source fonts. Typefaces.js | GitHub

Step 1: Install typeface fonts

Typefaces are available as npm packages for self-hosting and can be install with npm or yarn.

#! install fonts
yarn add typeface-source-sans-pro  
yarn add typeface-open-sans 
yarn add typeface-pt-sans

Each typeface package ships with all the necessary font files and CSS to self-host an open source typeface.

Step 2: Add the typefaces in gatsby-browser.js

The typefaces are added in gatsby-browser.js with require syntax (see below)

// gatsby-config.js - add require typefaces
require('typeface-source-sans-pro')
require('typeface-open-sans')
require('typeface-pt-sans')

It can also be added to the site’s entry file like <Layout /> component with import syntax.

// src/component/layout.js - add with import typefaces
import 'typeface-source-sans-pro';
import 'typeface-open-sans';
import 'typeface-pt-sans';

Gatsbyjs is setup to work typefaces and by default embeds CSS file in the <head> section for even faster loading.

Adding Typography.js Themes

Some global typography style like fonts and colors can also be configured through one of the many themes packages maintained at Typography.js. The themes can be used as such or with customization.

Step 1: Install the theme package
#! install theme & typography
yarn add typography typography-theme-kirkham

In the example above, a typography.js theme kirkham is added (above) and customized in utils/typography.js file (below)

Step 2: Configure the src/utils/typography.js file
//without customization
import Typography from 'typography'
import funstonTheme from 'typography-theme-kirkham'

const typography = new Typography(kirkhamTheme)

// with customizing
import Typography from 'typography'
import funstonTheme from 'typography-theme-kirkham'
//modify baseFontSize
kirkhamTheme.baseFontSize = '16px' // was 18px.

const typography = new Typography(kirkhamTheme)

The themes can be customized ( above line 11) where baseFontSize was modified from 18px to 16px and examples of how to customize themes is shown here.

Component Styling With Sass Plugin

Just like adding external .css style sheets in Gatsby, CSS processors like SASS or SCSS can also be added to Gatsby sites. The gatsby-plugin-sass provide support of SASS/SCSS style sheets.

Step 1: Install Plugin with npm or yarn
#! install node-sass & gatsby-sass
yarn add node-sass gatsby-plugin-sass

#! or with npm
npm install --save node-sass gatsby-plugin-sass

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
// include in gatsby-config.js
 module.exports = {
  siteMetadata: {
   // ..
  },
  // ..
  },
  {
    plugins [
    {
     // ...
    },
    // options can be included
    `gatsby-plugin-sass`
    // include options
   ],
}

Optionally, includePaths option can also be added to define path option

// src/gatsby-config.js
plugins: [
  {
    resolve: `gatsby-plugin-sass`,
    options: {
      includePaths: ["absolute/path/a" ],
      ...
    },
  },
]
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')

The .SCSS stylesheet can be imported to global <Layout /> component or 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 styles sub-directory as shown below:

#! style directory (partial)
├── src
│   └── styles
│       └── base
│           └── _variables.scss
│           └── _mixins.scss
│           └── _normalize.scss
│       └── scss
│           └── _elements.scss
│           └── _forms.scss
│           └── _site.scss
│           └── _post-pages.scss
│           └── _indexpage.module.scss
│           └── ...
│       └── main.scss
├── utils
│   └── typography.js
│ 
├── gatsby-browser.js
├── gatsby-config.js
├── gatsby-node.js
├──

Because this project is not being about Sass setting up variables, mixins , nesting and using Sass syntax are not discussed in this post. They could be found in this Sass guide.

Additional Information: SASS Basics | Learn Sass

Use Case Examples

In this project component styling is done with both the SCSS and CSS Module. Use of CSS module in styling Gatsby site was discussed in previous learning-note post too.

Step 1: Create Styling Rules with SCSS & SCSS module

As discussed in the previous section the index page of the site uses indexpage.module.scss file to style post title and its hover stage styling (shown below). Rest of the styling is achieved with other SCSS rules.

/* src/styles/scss/indexpage.module.scss */
.entrytitle {
  font-family: 'Helvetica Neue', Source Sans Pro, sans-serif;
  color: #cc3333;
  margin: .25em 0 .4em;
  font-size: 1.2rem;
  line-height: 1.2em;
}

/* hover stage background color */
@media screen and (min-width: 600px) {
  .entrytitle {
    font-size: 1.4rem;
    font-weight: 700;
    color: #cc3333;
    text-decoration: none !important;
    display: block;
    position: relative;
    &::after {
      content: "";
      position: absolute;
      width: 7em;
      transform: scaleX(0);
      height: 4px;
      bottom: 0;
      left: 0;
      background-color: rgba(70, 130, 180, 0.95);
      transform-origin: bottom right;
      transition: transform 0.4s cubic-bezier(0.86, 0, 0.07, 1);
    }
    &:hover::after {
      color: #000;
      text-decoration: none !important;
      transform: scaleX(1);
      transform-origin: bottom left;
    }
  }
}
Step 2: Apply CSS Module Rules in Page Component

The src/pages/index.js page component (partial) of the project site is shown below. The indexpage.module.scss rules are imported by giving a variable name styles (line 5).  Its important that the variable name shouldn’t contain cap, to not confuge for a component. Its rest of the styling rules comes from the <Layout /> component (line 4).

// src/pages/index.js
import React from "react"
import { Link, graphql } from "gatsby"
import Layout from "../components/layout"
import styles from "../styles/scss/indexpage.module.scss"

export default ({ data }) => (
  <Layout>
    <div>
     <h4>Total {data.allMarkdownRemark.totalCount} Posts</h4>
       {data.allMarkdownRemark.edges.map(({ node }) => (
         <div key={node.id}>
           <p className="date">Posted on {node.frontmatter.date}</p>
           <Link to={node.fields.slug} >
            <h2 className={styles.entrytitle}>{node.frontmatter.title}{" "}</h2>
           </Link>
            <p className="excerpt">{node.excerpt}</p> 
         </div>
       ))}
    </div>
  </Layout>
)

In the example above, the variable styles was referenced to style title as styles.entrytitle (line 15).

Step 3: View Styling Changes a Browser

After restarting the development server and viewed in localhost:8000 shows (see screenshot below) the post title color has been changed to red.

Figure: Screenshot of index.js page component styled using Scss and module.scss.

Because the css modules are locally scoped, the rules applies locally and do not affect the element styling with global rules.

Wrapping Up

In this learning-note posts, different methods to style Gatsby sites were highlighted.  The popular Typography.js library & npm typefaces packages were added to the project for global styling and SCSS & CSS Module for component styling. Use of the JS community favorite CSS-in-JS but controversial for others will be discussed separately.

Next Post: Learning to Work With Images in Gatsby Sites

Useful resources

While preparing this post, I have referred the following references extensively. Please to refer original posts for more detailed information.