Download this example using degit
npx degit https://github.com/ben-rogerson/twin.examples/next-styled-components folder-name
From within the new folder, run npm install
, then npm start
to start the dev server.
Install Next.js
npx create-next-app
Install the dependencies
npm install styled-components
npm install -D twin.macro tailwindcss babel-plugin-styled-components babel-plugin-macros react-is
Install with Yarn
yarn create next-app
Install the dependencies
yarn add styled-components
yarn add twin.macro tailwindcss babel-plugin-styled-components babel-plugin-macros react-is --dev
Twin uses the same preflight base styles as Tailwind to smooth over cross-browser inconsistencies.
The GlobalStyles
import adds these base styles along with some @keyframes for the animation classes and some global css that makes the ring classes and box-shadows work.
Due to an issue in styled-components, global styles get added in the wrong order when using styled-components. This gives the tailwind base styles an incorrect specificity.
Until the issue is fixed, the workaround is to export the styles from another file.
You can import GlobalStyles
within a new file placed in components/GlobalStyles.js
:
// components/GlobalStyles.js
import React from 'react'
import { createGlobalStyle } from 'styled-components'
import tw, { theme, GlobalStyles as BaseStyles } from 'twin.macro'
const CustomStyles = createGlobalStyle`
body {
-webkit-tap-highlight-color: ${theme`colors.purple.500`};
${tw`antialiased`}
}
`
const GlobalStyles = () => (
<>
<BaseStyles />
<CustomStyles />
</>
)
export default GlobalStyles
Then import the GlobalStyles file in page/_app.js
:
// page/_app.js
import GlobalStyles from './../components/GlobalStyles'
const App = ({ Component, pageProps }) => (
<div>
<GlobalStyles />
<Component {...pageProps} />
</div>
)
export default App
Twin’s config can be added in a couple of different files.
a) Either in babel-plugin-macros.config.js
:
// babel-plugin-macros.config.js
module.exports = {
twin: {
preset: 'styled-components',
},
}
b) Or in package.json
:
// package.json
"babelMacros": {
"twin": {
"preset": "styled-components"
}
},
Add this babel configuration in .babelrc.js
:
// In .babelrc.js
module.exports = {
presets: [['next/babel', { 'preset-react': { runtime: 'automatic' } }]],
plugins: ['babel-plugin-macros', ['styled-components', { ssr: true }]],
}
To avoid the ugly Flash Of Unstyled Content (FOUC), add a server stylesheet in pages/_document.js
that gets read by Next.js:
// pages/_document.js
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()
}
}
}
Learn how to work with twin
- The prop styling guide - A must-read guide to level up on prop styling
- The styled component guide - A must-read guide on getting productive with styled-components
Learn more about styled-components