# How createTheme and createSpacing Shape the Material-UI Design System

> Explore how createTheme and createSpacing build Material-UI's design system. Learn how these functions assemble a unified theme and generate spacing utilities for consistent design.

- Repository: [MUI/material-ui](https://github.com/mui/material-ui)
- Tags: internals
- Published: 2026-02-26

---

**The `createTheme` and `createSpacing` functions form the architectural backbone of Material-UI's theming system, with `createTheme` assembling breakpoints, palette, and shape into a centralized theme object while `createSpacing` generates a flexible utility function that converts design tokens into consistent 8dp-based pixel values.**

Material-UI's visual language depends on a centralized theme object that governs every component's spacing, color, and layout behavior. In the `mui/material-ui` repository, these two factories construct the design system programmatically, ensuring that values like margins and breakpoints remain consistent across your entire application.

## What Is createTheme?

The `createTheme` function in [`packages/mui-system/src/createTheme/createTheme.js`](https://github.com/mui/material-ui/blob/main/packages/mui-system/src/createTheme/createTheme.js) serves as the primary entry point for constructing a complete theme object. It orchestrates the assembly of various design tokens and utilities into a single cohesive structure that can be consumed by the `ThemeProvider`.

### Theme Composition and Deep Merging

At its core, `createTheme` accepts a user-supplied `options` object containing overrides for `breakpoints`, `palette`, `spacing`, `shape`, and other fields (lines 10-18). The function then employs `deepmerge` to combine these user preferences with generated sub-theme pieces, establishing the base MUI theme structure (lines 22-31). This merging strategy ensures that partial customizations inherit sensible defaults while allowing complete override of any theme property.

### Sub-Theme Generation

The factory delegates specialized theme creation to dedicated constructors:

- **Breakpoints** are generated via `createBreakpoints` (line 19), establishing the responsive grid system.
- **Spacing** is constructed through `createSpacing` (line 20), which is detailed in the following section.
- **Shape** tokens like `borderRadius` are incorporated from [`packages/mui-system/src/createTheme/shape.d.ts`](https://github.com/mui/material-ui/blob/main/packages/mui-system/src/createTheme/shape.d.ts).

### SX Prop and Container Query Integration

Beyond static tokens, `createTheme` configures dynamic styling capabilities. The function invokes `cssContainerQueries` to enrich the theme with CSS container-query utilities (line 33), future-proofing layouts for modern responsive design. It also exposes `applyStyles` (line 35), a helper that allows components to apply JSS style objects directly onto the theme.

Most critically, the theme receives `unstable_sxConfig` (default configuration plus any overrides) and a bound `unstable_sx` function that forwards to `styleFunctionSx` (lines 39-48). This integration enables the ubiquitous `sx` prop across all MUI components.

## How createSpacing Builds the Spacing System

Located in [`packages/mui-system/src/createTheme/createSpacing.ts`](https://github.com/mui/material-ui/blob/main/packages/mui-system/src/createTheme/createSpacing.ts), the `createSpacing` factory generates the `theme.spacing` utility that powers margins, paddings, and layout rhythm throughout the design system.

### The 8dp Grid Foundation

By default, Material-UI adheres to Material Design layout guidelines using an **8dp (8px) grid** (lines 30-33). The spacing function multiplies input values by this base unit, so `theme.spacing(2)` returns `"16px"`. Developers can customize this grid by passing a number (e.g., `spacing: 4` for a 4px grid) or a custom transformation function to `createTheme`.

### CSS Shorthand Syntax Support

Unlike static tokens, `createSpacing` returns a **function** that overloads multiple call signatures to mimic CSS shorthand syntax (lines 15-25):

- **0 arguments**: Returns the base unit string.
- **1 argument**: Returns the transformed value (e.g., `spacing(2)` → `"16px"`).
- **2-4 arguments**: Returns space-separated pixel strings (e.g., `spacing(1, 2)` → `"8px 16px"`).

The implementation passes raw values through `createUnarySpacing` (lines 33-36), a transformer that handles number-to-pixel conversion and custom unit logic. Numbers are converted to pixel strings, while string values pass through directly, and all parts are joined by spaces to emulate CSS shorthand (lines 54-58).

### Runtime Validation

During development, `createSpacing` includes defensive programming. If a developer supplies more than four arguments—violating CSS shorthand conventions—the function issues a console warning (lines 42-48), preventing subtle layout bugs.

## Integration: How They Work Together

`createTheme` plugs the `createSpacing` output into the theme object at line 20, making it available as `theme.spacing` throughout the component tree. This integration means that all layout components—**Grid**, **Box**, **Stack**, and any element using the `sx` prop—share the same spacing logic.

Because the spacing function is generated once per theme instance, global changes to the grid system propagate automatically. Changing `spacing: 4` to `spacing: 8` in your theme configuration instantly doubles all spacing values across the entire UI without modifying individual components.

## Practical Examples

Create a custom theme with a 4px spacing grid and rounded corners:

```tsx
// theme.ts
import { createTheme } from '@mui/material/styles';

const theme = createTheme({
  spacing: 4,  // Overrides default 8dp grid
  palette: {
    primary: { main: '#1976d2' },
  },
  shape: {
    borderRadius: 12,
  },
});

export default theme;

```

Consume the spacing function in a component:

```tsx
// Component.tsx
import Box from '@mui/material/Box';
import { useTheme } from '@mui/material/styles';

function SpacedBox() {
  const theme = useTheme();

  return (
    <Box
      sx={{
        // Generates "4px 8px" (margin shorthand)
        m: theme.spacing(1, 2),
        // Generates "12px" (3 × 4px base)
        p: theme.spacing(3),
      }}
    >
      Content with theme-aware spacing
    </Box>
  );
}

```

Provide the theme to your application:

```tsx
// App.tsx
import { ThemeProvider } from '@mui/material/styles';
import theme from './theme';
import SpacedBox from './Component';

function App() {
  return (
    <ThemeProvider theme={theme}>
      <SpacedBox />
    </ThemeProvider>
  );
}

```

## Summary

- **`createTheme`** in [`packages/mui-system/src/createTheme/createTheme.js`](https://github.com/mui/material-ui/blob/main/packages/mui-system/src/createTheme/createTheme.js) acts as the central factory, merging user options with generated breakpoints, spacing, and shape tokens using `deepmerge`.
- **`createSpacing`** in [`packages/mui-system/src/createTheme/createSpacing.ts`](https://github.com/mui/material-ui/blob/main/packages/mui-system/src/createTheme/createSpacing.ts) produces a flexible function supporting 0-4 arguments, converting design tokens into pixel values based on an 8dp grid.
- The **SX prop system** is configured within `createTheme` through `styleFunctionSx`, enabling ad-hoc styling with full theme access.
- **Container-query support** is added via `cssContainerQueries`, allowing components to respond to container rather than viewport dimensions.
- Both functions work in concert to ensure that spacing, color, and layout values remain consistent and type-safe across the entire component tree.

## Frequently Asked Questions

### What is the default spacing base in Material-UI?

According to the source code in [`packages/mui-system/src/createTheme/createSpacing.ts`](https://github.com/mui/material-ui/blob/main/packages/mui-system/src/createTheme/createSpacing.ts) (lines 30-33), the default spacing grid is based on an **8dp (8px) step**, aligning with Material Design specifications. When you call `theme.spacing(1)`, it returns `"8px"`. You can override this by passing a number or custom transformation function to the `spacing` property in `createTheme`.

### How does createTheme merge custom values with defaults?

`createTheme` utilizes `deepmerge` (lines 22-31 in [`createTheme.js`](https://github.com/mui/material-ui/blob/main/createTheme.js)) to recursively combine user-provided options with the base theme structure. This approach ensures that you can override specific nested properties—such as `palette.primary.main`—without losing other default palette values. Additional theme fragments passed as extra arguments are also deep-merged on top of the base theme.

### Can theme.spacing accept string values or custom units?

Yes. The `createSpacing` implementation passes all values through `createUnarySpacing` (lines 33-36), which handles both numbers and strings. If you pass a string like `"2rem"`, it returns that value directly without pixel conversion. This allows teams to adopt rem-based spacing or other CSS units while maintaining the same functional API.

### What happens if I pass more than four arguments to theme.spacing?

During development, the spacing function validates its argument count (lines 42-48 in [`createSpacing.ts`](https://github.com/mui/material-ui/blob/main/createSpacing.ts)). If you supply more than four arguments—violating CSS shorthand syntax—the function issues a `console.error` warning that the Material-UI spacing API supports zero to four arguments. In production builds, this validation is typically stripped to reduce bundle size.