The Theme UI styling system provides theme-aware styling through the sx prop, responsive design utilities, custom JSX runtime, and CSS-in-JS integration. It enables constraint-based design using theme scales and supports responsive breakpoints for mobile-first development.
The core JSX function that processes the sx prop and integrates with theme values for styling elements.
/**
* Enhanced JSX function with sx prop support and theme integration
* @param type - JSX element type or component
* @param props - Element props including sx
* @param children - Child elements
* @returns JSX element with processed theme-aware styles
*/
function jsx(type: any, props: any, ...children: any[]): JSX.Element;Usage Examples:
import { jsx } from 'theme-ui'
// Explicit jsx usage
const element = jsx('div', {
sx: { color: 'primary', p: 3 }
}, 'Hello Theme UI')
// With custom pragma (automatic)
/** @jsxImportSource theme-ui */
const component = <div sx={{ color: 'primary', p: 3 }}>Hello</div>Theme UI provides custom JSX runtime entries for automatic sx prop processing without manual jsx imports.
// JSX Runtime Entries
import 'theme-ui/jsx-runtime' // Production runtime
import 'theme-ui/jsx-dev-runtime' // Development runtime with enhanced debuggingUsage Examples:
// In tsconfig.json or babel config
{
"compilerOptions": {
"jsx": "react-jsx",
"jsxImportSource": "theme-ui"
}
}
// Or per-file pragma
/** @jsxImportSource theme-ui */
export default function Component() {
return <div sx={{ bg: 'primary', p: 4 }}>Automatic sx processing</div>
}The sx prop accepts theme-aware style objects with support for responsive values, pseudo-selectors, and nested styles.
interface SxProp {
/** Theme-aware style object supporting responsive values and theme lookups */
sx?: ThemeUIStyleObject;
}
interface ThemeUIStyleObject {
/** CSS properties with theme-aware values and responsive support */
[property: string]: ResponsiveStyleValue<any>;
/** Pseudo-selectors and nested styles */
[selector: `&:${string}`]: ThemeUIStyleObject;
[selector: `&[${string}]`]: ThemeUIStyleObject;
[selector: `& ${string}`]: ThemeUIStyleObject;
}
type ResponsiveStyleValue<T> = T | Array<T | null | undefined>;Usage Examples:
// Basic theme-aware styling
<Box sx={{
color: 'primary', // theme.colors.primary
fontSize: 3, // theme.fontSizes[3]
margin: 2, // theme.space[2]
fontFamily: 'heading' // theme.fonts.heading
}} />
// Responsive values (mobile-first)
<Box sx={{
fontSize: [2, 3, 4], // 14px, 16px, 20px at breakpoints
padding: [2, 3, 4, 5], // 8px, 16px, 32px, 64px
display: ['block', 'flex'] // block on mobile, flex on tablet+
}} />
// Pseudo-selectors and states
<Button sx={{
bg: 'primary',
'&:hover': {
bg: 'secondary'
},
'&:focus': {
outline: '2px solid',
outlineColor: 'primary'
},
'&[disabled]': {
opacity: 0.5
}
}} />
// Nested selectors
<Card sx={{
p: 3,
'& h2': {
color: 'heading',
fontSize: 4
},
'& > p': {
color: 'text',
lineHeight: 'body'
}
}} />Theme UI uses a mobile-first responsive approach with array-based responsive values and customizable breakpoints.
interface ResponsiveStyleValue<T> {
/** Single value applied at all breakpoints */
0: T;
/** Array of values for responsive breakpoints (mobile-first) */
1: Array<T | null | undefined>;
}
interface Breakpoints extends Array<string> {
/** Named breakpoint aliases */
[key: string]: string;
}Usage Examples:
// Default breakpoints: [40em, 52em, 64em]
const theme = {
breakpoints: ['40em', '52em', '64em', '80em'], // sm, md, lg, xl
}
// Responsive styling
<Box sx={{
width: ['100%', '50%', '33.333%', '25%'], // Full, half, third, quarter
padding: [1, 2, 3, 4], // 4px, 8px, 16px, 32px
display: ['block', null, 'flex'], // block mobile/tablet, flex desktop+
flexDirection: [null, null, 'row', 'column'] // only applies at lg and xl
}} />
// Named breakpoints
<Text sx={{
fontSize: {
_: 2, // base (mobile)
sm: 3, // small screens
md: 4, // medium screens
lg: 5 // large screens
}
}} />Theme UI provides utility functions for working with styles and theme values outside of React components.
/**
* Convert theme-aware style objects to CSS
* @param styles - Style object with theme references
* @returns Function that accepts theme and returns CSS object
*/
function css(styles: ThemeUIStyleObject): (theme: Theme) => CSSObject;
/**
* Get nested values from objects using dot notation
* @param object - Object to search
* @param key - Dot-notation key path
* @param fallback - Fallback value if key not found
* @returns Retrieved value or fallback
*/
function get(object: object, key: string, fallback?: any): any;Usage Examples:
import { css, get } from 'theme-ui'
// Generate CSS from theme-aware styles
const styles = css({
color: 'primary',
fontSize: 3,
'&:hover': {
color: 'secondary'
}
})
// Use with emotion or other CSS-in-JS
const StyledDiv = styled.div(styles)
// Get theme values programmatically
const primaryColor = get(theme, 'colors.primary', '#000')
const fontSize3 = get(theme, 'fontSizes.3', '16px')
const nestedValue = get(theme, 'components.Button.primary.backgroundColor')Many Theme UI components support system props for quick styling without the sx prop.
interface SystemProps {
// Margin
m?: ResponsiveStyleValue<string | number>;
margin?: ResponsiveStyleValue<string | number>;
mt?: ResponsiveStyleValue<string | number>;
mr?: ResponsiveStyleValue<string | number>;
mb?: ResponsiveStyleValue<string | number>;
ml?: ResponsiveStyleValue<string | number>;
mx?: ResponsiveStyleValue<string | number>;
my?: ResponsiveStyleValue<string | number>;
// Padding
p?: ResponsiveStyleValue<string | number>;
padding?: ResponsiveStyleValue<string | number>;
pt?: ResponsiveStyleValue<string | number>;
pr?: ResponsiveStyleValue<string | number>;
pb?: ResponsiveStyleValue<string | number>;
pl?: ResponsiveStyleValue<string | number>;
px?: ResponsiveStyleValue<string | number>;
py?: ResponsiveStyleValue<string | number>;
// Colors
color?: ResponsiveStyleValue<string>;
bg?: ResponsiveStyleValue<string>;
backgroundColor?: ResponsiveStyleValue<string>;
// Typography
fontSize?: ResponsiveStyleValue<string | number>;
fontFamily?: ResponsiveStyleValue<string>;
fontWeight?: ResponsiveStyleValue<string | number>;
lineHeight?: ResponsiveStyleValue<string | number>;
// Layout
width?: ResponsiveStyleValue<string | number>;
height?: ResponsiveStyleValue<string | number>;
minWidth?: ResponsiveStyleValue<string | number>;
maxWidth?: ResponsiveStyleValue<string | number>;
minHeight?: ResponsiveStyleValue<string | number>;
maxHeight?: ResponsiveStyleValue<string | number>;
}Usage Examples:
// System props for quick styling
<Box
p={4} // padding: theme.space[4]
m={[2, 3]} // responsive margin
bg="primary" // background: theme.colors.primary
color="white" // color: theme.colors.white
fontSize={[2, 3, 4]} // responsive font size
width="100%" // width: 100%
maxWidth={500} // maxWidth: 500px
/>
// Combining system props with sx
<Button
variant="primary"
p={3}
m={2}
sx={{
borderRadius: 'full',
'&:hover': {
transform: 'scale(1.05)'
}
}}
>
Enhanced Button
</Button>All styling in Theme UI is theme-aware, automatically looking up values from the theme object and supporting design system constraints.
interface ThemeScale {
/** Design system scale (colors, space, fontSizes, etc.) */
[key: string]: any;
[index: number]: any;
}
interface ThemeLookup {
/** Theme scale reference by key */
scale: string;
/** Property name for CSS output */
property: string;
/** Transform function for values */
transform?: (value: any, scale: ThemeScale) => any;
}Usage Examples:
// Theme scales
const theme = {
colors: {
primary: '#007acc',
secondary: '#ff6b6b',
text: '#333',
background: '#fff'
},
space: [0, 4, 8, 16, 32, 64, 128, 256],
fontSizes: [12, 14, 16, 20, 24, 32, 48, 64],
radii: {
none: 0,
sm: 2,
md: 4,
lg: 8,
full: 9999
}
}
// Automatic theme lookups
<Box sx={{
color: 'primary', // theme.colors.primary
bg: 'secondary', // theme.colors.secondary
p: 3, // theme.space[3] = 16px
fontSize: 4, // theme.fontSizes[4] = 24px
borderRadius: 'md', // theme.radii.md = 4px
boxShadow: 'card' // theme.shadows.card
}} />
// Fallback to raw values when not in theme
<Box sx={{
color: '#custom', // Raw hex color
padding: '1rem', // Raw CSS value
fontSize: '18px' // Raw pixel value
}} />interface SxProp {
sx?: ThemeUIStyleObject;
}
interface ThemeUIStyleObject {
[property: string]: ResponsiveStyleValue<any>;
}
type ResponsiveStyleValue<T> = T | Array<T | null | undefined>;
interface CSSObject {
[property: string]: any;
}
interface ThemeUICSSObject extends CSSObject {
[property: string]: ResponsiveStyleValue<any>;
}
interface SystemProps {
m?: ResponsiveStyleValue<string | number>;
margin?: ResponsiveStyleValue<string | number>;
mt?: ResponsiveStyleValue<string | number>;
mr?: ResponsiveStyleValue<string | number>;
mb?: ResponsiveStyleValue<string | number>;
ml?: ResponsiveStyleValue<string | number>;
mx?: ResponsiveStyleValue<string | number>;
my?: ResponsiveStyleValue<string | number>;
p?: ResponsiveStyleValue<string | number>;
padding?: ResponsiveStyleValue<string | number>;
pt?: ResponsiveStyleValue<string | number>;
pr?: ResponsiveStyleValue<string | number>;
pb?: ResponsiveStyleValue<string | number>;
pl?: ResponsiveStyleValue<string | number>;
px?: ResponsiveStyleValue<string | number>;
py?: ResponsiveStyleValue<string | number>;
color?: ResponsiveStyleValue<string>;
bg?: ResponsiveStyleValue<string>;
backgroundColor?: ResponsiveStyleValue<string>;
fontSize?: ResponsiveStyleValue<string | number>;
fontFamily?: ResponsiveStyleValue<string>;
fontWeight?: ResponsiveStyleValue<string | number>;
lineHeight?: ResponsiveStyleValue<string | number>;
width?: ResponsiveStyleValue<string | number>;
height?: ResponsiveStyleValue<string | number>;
minWidth?: ResponsiveStyleValue<string | number>;
maxWidth?: ResponsiveStyleValue<string | number>;
minHeight?: ResponsiveStyleValue<string | number>;
maxHeight?: ResponsiveStyleValue<string | number>;
}
interface Breakpoints extends Array<string> {
[key: string]: string;
}