Tailwind CSS installation with Next.js and Styled Components

Tailwind CSS installation with Next.js and Styled Components cover image

Outdated: This is an old Tailwind v1-era setup using twin.macro, Styled Components, and custom Babel config. I am keeping it as an archive. For a current setup, use the official Tailwind CSS Next.js guide.

At the time, I wanted Tailwind utilities inside a Next.js app that already used Styled Components. twin.macro was the bridge: it let me write Tailwind classes inside CSS-in-JS without giving up the component style I was using.

Create the app

yarn create next-app example
cd example

Install Tailwind, Styled Components, and the macro packages:

yarn add tailwindcss postcss autoprefixer twin.macro styled-components
yarn add -D babel-plugin-macros babel-plugin-styled-components

Configure the macro

Create babel-plugin-macros.config.js:

module.exports = {
  twin: {
    preset: 'styled-components',
  },
}

Then add a .babelrc so Next uses the macro and Styled Components plugin:

{
  "presets": ["next/babel"],
  "plugins": [
    "babel-plugin-macros",
    [
      "styled-components",
      {
        "pure": true,
        "ssr": true
      }
    ]
  ]
}

Add Tailwind globals

In _app.js, wrap the app with GlobalStyles from twin.macro:

import { GlobalStyles } from 'twin.macro'
 
const App = ({ Component, pageProps }) => (
  <>
    <GlobalStyles />
    <Component {...pageProps} />
  </>
)
 
export default App

Initialize Tailwind:

npx tailwindcss init

Back then I also needed a webpack workaround for the fs module:

module.exports = {
  webpack: (config, { isServer }) => {
    if (!isServer) {
      config.node = { fs: 'empty' }
    }
 
    return config
  },
}

Try a small component

import tw, { css } from 'twin.macro'
 
export default function Index() {
  return (
    <div
      css={[
        css`
          height: 100vh;
        `,
        tw`flex items-center justify-center bg-black text-2xl text-white`,
      ]}
    >
      Hello, World!
    </div>
  )
}

This worked, but I would not start here today. Modern Tailwind and Next.js do not need this much Babel and webpack wiring. The useful lesson from this old setup is smaller: if a styling tool needs this many adapters, check whether the newer official path has already made the adapters obsolete.