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
or
yarn create next-app --typescript
then add these packages,
yarn add styled-components
yarn add -D @types/styled-components
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;
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();
}
}
}
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;
`}
`;
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;
}
}
}
}
`;
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;
}
}
}
}
`;
Top comments (4)
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.
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 ?
If you don't customize
_document.tsx
, thenstyled-components
styling is not rendered on server side, but only on client side.Exactly, The author should update the blog with these info.