DEV Community

Cover image for πŸ’… Setting up styled components with Next.js 9.5.2
Dharmi Kumbhani
Dharmi Kumbhani

Posted on

πŸ’… Setting up styled components with Next.js 9.5.2

Step 1 - Creating a Next.js application

I just like all my development folders to be on Desktop so i do cd Desktop

cd Desktop
npx create-next-app
//Running this script on the folder you want to store the project folder
* Will ask you whats your project name? projectName
/*
Enter the project name and it will create a folder with that name along 
with all the neccessary files
*/
Enter fullscreen mode Exit fullscreen mode

Step 2 - Adding styled-components library

yarn add styled-components
Enter fullscreen mode Exit fullscreen mode

Step 3 - Adding developer dependency

yarn add -D babel-plugin-styled-components
Enter fullscreen mode Exit fullscreen mode

-D flag is used for adding the library as a developer dependency.

Step 4 - Creating .babelrc file

To put things into perspective when working with styled components along with SSR it creates a hash (unique names) and that can get a bit tricky while debugging. This file does the following 2 things

  1. Let's babel know that styled components is to be rendered on the server side.
  2. Turns displayName to true so that you can make the className more familiar.

Full documentation of the plugin can be found here: https://styled-components.com/docs/tooling#babel-plugin

{
  "presets": ["next/babel"],
  "plugins": [["styled-components", { "ssr": true, "displayName": true}]]
}
Enter fullscreen mode Exit fullscreen mode

i have seen a environment version of the same like this :

this was used so to prevent props className warning/error but however this error pops up sometimes even after adding this file.

className warning error

You can track this issue here: https://github.com/vercel/next.js/issues/16637

{
   "env": {
      "development": {
         "plugins": [
            [
               "styled-components",
               { "ssr": true, "displayName": true, "preprocess": false }
            ]
         ],
         "presets": ["next/babel"]
      },
      "production": {
         "plugins": [
            [
               "styled-components",
               { "ssr": true, "displayName": true, "preprocess": false }
            ]
         ],
         "presets": ["next/babel"]
      }
   },
   "plugins": [
      [
         "styled-components",
         { "ssr": true, "displayName": true, "preprocess": false }
      ]
   ]
}
Enter fullscreen mode Exit fullscreen mode

Step 5 - Creating _document.js

Create a file named "_document.js" inside your pages folder. This overrides the default Document file that is made in

A custom Document is commonly used to augment your application's and

tags. This is necessary because Next.js pages skip the definition of the surrounding document's markup.

To override the default Document, create the file ./pages/_document.js and extend the Document class as shown below:

You can find more on this here: https://nextjs.org/docs/advanced-features/custom-document

import Document, {Html, Head, Main, NextScript } from 'next/document'
import { ServerStyleSheet } from 'styled-components'

export default class MyDocument extends Document {
  static async getInitialProps(ctx) {
    const sheet = new ServerStyleSheet()
    const originalRenderPage = ctx.renderPage

    try {
      ctx.renderPage = () =>
        originalRenderPage({
          enhanceApp: (App) => (props) =>
            sheet.collectStyles(<App {...props} />),
        })

      const initialProps = await Document.getInitialProps(ctx)
      return {
        ...initialProps,
        styles: (
          <>
            {initialProps.styles}
            {sheet.getStyleElement()}
          </>
        ),
      }
    } finally {
      sheet.seal()
    }
  }
  render() {
    return (
        <Html lang="en">
            <Head />
            <body>
                <Main />
                <NextScript />
            </body>
        </Html>
    );
}
}
Enter fullscreen mode Exit fullscreen mode

The collectStyles method wraps your element in a provider.

getStyleElement() method that returns an array of React elements.

Know more about what is severSideRendering https://styled-components.com/docs/advanced#server-side-rendering

Thats it! Test it.

Now you add the following code inside index.js

index.js:

import Head from 'next/head'
import styled from  'styled-components';
// Creating a styled-component
const Test = styled.p`
  font-size: 40px;
  color: blue;
`;
export default function Home() {
  return (
    <div>
      <Head>
        <title>Create Next App</title>
        <link rel="icon" href="/favicon.ico" />
      </Head>
      <main>
                {/*Testing Styled component */}
        <Test>Hello</Test>
      </main>
    </div>
  )
};
Enter fullscreen mode Exit fullscreen mode

Once this is added go to your terminal inside your folder and run:

$ yarn dev
// $ just mean run it inside your bash terminal you just need to copy "yarn dev"
Enter fullscreen mode Exit fullscreen mode

Once this is done go to https://localhost.3000 and see your next.js app running.

Hello world screen on local host

Extras: How to use Global Styles with styled components

import { createGlobalStyle } from "styled-components";

const GlobalStyle = createGlobalStyle`
    p {
    font-size: 20;
  }
`;

function MyApp({ Component, pageProps }) {
  return (
    <>
      <GlobalStyle />
      <Component {...pageProps} />
    </>
  );
}

export default MyApp
Enter fullscreen mode Exit fullscreen mode

Important Pointer:

If your are watching this in future post release of Next.js 9.5.2 and its not working for some reason this is a repository that you would want to keep an eye out for any changes : https://github.com/vercel/next.js/tree/master/examples/with-styled-components

Other resources:

https://codesandbox.io/s/github/zeit/next.js/tree/canary/examples/with-styled-components?file=/pages/index.js

https://dev.to/rffaguiar/nextjs-typescript-styled-components-1i3m#bonus1

https://nextjs.org/learn/basics/assets-metadata-css/global-styles (Use this even for SVG icons)

Discussion (0)