DEV Community

Cover image for Using styled components with next.js 12 and typescript in 2022
Sumukhakb
Sumukhakb

Posted on • Edited on

Using styled components with next.js 12 and typescript in 2022

In this article, I will show how you can use styled-components in next.js 12 along with typescript.


Benefits:-

  • We can use normal css syntax, instead of using css-in-js method. In order to set background color, we write background-color:red in plain css instead of using css-in-js method(annoying) backgroundColor="red".
  • If you are a fan of sass(scss) like me, we can use sass like syntax inside the component.
  • Documentation is also pretty good.
  • Output size is small.

Project Repo:- https://github.com/Sumukha210/tesla-clone


Installing Next.js along with other dependencies,

npx create-next-app@latest --typescript
Enter fullscreen mode Exit fullscreen mode

or

yarn create next-app --typescript 
Enter fullscreen mode Exit fullscreen mode

then add these packages,

yarn add styled-components
Enter fullscreen mode Exit fullscreen mode
yarn add -D @types/styled-components
Enter fullscreen mode Exit fullscreen mode

Configuring Styled components for Next.js

You can skip this part if you are using plain React.js

If you are Next.js 12, then you can just use this code, in next.config.js,

/** @type {import('next').NextConfig} */
const nextConfig = {
  reactStrictMode: false,
  compiler: {
    styledComponents: true,
  },
};

module.exports = nextConfig;
Enter fullscreen mode Exit fullscreen mode

In _document.tsx file(inside pages folder), use this method if you are not using Next.js 12

import Document, { DocumentContext } from "next/document";
import { ServerStyleSheet } from "styled-components";

export default class MyDocument extends Document {
  static async getInitialProps(ctx: DocumentContext) {
    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();
    }
  }
}
Enter fullscreen mode Exit fullscreen mode

Now we can get started to use styled components along with next js and typescript


Creating a Button component


const MyCustomBtn = () => <Button darkBtn={false}>Custom Btn Button</Button>;

// Creating Simple button with props, checkout button component in elements folder for more advanced stuff about button
type buttonProps = {
  active?: boolean; // making this props optional
  darkBtn: boolean;
};

const Button = styled.button<buttonProps>`
  background-color: ${({ darkBtn }) =>
    darkBtn
      ? "black"
      : "cyan"}; // i am destructing here, instead of using as prop.darkBtn
  padding: 1rem 2rem;
  font-size: 1.2rem;
  border: none;

  &:hover {
    background: rebeccapurple;
  }


  /* if you want to place multiple lines of css, you can import {css}  */
  ${({ active }) =>
    active &&
    css`
      border: 2px solid gold;
      background-color: darkcyan;
      color: white;
    `}
`;

Enter fullscreen mode Exit fullscreen mode

Creating a Container Component, using scss like syntax inside the component,


const MyContainer: React.FC = ({ children }) => (
  <Container>
    <div className="content">
      <ul>
        <li>First list</li>
        <li>second list</li>
        <li>third list</li>
        <li>fourth list</li>
      </ul>
      {children}
    </div>
  </Container>
);

const Container = styled.div`
  width: 80%;

  .content {
    padding: 2rem;

    ul {
      margin-bottom: 5rem;
      li {
        &:not(:last-child) {
          margin-bottom: 0.5rem;
        }
      }
    }
  }
`;
Enter fullscreen mode Exit fullscreen mode

Final Code:-

import React from "react";
import styled, { css } from "styled-components";

const StyledComponents = () => {
  return (
    <MyContainer>
      <MyCustomBtn />
    </MyContainer>
  );
};

export default StyledComponents;

const MyCustomBtn = () => <Button darkBtn={false}>Custom Btn Button</Button>;

// Creating Simple button with props, checkout button component in elements folder for more advanced stuff about button
type buttonProps = {
  active?: boolean; // making this props optional
  darkBtn: boolean;
};

const Button = styled.button<buttonProps>`
  background-color: ${({ darkBtn }) =>
    darkBtn
      ? "black"
      : "cyan"}; // i am destructing here, instead of using as prop.darkBtn
  padding: 1rem 2rem;
  font-size: 1.2rem;
  border: none;

  &:hover {
    background: rebeccapurple;
  }

  /* if you want to place multiple lines of css, you can import {css}  */
  ${({ active }) =>
    active &&
    css`
      border: 2px solid gold;
      background-color: darkcyan;
      color: white;
    `}
`;

const MyContainer: React.FC = ({ children }) => (
  <Container>
    <div className="content">
      <ul>
        <li>First list</li>
        <li>second list</li>
        <li>third list</li>
        <li>fourth list</li>
      </ul>
      {children}
    </div>
  </Container>
);

const Container = styled.div`
  width: 80%;

  .content {
    padding: 2rem;

    ul {
      margin-bottom: 5rem;
      li {
        &:not(:last-child) {
          margin-bottom: 0.5rem;
        }
      }
    }
  }
`;
Enter fullscreen mode Exit fullscreen mode

Final output:-

Code output

Top comments (4)

Collapse
 
sgagliardi profile image
Stefano Gagliardi

Good morning! Thanks for the guide, really well done!
I wanted to point out to everyone that it is no longer necessary to edit the _document.tsx with NextJs12.
NextJs in version 12 if we enable compilation via SWC, in the next.config.js inside the" Compiler "object we can define the following propertystyledComponents: true.

nextjs.org/docs/advanced-features/...

This is enough for a correct loading of the Styled Components with Typescript in Nextjs.
NB: as indicated in the documentation linked above, it is not yet possible to use the "compiler" property with "Babel" as they are finishing the porting.

Collapse
 
sumukhakb210 profile image
Sumukhakb

Thank you for mentioning this. But I tried this method, and it didn't work properly on production build, is there any other configuration needed ?

Collapse
 
writer0713 profile image
KIM JUNGHWAN

If you don't customize _document.tsx, then styled-components styling is not rendered on server side, but only on client side.

Collapse
 
dkumar431 profile image
Deepak kumar padhy

Exactly, The author should update the blog with these info.