Add inline style elements in Gatsby

I wanted to add inline style elements that are unique per page in this Gatsby blog. My use case was to create several posts where I would share my notes about some typefaces I like from Google Fonts. Inside those posts, I would download the font files, display an interactive component where the user can add text and change font-related CSS attributes, and, finally, show some interesting characters and OpenType features.

I didn’t want the font face rules to be present in all pages, something that would increase the HTML size. If you want that, you have a ton of options. Let’s name a few:

  • You can import a CSS file inside your gatsby-browser.js file.
  • You can import a CSS file inside any React component.
  • You can create a “global style” with a CSS-in-JS library like styled-components or emotion.
  • You can use the Gatsby SSR APIs. More specifically, the onRenderBody and its parameters setHeadComponents and setPostBodyComponents.

Coming back to the initial requirement, if you want to add an inline style element that would apply only to a specific page in Gatsby, you can do the following:

src/pages/page-2.js
const Page2 = () => (
  <Layout>
    <Helmet>
      <style type="text/css">
        {`
        @font-face {
          font-family: "Source Sans Variable";
          font-display: swap;
          font-weight: 200 900;
          font-style: normal;
          font-stretch: normal;
          src: url("/fonts/SourceSansVariable-Roman-latin.woff2") format("woff2");
          unicode-range: U+00-FF;
        }
        ... skipping the rest
      `}
      </style>
    </Helmet>
    <h1>Page 1</h1>
    {/* content */}
  </Layout>
);

In my case, the pages were not JSX files but MDX, and the above snippet didn’t work inside an MDX page. The workaround was simple—and maybe preferred from a “clean code” perspective. I created a react-helmet only component with the font faces, and then I imported that component inside the MDX. This the component I’m talking about:

content/posts/source-sans/font-faces.jsx
import React from "react";
import { Helmet } from "react-helmet";

export default () => (
  <Helmet>
    <style type="text/css">
      {`
        @font-face {
          ... skipping
        }
      `}
    </style>
  </Helmet>
);

And this is the import/render inside the MDX page:

content/posts/source-sans/index.mdx
import FontFaces from "./font-faces";

<FontFaces />;

The GitHub page for the react-helmet has a reference guide that shows how to add other types of elements in the head of the document.

Don't forget that to use react-helmet properly in Gatsby, you need the gatsby-plugin-react-helmet plugin.

Other things to read

Popular

Previous/Next