DEV Community

loading...

Add Theme UI to your NextJS site

Eka
Web developer, late bloomer. Can center an element with grace and style (pun intended). Mostly sensible (citation needed).
・2 min read

Theme UI is a React styling library “based on constraint-based design principles”, where we can centralize our design tokens in a regular JavaScript theme object . Although there’s no Theme UI plugin specifically for NextJS like for Gatsby, we can add Theme UI to our NextJS web app/site in three straightforward steps.

1. Install theme-ui

npm i -D theme-ui
# or yarn add theme-ui

2. Create and export the theme object

// src/utils/theme.js
export default {
  colors: {
    text: "#111",
    background: "#fff",
    primary: "tomato",
    secondary: "#3f3f3f",
    muted: "#e0e0e0",
    highlight: "#9f9f9f",
    gray: "#6c6c6c",
    accent: "#3f3f3f",
  },
  fonts: {
    body: "Comic Sans MS",
  },
};

You can use any filename and directory, just make sure you import it correctly in the next step. See more theming references and demo in the Theme UI docs.

3. Wrap our NextJS app with Theme UI’s ThemeProvider

We achieve this by making use of NextJS’s custom App.

// src/pages/_app.js
import * as React from "react";
import NextApp from "next/app";
import { ThemeProvider } from "theme-ui";
import theme from "../utils/theme"; // theme object from step 2

export default class App extends NextApp {
  render() {
    const { Component, pageProps } = this.props;
    return (
      <ThemeProvider theme={theme}>
        <Component {...pageProps} />
      </ThemeProvider>
    );
  }
}

We also add Theme UI’s InitializeColorMode to NextJS’s custom Document to prevent flash of colour.

// src/pages/_document.js
import Document, { Main, NextScript } from "next/document";
import { InitializeColorMode } from "theme-ui";

export default class extends Document {
  static async getInitialProps(ctx) {
    const initialProps = await Document.getInitialProps(ctx);
    return { ...initialProps };
  }

  render() {
    // Replace html lang attribute value with your language.
    return (
      <html lang="en">
        <body>
          <InitializeColorMode />
          <Main />
          <NextScript />
        </body>
      </html>
    );
  }
}

Learn more:

Does it work?

We should be able to use the sx property in our components. Remember to use the @jsx pragma and import jsx in order to use it.

// src/any-component.js
/** @jsx jsx */
import { jsx } from "theme-ui";

export default function SomeComponent() {
  return (
    <>
      <div sx={{ backgroundColor: "primary", color: "#fff", p: 4 }}>
        tomato
      </div>
    </>
  );
}

Run npm run dev (or yarn dev) to check if the theme styles have been applied.

That’s it, we have added Theme UI in our NextJS site!

Discussion (2)

Collapse
jameshusband profile image
James Husband

A nice solution, but theme-ui should be included in dependencies rather than devDependencies

Collapse
varun_mathur profile image
Varun

Hi Eka - This was quite insightful. Would love to connect. Thanks.