Styled JSX

Styled JSX is a CSS-in-JS library that allows you to write encapsulated and scoped CSS to style your components. The styles you introduce for one component won't affect other components, allowing you to add, change and delete styles without worrying about unintended side effects.

Creating a site theme

Inside colors.js add your color palette. The color tokens will be an object containing the values in increments of 100 which will allow us to access them using the syntax blue[100].

// utils/colors.js

export const blue = {
  100: "#3a36e0",
  200: "#0804b8",
  300: "#030086",
  400: "#5f25a4",
  500: "#050449"
};

export const green = {
  100: "#529e66",
  200: "#367b48",
  300: "#276738"
};

export const yellow = {
  100: "#e1c542",
  200: "#cab23f",
  300: "#b49e35"
};

export const red = {
  100: "#d0454c",
  200: "#b54248",
  300: "#95353a"
};

export const neutral = {
  100: "#ffffff",
  200: "#f4f5f7",
  300: "#e1e1e1",
  400: "#737581",
  500: "#4a4b53",
  600: "#000000"
};

typography.js

// utils/typography.js

export const primaryFont = '"Roboto Mono", monospace';
// utils/typography.js

export const typeScale = {
  header1: "1.8rem",
  header2: "1.6rem",
  header3: "1.4rem",
  header4: "1.2rem",
  header5: "1.1rem",
  paragraph: "1rem",
  helperText: "0.8rem",
  copyrightText: "0.7rem"
};

theme.js

// utils/theme.js

import { blue, yellow, neutral } from "./colors";
import { primaryFont } from "./typography";

export const defaultTheme = {
  primaryColor: blue[300],
  primaryHoverColor: blue[200],
  primaryActiveColor: blue[100],
  primaryWarningColor: yellow[300],
  textColorOnPrimary: neutral[100],
  textColor: neutral[600],
  textColorInverted: neutral[100],
  primaryFont: primaryFont,
};

Add an index.js file inside of utils/ which exports each utility.

// utils/index.js

export * from "./colors";
export * from "./typography";
export * from "./theme";

This will allow us to import utilities from the utils folder instead of the individual folder.

import { defaultTheme } from "./../utils"

// We don't need import { defaultTheme } from "./../utils/theme";

Finally let's use our theme inside of our Buttons.js file

// styles/Buttons.js

import css from "styled-jsx/css";
import { defaultTheme, typeScale } from "./../utils";

const button = css.button`
  padding: 8px 12px;
  font-size: ${typeScale.paragraph};
  border-radius: 5px;
  min-width: 100px;
  cursor: pointer;

  :hover {
    background-color: ${defaultTheme.primaryHoverColor};
  }
`;

export const PrimaryButton = ({ children }) => (
  <button>
    {children}
    <style jsx>{button}</style>
    <style jsx>{`
      button {
        background-color: ${defaultTheme.primaryColor};
        color: ${defaultTheme.textColorInverted};
        border: 2px solid transparent;
      }
    `}</style>
  </button>
);

export const WarningButton = ({ children }) => (
  <button>
    {children}
    <style jsx>{button}</style>
    <style jsx>{`
      button {
        background-color: ${defaultTheme.primaryWarningColor};
        color: ${defaultTheme.textColorInverted};
        border: 2px solid transparent;
      }
    `}</style>
  </button>
);

You can then use those styles in your component:

import { PrimaryButton } from "./../../styles/Buttons";

export default () => (
    <div>
      <PrimaryButton>My Button</PrimaryButton>
    </div>
)

Adding global styles

To apply global styles to all pages in our app, a good approach is to first create a layout component with the global styles, then wrap all pages with it.

Using a layout component provides the flexibility to apply a certain set of styles to some pages while still allowing a different style for others.

// styles/global.js

import css from "styled-jsx/css";
import { defaultTheme, typeScale } from "./../utils";

export default css.global`
  body {
    margin: 0;
    padding: 0;
    font-size: ${typeScale.paragraph};
    font-weight: 400;
    line-height: 1.8;
    color: ${defaultTheme.textColor};
    font-family: ${defaultTheme.primaryFont};
  }
  h1 {
    font-weight: 700;
  }
  p {
    margin-bottom: 10px;
  }
`;
// components/Layout.js

import globalStyles from "../../styles/global";

function Layout(props) {
  return (
    <div className="page-layout">
      {props.children}
      <style jsx global>
        {globalStyles}
      </style>
    </div>
  );
}

export default Layout;

Last updated