Skip to main content
The sx prop is the primary way to style elements with Theme UI. It provides theme-aware styling with automatic lookups to your theme’s design scales.

Basic Usage

The sx prop accepts a style object with CSS properties:
<div
  sx={{
    color: 'primary',
    bg: 'background',
    p: 3,
    borderRadius: 4
  }}
>
  Hello World
</div>

Theme Lookups

The sx prop automatically maps CSS properties to theme scales:
// These properties map to theme scales:
export const scales = {
  color: 'colors',
  backgroundColor: 'colors',
  borderColor: 'colors',
  margin: 'space',
  marginTop: 'space',
  padding: 'space',
  paddingLeft: 'space',
  fontFamily: 'fonts',
  fontSize: 'fontSizes',
  fontWeight: 'fontWeights',
  lineHeight: 'lineHeights',
  letterSpacing: 'letterSpacings',
  border: 'borders',
  borderWidth: 'borderWidths',
  borderStyle: 'borderStyles',
  borderRadius: 'radii',
  boxShadow: 'shadows',
  textShadow: 'shadows',
  zIndex: 'zIndices',
  width: 'sizes',
  height: 'sizes',
  // ... and more
}

Example with Theme

Given this theme:
const theme = {
  colors: {
    primary: '#07c',
    background: '#fff'
  },
  space: [0, 4, 8, 16, 32],
  radii: [0, 4, 8]
}
This component:
<Box
  sx={{
    color: 'primary',      // → #07c (from theme.colors)
    bg: 'background',      // → #fff (from theme.colors)
    p: 3,                  // → 16px (from theme.space[3])
    borderRadius: 1        // → 4px (from theme.radii[1])
  }}
/>

Property Aliases

Theme UI provides shorthand aliases for common CSS properties:
const aliases = {
  bg: 'backgroundColor',
  m: 'margin',
  mt: 'marginTop',
  mr: 'marginRight',
  mb: 'marginBottom',
  ml: 'marginLeft',
  mx: 'marginX',  // marginLeft + marginRight
  my: 'marginY',  // marginTop + marginBottom
  p: 'padding',
  pt: 'paddingTop',
  pr: 'paddingRight',
  pb: 'paddingBottom',
  pl: 'paddingLeft',
  px: 'paddingX', // paddingLeft + paddingRight
  py: 'paddingY'  // paddingTop + paddingBottom
}
Example usage:
<Box
  sx={{
    bg: 'primary',
    px: 3,        // paddingLeft: 16px, paddingRight: 16px
    my: 2         // marginTop: 8px, marginBottom: 8px
  }}
/>

Nested Selectors

You can use nested selectors for more complex styling:
<div
  sx={{
    color: 'text',
    '& a': {
      color: 'primary',
      textDecoration: 'none'
    },
    '& > p': {
      mb: 3
    }
  }}
/>

Pseudo-Selectors

All CSS pseudo-selectors are supported:
<button
  sx={{
    bg: 'primary',
    color: 'white',
    ':hover': {
      bg: 'secondary'
    },
    ':focus': {
      outline: '2px solid',
      outlineColor: 'primary'
    },
    ':active': {
      transform: 'scale(0.98)'
    },
    ':disabled': {
      opacity: 0.5,
      cursor: 'not-allowed'
    }
  }}
>
  Click me
</button>

Example from Theme UI Source

Here’s a real example from the Theme UI codebase:
const theme = {
  styles: {
    a: {
      color: 'primary',
      textDecoration: 'none',
      bg: 'primary05',
      p: 1,
      borderRadius: '2px',
      ':hover': {
        p: 2,
        m: -1,
        borderRadius: '4px',
      },
    },
  },
}

Media Queries

You can use media queries directly:
<div
  sx={{
    fontSize: 2,
    '@media screen and (min-width: 40em)': {
      fontSize: 3
    },
    '@media screen and (min-width: 52em)': {
      fontSize: 4
    }
  }}
/>
For responsive styles, use responsive arrays instead of media queries for a cleaner syntax.

Nested Scale Access

Access nested values in theme scales using dot notation:
const theme = {
  colors: {
    primary: {
      __default: '#00f',
      light: '#33f',
      dark: '#00a'
    }
  }
}
<Box sx={{ color: 'primary.light' }} />
// color: #33f

Negative Values

Use negative values for margins and positioning:
<Box
  sx={{
    mt: -3,      // Negative value from theme.space[3]
    ml: '-16px'  // Negative pixel value
  }}
/>
With theme values:
const theme = {
  space: [0, 4, 8, 16, 32]
}
<Box sx={{ mt: -2 }} />
// marginTop: -8px (negative of theme.space[2])

Raw CSS Values

You can use raw CSS values that won’t be transformed:
<div
  sx={{
    color: '#f00',           // Raw hex color
    padding: '1rem',         // Raw CSS value
    width: '50%',            // Raw percentage
    fontSize: 'inherit'      // CSS keyword
  }}
/>

The css Function

The sx prop uses the css function internally. You can use it directly:
import { css } from '@theme-ui/css'

const styles = css({
  color: 'primary',
  bg: 'background',
  p: 3
})

const result = styles({ theme })
// Returns plain CSS object

Variants

Apply pre-defined style variants from your theme:
const theme = {
  buttons: {
    primary: {
      color: 'white',
      bg: 'primary',
      fontWeight: 'bold',
      borderRadius: 2
    },
    secondary: {
      color: 'text',
      bg: 'secondary'
    }
  }
}
<button
  sx={{
    variant: 'buttons.primary'
  }}
>
  Primary Button
</button>

Function Values

Access the theme object directly with function values:
<div
  sx={{
    color: theme => theme.colors.primary,
    margin: theme => theme.space[3] * 2
  }}
/>

Type Safety

The sx prop is fully typed in TypeScript:
import type { ThemeUIStyleObject } from '@theme-ui/css'

const styles: ThemeUIStyleObject = {
  color: 'primary',
  bg: 'background',
  p: 3,
  ':hover': {
    color: 'secondary'
  }
}
The sx prop provides a powerful, theme-aware styling API that makes it easy to build consistent, maintainable designs.

Build docs developers (and LLMs) love