Download this example using degit
npx degit https://github.com/ben-rogerson/twin.examples/next-emotion 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 @emotion/react @emotion/styled @emotion/css @emotion/server
npm install -D twin.macro tailwindcss @emotion/babel-plugin babel-plugin-macros
Install with Yarn
yarn create next-app
Install the dependencies
yarn add @emotion/react @emotion/styled @emotion/css @emotion/server
yarn add -D twin.macro tailwindcss @emotion/babel-plugin babel-plugin-macros
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.
You can add Twin’s GlobalStyles
import in pages/_app.js
:
// pages/_app.js
import { GlobalStyles } from 'twin.macro'
const App = ({ Component, pageProps }) => (
<div>
<GlobalStyles />
<Component {...pageProps} />
</div>
)
export default App
Creating a _document.js
file like this will put critical styles in the head of the page.
Without this step, you’ll notice a difference between the SSR generated styles and the ones that hydrate on the client side.
// pages/_document.js
import React from 'react'
import Document, { Html, Head, Main, NextScript } from 'next/document'
import { extractCritical } from '@emotion/server'
export default class MyDocument extends Document {
static async getInitialProps(ctx) {
const initialProps = await Document.getInitialProps(ctx)
const critical = extractCritical(initialProps.html)
initialProps.html = critical.html
initialProps.styles = (
<React.Fragment>
{initialProps.styles}
<style
data-emotion-css={critical.ids.join(' ')}
dangerouslySetInnerHTML={{ __html: critical.css }}
/>
</React.Fragment>
)
return initialProps
}
render() {
return (
<Html lang="en">
<Head>
<style
data-emotion-css={this.props.ids.join(' ')}
dangerouslySetInnerHTML={{ __html: this.props.css }}
/>
</Head>
<body>
<Main />
<NextScript />
</body>
</Html>
)
}
}
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: 'emotion',
},
}
b) Or in package.json
:
// package.json
"babelMacros": {
"twin": {
"preset": "emotion"
}
},
Note: The preset gets set to 'emotion' by default, so adding the config is only useful if you want to adjust Twin’s other options.
Add this babel configuration in .babelrc.js
:
// .babelrc.js
module.exports = {
presets: [
[
'next/babel',
{
'preset-react': {
runtime: 'automatic',
importSource: '@emotion/react',
},
},
],
],
plugins: ['@emotion/babel-plugin', 'babel-plugin-macros'],
}
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 emotion