SimpleNext.js

How to use styled components in Next.js apps

Cover Image for How to use styled components in Next.js apps
Marouane Reda
Marouane Reda

While Next.js comes with styled-jsx as a built-in styling solution, you may be wishing to use styled-components to style your app. In this article we will see how to use styled components in an example Next.js app without hassle!

What is styled components

styled components is a tool meant to write CSS scoped to a single components and ensures it doesn't leak to other parts of our apps.

In the example below we style Title component and Wrapper component individually :

// Create a Title component that'll render an <h1> tag with some styles
const Title = styled.h1`
  font-size: 1.5em;
  text-align: center;
  color: palevioletred;
`;

// Create a Wrapper component that'll render a <section> tag with some styles
const Wrapper = styled.section`
  padding: 4em;
  background: papayawhip;
`;

// Use Title and Wrapper like any other React component – except they're styled!
render(
  <Wrapper>
    <Title>
      Hello World!
    </Title>
  </Wrapper>
);

the main benefits of using styled components are :

  • Minimal generation of CSS
  • Automatic generation of class names avoids bugs such as duplication, misspelling, ...
  • Easier maintenance, upgrade or deletion of your CSS

How to use styled components in Next.js

We will see now how to use styled components in an example Next.js app :

Step1 : Install styled components

Open your terminal window and navigate to the place you want your Next.js project to locate in then running:

npx create-next-app next_styled

The name is totally up to you.

Navigate to the project root folder:

cd next_styled

Install styled components with the following command:

# with npm
npm install --save styled-components

#or with yarn
yarn add styled-components

Step 2 :Create a /pages directory and your first page.

From your project root directory:

mkdir pages && touch pages/index.js

Populate ./pages/index.js:

export default () => (
   <div>
       <h1>My First Next.js Page</h1>
   </div>
)

and then just run yarn dev and go to http://localhost:3000.

Step 3 : Add babel plugin and custom .bablerc file

First, lets install the styled components babel plugin as a dev dependency:

yarn add -D babel-plugin-styled-components

then create a .babelrc file :

{
  "presets": ["next/babel"],
  "plugins": [["styled-components", { "ssr": true }]]
}

Step 4 : create a custom _document.js file

Now we will create a pages/_document.js file, this file basically will override the default document and will be applied to all pages :

import Document 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()
    }
  }
}

now you can style your components, like in the index.js page :

import styled from 'styled-components';

or add a global style in your _app.js file :

```javascript
import { createGlobalStyle, ThemeProvider } from 'styled-components'

const GlobalStyle = createGlobalStyle`
  body {
    margin: 0;
    padding: 0;
    box-sizing: border-box;
  }
`

const theme = {
  colors: {
    primary: '#0070f3',
  },
}

export default function App({ Component, pageProps }) {
  return (
    <>
      <GlobalStyle />
      <ThemeProvider theme={theme}>
        <Component {...pageProps} />
      </ThemeProvider>
    </>
  )
}


export default () => (
  <div>
    <Title>My First Next.js Page</Title>
  </div>
);

const Title = styled.h1`
  color: red;
`;