reactjsgatsbystyled-componentsserver-side-renderingcss-in-js

Is there a way in Gatsby to export inlined styled components CSS into a CSS file?


I have accomplished my first Gatsby app, which will be going to production soon. Here's the link: https://majiid-landing-page.vercel.app/

I have used styled components throughout the app, I usually take the SCSS with BEM approach, but I wanted to try this CSS in JS approach.

The issue is that the page first appears unstyled for a fraction of a second, then the styles are parsed, like if those were injected with JS, while the styles are actually in the HTML as Gatsby uses SSR.

Is this the normal behaviour?

I'm not sure how to reproduce the whole thing as the repo is private anyways I'm using GlobalStyles as well as specific styles in every component.

Here's some snippets:

Global Styles

import React from "react";

import Abstracts from "./abstracts/abstracts";
import Base from "./base/base";
import Utils from "./utils/utils";

const GlobalStyles = () => {
  return (
    <>
      <Abstracts />
      <Base />
      <Utils />
    </>
  );
};

export default GlobalStyles;

Example of global styles creation:

import { createGlobalStyle } from "styled-components";

export default createGlobalStyle`
  :root {
      // COLORS
    --body-background: #ffffff;
  }
`;

Gatsby SSR

// gatsby-ssr.js
const React = require("react");
require("./src/scss/index.scss");
const GlobalStyles = require("./src/styles/global-styles").default;
const Layout = require("./src/layout/Layout").default;

exports.wrapRootElement = ({ element }) => {
  return (
    <>
      <GlobalStyles />
      <Layout>{element}</Layout>
    </>
  );
};

gatsby-browser.js

const React = require("react");
require("./src/scss/index.scss");
const GlobalStyles = require("./src/styles/global-styles").default;
const Layout = require("./src/layout/Layout").default;

exports.wrapRootElement = ({ element }) => {
  console.log("Running this");
  return (
    <>
      <GlobalStyles />
      <Layout>{element}</Layout>
    </>
  );
};

Gatsby Config (extract):

plugins: [
    "gatsby-plugin-styled-components",
...

package.json dependencies

"dependencies": {
    "@vimeo/player": "^2.16.0",
    "babel-plugin-styled-components": "^1.13.2",
    "bootstrap": "^5.1.0",
    "gatsby": "^3.11.1",
    "gatsby-plugin-image": "^1.11.0",
    "gatsby-plugin-react-helmet": "^4.11.0",
    "gatsby-plugin-sass": "^4.11.0",
    "gatsby-plugin-sharp": "^3.11.0",
    "gatsby-plugin-sitemap": "^4.7.0",
    "gatsby-plugin-styled-components": "^4.11.0",
    "gatsby-plugin-webfonts": "^2.1.1",
    "gatsby-source-contentful": "^5.11.1",
    "gatsby-source-filesystem": "^3.11.0",
    "gatsby-transformer-sharp": "^3.11.0",
    "node-sass": "^6.0.1",
    "normalize.css": "^8.0.1",
    "polished": "^4.1.3",
    "react": "^17.0.1",
    "react-dom": "^17.0.1",
    "react-helmet": "^6.1.0",
    "react-icons": "^4.2.0",
    "react-responsive": "^9.0.0-beta.3",
    "styled-components": "^5.3.0"
  }

Solution

  • This has made it: https://www.youtube.com/watch?v=G_dVwrhvkBI

    Basically the Global Styles have to be applied in a wrapPageElement hook instead of the wrapRootElement one.

    I'll leave it here if anyone else searches SO to handle this issue.