Setup Emotion to use Tailwind classes in Next.js

Created
Oct 4, 2021 6:11 PM
Tags
devcsstailwind
URL
https://codedaily.io/tutorials/187/Setup-Emotion-to-use-Tailwind-classes-in-Nextjs
Type
Article
image

Why?

Rather than utilizing class names and handling the optimization of which Tailwind classes to include we can leverage the style attributes but render those values with Emotion.

We can also integrate dynamic and existing styling with Emotion. Further more because the styles are dynamically assessed we can check that the style actually exists from Tailwind.

If there is ever a className you're trying to use that isn't supplied by Tailwind, or a style that was created from your modifications to Tailwind config an error will be thrown.

This allows you to verify that all your styling and classes exist in your whole app.

Setup the Dependencies and Base

Rather than provide an install this is the package.json there are a lot of packages that all work in conjunction with each other.

This is just a basic Tailwind config. Setup yours for whatever you need.

// tailwind.config.js
const defaultTheme = require('tailwindcss/defaultTheme')

module.exports = {
  theme: {
    extend: {
      fontFamily: {
        sans: ['Inter var', ...defaultTheme.fontFamily.sans],
      },
    },
  },
  variants: {},
  plugins: [require('@tailwindcss/ui')],
}

If you make any changes here run yarn build:base-css to rebuild and regenerate the base css.

Config Babel

Now create a custom .babelrc file at the root, and add next/babel as the first preset. This is essential. Then add our @emotion/babel-preset-css-prop to the preset which will automatically look for css={} props and swap over the jsx pragma for you.

So you do not need to manually add /** @jsx jsx */ to the top of the file with the jsx import.

Also add babel-macros so we can transform our Tailwind classnames into CSS that will be passed into Emotion.

// .babelrc
{
  "presets": ["next/babel", "@emotion/babel-preset-css-prop"],
  "plugins": ["macros"]
}

Add in Custom _document Page

This is semi-optional, but probably recommended. If you plan to use @emotion/css at all then this it is required to setup a custom _documentpage. This will allow you to render and extract all the styling at SSR time to ensure it's all there at initial render time.

Also to include font stylings that are recommended from Tailwind.

Add in Custom _app Page

The custom _app will allow us to include global CSS, but not have it imported as css modules. Next.js will automatically include and insert a link tag in the head for us.

import Head from "next/head";
import "../styles/base.css";

export default function MyApp({ Component, pageProps }) {
  return (
    <>
      <Head>
        <title>Tailwindcss Emotion</title>
      </Head>
      <Component {...pageProps} />
    </>
  );
}

Style Option One with className

If you do not want to use the @emotion/babel-preset-css-prop plugin this is an option. Using @emotion/css and wrapping the tw macro to turn the combination of stylings into a stringified className.

Also if you need to combine styles you can use the cx export from @emotion/css to dynamically apply styling. This is the most verbose option of styling.

Style with @emotion/styled

A typical styling from @emotion is to use the styled package and create styled components. These are components that can be used as normal React components but have their encapsulated styling applied.

You can additionally supply a className or even css prop to add extend and add more styling.

Style with css Prop

A handy method that @emotion/babel-preset-css-prop allows is to add a css prop. This means we do not need to import anything but our tailwind macro. It will handle converting our supplied styles to a className. So it might appear as a css prop here but will be compiled to className prop.

Further we don't even need cx here as it accepts an array of styles to apply, and this can even be dynamically changed.

VSCode Extension

If you want an even easier time writing your styling install the VSCode extension https://marketplace.visualstudio.com/items?itemName=DennisVash.twin-macro-autocomplete-vscode

It will autocomplete for the tw macro.

Conclusion

Overall this might be over kill, but it is a great way to add autocompletion, and verify that all the classes inside of your app are valid. Further it will only include the exact styling you need, so no need to analyze your code and remove classNames from Tailwind after the fact. It does that automatically for us.