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-macros
Install with Yarn
yarn create next-app
Install the dependencies
yarn add styled-components
yarn add twin.macro tailwindcss babel-plugin-macros --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 {
WebkitTapHighlightColor?: ${theme`colors.purple.500`};
${tw`antialiased`}
}
`;
const GlobalStyles = () => (
<>
<BaseStyles />
<CustomStyles />
</>
);
export default GlobalStyles;
Then import the GlobalStyles file in pages/_app.js
:
// pages/_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",
autoCssProp: false,
},
};
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",
["babel-plugin-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