Skip to content
Theme UI
GitHub

Theming

Theming with theme-ui is based on the System UI Theme Spec with an additional theme.styles object for styling markdown elements and other components.

Colors

Add a theme.colors object to provide colors for a theme. In order to make themes and projects built with theme-ui as portable and interoperable as possible, the following base color abstraction should be used for defining a base set of colors:

KeyDescription
textbody color
backgroundbody background color
primaryprimary button and link color
secondarysecondary color - can be used for hover states
muteda gray or subdued color for decorative purposes

Beyond these base colors, any additional values can be added to a theme to augment the base color palette.

Color Modes

Color modes, such as dark and light modes, can be handled with a nested modes object that matches the shape of the default colors.

// example colors with modes
colors: {
  text: '#000',
  background: '#fff',
  primary: '#07c',
  modes: {
    dark: {
      text: '#fff',
      background: '#000',
      primary: '#0cf',
    }
  }
}

See the color mode docs for more information.

Typography

Core typographic values can be stored in the following theme keys:

  • fonts (font families)
  • fontSizes
  • fontWeights
  • lineHeights
  • letterSpacings
// example theme object
{
  colors,
  fonts: {
    body: 'system-ui, sans-serif',
    heading: 'Georgia, serif',
    monospace: 'Menlo, monospace',
  },
  fontSizes: [
    12, 14, 16, 20, 24, 32, 48, 64
  ],
  fontWeights: {
    body: 400,
    heading: 700,
    bold: 700,
  },
  lineHeights: {
    body: 1.5,
    heading: 1.125,
  },
  letterSpacings: {
    body: 'normal',
    caps: '0.2em',
  },
}

Styles

Styles for elements rendered in MDX can be added to the theme.styles object. This is the primary, low-level way to control typographic and other styles in markdown content. Styles within this object are processed with @styled-system/css and have access to base theme values like colors, fonts, etc.

// example theme styles
{
  colors: {
    text: '#000',
    background: '#fff',
    primary: '#07c',
  },
  fonts: {
    body: 'system-ui, sans-serif',
    heading: 'Georgia, serif',
  },
  fontWeights: {
    body: 400,
    heading: 700,
  },
  styles: {
    h1: {
      fontSize: 32,
      fontFamily: 'heading',
      fontWeight: 'heading',
      color: 'primary',
      mt: 4,
      mb: 2,
    },
  }
}

Typography.js

Since Typography.js outputs a style object, this can be passed to the theme.styles object to style content in an MDX document. In order to fit the shape required in theme-ui, the theme-ui/typography module can be used in place of the core Typography.js module.

import Typography from 'theme-ui-typography'
import wordpress2016 from 'typography-theme-wordpress-2016'
import merge from 'lodash.merge'

const typography = Typography(wordpress2016)

const theme = {
  styles: merge(typography.styles, {
    // ...additional styles
  })
}

Note: the Typography.js integration is still in progress and the API may change over time

Layout

The built in theme-ui layout components can also be styled with the theme.styles object.

For example, to change the max-width of the Container component, styles can be set in the theme:

// example theme with Container styles
{
  styles: {
    Container: {
      maxWidth: 768
    },
  }
}

Syntax Highlighting

When using syntax highlighting that produces spans with class names, colors and other styles can be added to theme.styles.pre using the @styled-system/css variant feature.

Note: this approach is in progress and the API may change

First, create a theme.prism object for handling the syntax highlighting styles.

{
  colors: {
    gray: '#666',
  },
  prism: {
    '.comment': {
      // theme.colors and other values can be referenced
      color: 'gray',
    }
  }
}

Next, add a theme.styles.pre object that references the prism variant.

{
  colors: {
    gray: '#666',
  },
  prism: {
    '.comment': {
      // theme.colors and other values can be referenced
      color: 'gray',
    }
  },
  styles: {
    pre: {
      variant: 'prism',
      // add other custom styles for the base pre tag
    }
  }
}

Since theme-ui uses Emotion for styling, multiple classNames can be targeted by using an array as a key.

{
  prism: {
    [[
      '.comment',
      '.prolog',
      '.doctype',
      '.cdata'
    ]]: {
      color: 'gray',
    },
    '.comment': {
      fontStyle: 'italic',
    }
  }
}