Paul Cook

Styling Gatsby with Tailwind and Emotion Styled Components

February 27, 2020

Trees being blown in the wind

Introduction

In the spirit of continuous dissatisfaction with my current site, I've decided to add Tailwind into the mix.

Right now my site uses Emotion to do some very barebones styling, but I've been wanting to play around with Tailwind for quite a while, because, why not?

Before I do that (and because I ran into problems doing it with my current setup) I decided to do a dry run with CodeSandbox.

We'll use CodeSandbox and the Gatsby starter default to accomplish it.

If you want to skip the rest of this and just see the results, you can find that here: https://codesandbox.io/s/gatsby-starter-with-tailwind-and-emotion-nb2w7

Don't know what Emotion and Tailwind are?

You're not alone!

The short of it is that Emotion helps you write your CSS in your JS and Tailwind is a CSS framework for writing your styles with utility classes.

If that doesn't answer your questions check out their docs:

What this post isn't

An introduction to any of these technologies. I'll post some resources at the end if you want to dig into them further, but this is just intended to explain how I scratched my itch figuring out how to Emotion and Tailwind together in Gatsby.

Something I intend to apply to my website very soon.

Let's install stuff!

Everyone's favorite part of the tutorials is talking about what you need to install, right? Great!

I want to be able to do 2 things:

  1. Be able to use Tailwind in my CSS-in-JS styling.
  2. Be able to use Tailwind classes as you would normally within className.

Step 1: Install Tailwind

npm install tailwindcss --save-dev

Step 2: Install the PostCSS plugin for Gatsby

npm install --save gatsby-plugin-postcss

Additionally, we'll need to add a PostCSS config in the root folder called postcss.config.js. Add this:

module.exports = () => ({
  plugins: [require("tailwindcss")],
})

Step 3: Install the Babel Tailwind macro

npm install --save tailwind.macro@next

Step 4: Install the necessary libraries for Emotion

This is because I want to use Emotion! Thankfully, it's my site so I don't have to justify my decisions to 3rd parties.

npm install --save gatsby-plugin-emotion @emotion/core @emotion/styled

Then add the plugin to your gatsby-config.js

Step 5: Install Purgecss

To remove those unwanted styles we aren't using we'll want to add Purgecss.

Thankfully, Gatsby has a plugin to help us out:

npm i gatsby-plugin-purgecss

Confirming we're all on the same page

After installing everything you should be sure to have the plugins in your gatsby-config.js.

Do note: the Purgecss plugin goes LAST.

plugins: [
    `gatsby-plugin-postcss`,
    `gatsby-plugin-emotion`,
    // ...other plugins,
    {
      resolve: `gatsby-plugin-purgecss`,
      options: {
        printRejected: true,
        tailwind: true,
      },
    },  
],

Styling and profiling

I'm going to do all of the example styling in the index.js of the gatsby-starter-default.

Using Tailwind Macro

I'm not well versed in Babel macro's, but I thought this was pretty sweet.

import tw from "tailwind.macro"
const Text = tw.p`
  text-xl text-gray-700 font-sans 
`

const IndexPage = () => (
  <Layout>
    <SEO title="Home" />
    <h1>Hi people</h1>
    <Text>Welcome to your new Gatsby site.</Text>
    <Text>Now go build something great.</Text>
    <div style={{ maxWidth: `300px`, marginBottom: `1.45rem` }}>
      <Image />
    </div>
    <Link to="/page-2/">Go to page 2</Link>
  </Layout>
)

What Babel does is transform the tagged templates into a style object.

This is from the docs:

In

const foo = tw`text-red hover:text-green sm:text-blue` 

Out

const foo = {
  color: '#e3342f',
  ':hover': {
    color: '#38c172'
  },
  '@media (min-width: 576px)': {
    color: '#3490dc'
  }
}

Mixing up Tailwind and Emotion

If you happen to be incrementally adding Tailwind onto a site that already has some styled components you can do that too.

All you need to do is wrap

import styled from "@emotion/styled"

const Header = styled.h1`
  color: red;
  ${tw`
    text-xl font-mono
  `}
`

const IndexPage = () => (
  <Layout>
    <SEO title="Home" />
    <Header>Hi people</Header>
    <Text>Welcome to your new Gatsby site.</Text>
    <Text>Now go build something great.</Text>
    <div style={{ maxWidth: `300px`, marginBottom: `1.45rem` }}>
      <Image />
    </div>
    <Link to="/page-2/">Go to page 2</Link>
  </Layout>
)

Using Utility classes

And then last but not least can always use Tailwind's utility class directly in className.

const IndexPage = () => (
  <Layout>
    <SEO title="Home" />
    <Header className="bg-black">Hi people</Header>
    <Text>Welcome to your new Gatsby site.</Text>
    <Text>Now go build something great.</Text>
    <div style={{ maxWidth: `300px`, marginBottom: `1.45rem` }}>
      <Image />
    </div>
    <Link
      className="block mt-1 text-lg leading-tight font-semibold text-gray-900 hover:underline"
      to="/page-2/"
    >
      Go to page 2
    </Link>
  </Layout>
)

Conclusion

That's all I needed to get up and running.

Let me know if you run into any problems. Feel free to message me on Twitter or ask questions in the comments and I'll try to help you out.

If this was helpful you be sure to heart it and retweet.

Thanks!

Additional links for your own research