Skip to main content
Theme UI is built on the idea of using design scales for styling. A theme object contains collections of design tokens organized into scales like colors, fonts, and spacing values.

Theme Object Structure

The Theme type defines the complete structure of a Theme UI theme:
export interface Theme {
  // Design scales
  colors?: ColorModesScale
  space?: Scale<CSS.Property.Margin<number | string>>
  fonts?: Scale<CSS.Property.FontFamily>
  fontSizes?: Scale<CSS.Property.FontSize<number>>
  fontWeights?: Scale<CSS.Property.FontWeight>
  lineHeights?: Scale<CSS.Property.LineHeight<TLengthStyledSystem>>
  letterSpacings?: Scale<CSS.Property.LetterSpacing<TLengthStyledSystem>>
  sizes?: Scale<CSS.Property.Height<{}> | CSS.Property.Width<{}>>
  borders?: Scale<CSS.Property.Border<{}>>
  borderStyles?: Scale<CSS.Property.Border<{}>>
  borderWidths?: Scale<CSS.Property.BorderWidth<TLengthStyledSystem>>
  radii?: Scale<CSS.Property.BorderRadius<TLengthStyledSystem>>
  shadows?: Scale<CSS.Property.BoxShadow>
  zIndices?: Scale<CSS.Property.ZIndex>
  transitions?: Scale<CSS.Property.Transition>
  opacities?: Scale<CSS.Property.Opacity>
  
  // Configuration
  config?: ThemeUIConfig
  
  // Breakpoints
  breakpoints?: Array<string>
  mediaQueries?: { [size: string]: string }
  
  // Element styles
  styles?: ThemeStyles
  
  // Component variants
  buttons?: Record<string, ThemeUIStyleObject>
  text?: Record<string, ThemeUIStyleObject>
  links?: Record<string, ThemeUIStyleObject>
  images?: Record<string, ThemeUIStyleObject>
  cards?: Record<string, ThemeUIStyleObject>
  layout?: Record<string, ThemeUIStyleObject>
  forms?: Record<string, ThemeUIStyleObject>
  badges?: Record<string, ThemeUIStyleObject>
  alerts?: Record<string, ThemeUIStyleObject>
  // ... and more
}

Design Scales

Design scales are collections of related values stored as arrays or objects. Theme UI uses these scales to provide consistent styling across your application.

Space Scale

The space scale is used for margin, padding, and other spatial properties:
const theme = {
  space: [0, 4, 8, 16, 32, 64, 128, 256, 512]
}
You can reference these values by index:
<Box sx={{ m: 2, p: 3 }} />
// margin: 8px, padding: 16px

Color Scale

Colors can be defined as flat or nested objects:
const theme = {
  colors: {
    text: '#000',
    background: '#fff',
    primary: '#07c',
    secondary: '#609',
    muted: '#f6f6f6'
  }
}

Font Scales

const theme = {
  fonts: {
    body: 'system-ui, -apple-system, sans-serif',
    heading: 'Georgia, serif',
    monospace: 'Menlo, monospace'
  },
  fontSizes: [12, 14, 16, 20, 24, 32, 48, 64, 72],
  fontWeights: {
    body: 400,
    heading: 700,
    bold: 700
  },
  lineHeights: {
    body: 1.5,
    heading: 1.125
  }
}

Other Scales

const theme = {
  // Border radius
  radii: [0, 4, 8, 16],
  
  // Box shadows
  shadows: {
    small: '0 1px 3px rgba(0,0,0,0.12)',
    medium: '0 4px 6px rgba(0,0,0,0.16)',
    large: '0 10px 20px rgba(0,0,0,0.19)'
  },
  
  // Z-index values
  zIndices: {
    dropdown: 1000,
    modal: 1050,
    tooltip: 1100
  },
  
  // Transitions
  transitions: {
    fast: '150ms ease-in-out',
    normal: '300ms ease-in-out'
  }
}

Nested Scales with __default

Theme UI supports nested scales with a special __default key for shorthand access:
const theme = {
  colors: {
    primary: {
      __default: '#00f',
      light: '#33f',
      dark: '#00a'
    }
  }
}
Usage:
<Box sx={{ color: 'primary' }} />
// color: #00f (uses __default)

<Box sx={{ color: 'primary.light' }} />
// color: #33f

Scale Mappings

Theme UI automatically maps CSS properties to theme scales:
export const scales = {
  // Colors
  color: 'colors',
  backgroundColor: 'colors',
  borderColor: 'colors',
  
  // Space
  margin: 'space',
  marginTop: 'space',
  padding: 'space',
  gap: 'space',
  
  // Typography
  fontFamily: 'fonts',
  fontSize: 'fontSizes',
  fontWeight: 'fontWeights',
  lineHeight: 'lineHeights',
  letterSpacing: 'letterSpacings',
  
  // Borders
  borderRadius: 'radii',
  borderWidth: 'borderWidths',
  
  // Shadows and sizing
  boxShadow: 'shadows',
  width: 'sizes',
  height: 'sizes',
  
  // ... and many more
}

Example Theme

Here’s a complete example theme from the Theme UI codebase:
import { makeTheme } from '@theme-ui/css/utils'

export const theme = makeTheme({
  config: {
    initialColorModeName: 'light',
    useColorSchemeMediaQuery: true,
  },
  colors: {
    text: '#000',
    background: '#fff',
    primary: '#07c',
    secondary: '#b0b',
    modes: {
      dark: {
        text: '#fff',
        background: '#222',
        primary: '#0cf',
        secondary: '#faf',
      },
    },
  },
  fonts: {
    body: 'system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif',
    heading: 'sans-serif',
  },
  radii: [0, 4],
  styles: {
    root: {
      fontFamily: 'body',
      color: 'text',
      bg: 'background',
      p: 4,
    },
    a: {
      color: 'primary',
      fontWeight: 'bold',
      textDecoration: 'none',
      ':hover': {
        color: 'secondary',
        textDecoration: 'underline',
      },
    },
  },
  buttons: {
    primary: {
      cursor: 'pointer',
    },
  },
})

Using the Theme

Wrap your application with ThemeProvider:
import { ThemeProvider } from '@theme-ui/core'
import theme from './theme'

function App() {
  return (
    <ThemeProvider theme={theme}>
      {/* Your app */}
    </ThemeProvider>
  )
}
Access the theme in components:
import { useThemeUI } from '@theme-ui/core'

function MyComponent() {
  const { theme } = useThemeUI()
  return <div>Primary color: {theme.colors.primary}</div>
}

Merging Themes

You can merge multiple theme objects:
import { merge } from '@theme-ui/core'

const baseTheme = { /* ... */ }
const customTheme = { /* ... */ }

const mergedTheme = merge(baseTheme, customTheme)

// Merge multiple themes
const multiMerged = merge.all(theme1, theme2, theme3)
Theme values are automatically applied when using the sx prop, making it easy to create consistent, theme-aware components.

Build docs developers (and LLMs) love