How createTheme and createSpacing Shape the Material-UI Design System

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 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.

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, 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:

// 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:

// 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:

// 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 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 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 (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) 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). 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.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →