Styled-components
Setup
- install packages
npm install --save styled-components
npm install --save-dev babel-plugin-styled-components
- (Deprecated after next12) add
.babelrc
{
"presets": ["next/babel"],
"plugins": [["styled-components", { "ssr": true, "displayName": true }]]
}
According to the document, use
next.config.js
as the alternative.
next.config.js
const nextConfig = {
compiler: {
styledComponents: true,
},
}
module.exports = nextConfig
Usage
-
Extended Styled Components
import { Icon } from "../../../../styles/Icon";
export const IconMusic = styled(Icon)``;
- with arguments
import styled, { css } from "styled-components";
const Button = styled.button`
border-radius: 3px;
${props => props.primary && css`
background: palevioletred;
color: white;
`}
`;
- element with attribute
const InputColor = styled.input.attrs({
type: 'color',
})`
border-radius: 3px;
`;
- usage in
.js
render(
<Container>
<InputColor/>
<Button>Normal Button</Button>
<Button primary>Primary Button</Button>
</Container>
);
- keyframes
import styled, { css, keyframes } from "styled-components";
const sizeChangingAnimation = keyframes`
0% { transform: scale(1.0);}
50% { transform: scale(0.7);}
100% { transform: scale(1.0);}
`;
export const IconMusic = styled.div`
${(props) =>
props.isPlaying &&
css`
animation: ${sizeChangingAnimation} 1s infinite;
`}
`;
Advanced
Vite
vite.config.js
import { defineConfig } from 'vite'
import react from '@vitejs/plugin-react'
// https://vitejs.dev/config/
export default defineConfig({
plugins: [react({
include: /\.(jsx|tsx)$/,
babel: {
plugins: ['styled-components'],
babelrc: false,
configFile: false,
},
})],
})
Frequently changed styles.
- If styles change frequently use following syntax.
+ const Component = styled.div.attrs((props) => ({
+ style: {
+ backgroundColor: props.color,
+ },
+ }))`
- background-color: ${(props) => props.color};
/* Other static styles here */
`;
- This change make component appends a inline-style instead of creating a new class during every update.
<div color="#877d7d" class="styled__Component-sc-16v9z3c-4 jYllQ" style="background-color: rgb(135, 125, 125);"></div>
Server side rendering Styled-Components with NextJS
-
disable JavaScript on the browser (e.g in Chrome: Settings / Site settings / JavaScript / Blocked) to check setting works
-
/pages/_document.js
import Document, { Head, Html, 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> <Head /> <body style=> <Main /> <NextScript /> </body> </Html> ); } }
Examples
Dropdown Menu
import styled from "styled-components";
const Icon = styled.div`
pointer-events: auto;
`;
const Menu = styled.div`
display: none;
`;
const Wrapper = styled.div`
&:focus-within {
${Menu} {
display: flex;
}
${Icon} {
pointer-events: none;
}
}
`;
const DropdownMenu = ({ children }) => (
<Wrapper>
<Icon tabIndex={0}>
// some icon.
</Icon>
<Menu tabIndex={1}>
{children}
</Menu>
</Wrapper>
);