Skip to content

Latest commit

 

History

History
 
 

next-emotion

twin, next, emotion

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.

Table of contents

Getting started

Installation

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

Add the global styles

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

SSR styles setup

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>
    )
  }
}

Add the twin config (optional)

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 the babel config

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'],
}

Customization

Next steps

Learn how to work with twin

Learn more about emotion