loading...

Let's Refactor My Personal Website and Portfolio using Gatsby, Part Four: CSS in JS Using Emotion

dylanesque profile image Michael Caveney Updated on ・4 min read

Part One
Part Two
Part Three

Welcome to the latest entry in my portfolio refactor blog series! Today I'm going to discuss how you can make CSS architecture in your applications easier by using the popular CSS-in-JS library Emotion.

What Is CSS-in-JS?

CSS-in-JS is exactly what it sounds like: using some combination of architectural style or third-party library to place most, if not all of a project's CSS in the JS files. It's somewhat controversial amongst developers, but I have found it to simplify the CSS code I need to write in applications, making maintenance, debugging, and overall drafting of code quicker.

What is Emotion and How Does It Work?

There are several strong choices for CSS-in-JS libraries out there, but I'm going with Emotion on this project because I haven't used it before, and it has been one of the favorites for a long time. It's worth noting at this point that the major CSS-In-JS libraries more or less have feature parity, so use the one that works best for you or your team.

To use Emotion in a Gatsby project, we need to include the package(s) and the corresponding plugin:

npm i --save @emotion/core @emotion/styled gatsby-plugin-emotion
Enter fullscreen mode Exit fullscreen mode

And add that plugin to gatsby-config.js:

`gatsby-plugin-emotion`
Enter fullscreen mode Exit fullscreen mode

There are a couple of different ways that I could go about styling with Emotion in Gatsby. The first, and my least preferred, is using the css prop, which is literally sets the style(s) as a prop that gets passed into components, ala the following example:

import React from "react"
import styled from "@emotion/styled"
import { css } from "@emotion/core"

const redBackground = css`
  background-color: red;
`

<h1 css={redBackground}>I am a demo headline</h1>
Enter fullscreen mode Exit fullscreen mode

While this can work for smaller insertions of code, I feel that it adds noise to the JS code and makes it less readable.

Edit: Something I've learned the hard way when using Emotion with Gatsby, or perhaps any instance in which you're trying to use it on non-native HTML elements: styled-components may not work as expected on certain elements (like Gatsby/Reach Router's <Link />, and the css prop as absolutely necessary in instances like this.

My preferred architectural style for Emotion is using styled components, something cribbed from the previously mentioned styled-components library. This works by creating a new named component as a tagged template literal, and adding the styles inside, like the Headline component in the following example:

import React from "react"
import styled from '@emotion/styled';

import Layout from "../components/layout"
import Image from "../components/image"
import SEO from "../components/seo"

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

export default IndexPage;

const Headline = styled.h1`
  color: white;
  background-color: purple
`;
Enter fullscreen mode Exit fullscreen mode

I like this style because:

  • It makes is easy to separate the CSS logic from the React logic on the page. You don't have to put the styled components underneath the export statement, but I do so for readability.

  • You have the opportunity to again, improve code readability, with semantically named components.

  • Having all component-specific logic, including styling, in one place can really aid with site building and maintenance speed.

  • Another advantage I almost forgot to mention is this technique disrupts the normal CSS cascade, resulting is less monkey-patching and hacks like !important to get desired results, which can reduce a lot of mental overhead.

  • You don't HAVE to put everything in components: My usual approach, especially for smaller site like this one is going to be, is to maintain a traditional CSS file for any and all global styling for the site, and put everything else in individual components. When I refactored the last iteration of my portfolio from standard CSS to styled-components, this reduced the size of my global CSS file by about 400 lines.

Wrap Up

At the end of the day, you have to decide if a CSS-In-JS library is a CSS tool that works for you, but I hope that a lot of others can get the vastly improved experience that tools like Emotion and styled-components have given me.

I've written very little application-specific code in these first four part of this walkthrough of my new site, but that changes next week as we take a deep dive into working with images in Gatsby, and a landing page starts to emerge!

Discussion

pic
Editor guide