The Ultimate Guide to the MUI ‘sx’ Prop

Material-UI (rebranded as MUI) recently released version 5, and there were significant changes to the syntax and systems used for styling components.

Material-UI v4 relied on JSS and the makeStyles hook for component styling. MUI v5 has migrated to two options: styled API or sx API (<- definitely read this). The styled API creates a new component that can easily be exported, and usage of the component is very clean with less inline prop code. The sx prop is a superset of CSS that include built-in shorthands (i.e. mt={2} sets margin-top).

Both of the new APIs offer the following advantages over makeStyles:

  • One less import: the @material-ui/core/styles import is no longer needed
  • Less boiler-plate code: the makeStyles() and useStyles syntax are no longer needed and it results in several fewer lines of code written for each component
  • Better abstraction: sx and styled both offer unique abstractions that simplify your code. sx requires less code to do more styling, while styled offers simplified reusability. I’ll explain this in-depth in the last section

Read my guide to the new styled() API here.

makeStyles is still supported, but it is deprecated. If you want to use it, it now requires the @mui/styles import. Read my guide to makeStyles, useStyles, withStyles, and createStyles here.

A Code Sandbox link with full React code is in the Resources section.

Watch the YouTube version of this article or watch the embedded video below.

The Ultimate Guide to the MUI 'sx' ...
The Ultimate Guide to the MUI 'sx' Prop

The Purpose of the SX Prop

Since MUI 5 created a new styling API, the primary questions to ask are “What is the sx prop and why should I use it?”. The docs explain it simply:

The `sx` prop is a shortcut for defining custom style that has access to the theme.

MUI sx prop docs

The sx prop simply requires very little code to accomplish lots of styling.

  • Superset of CSS – sx can accept all CSS attributes (using JSS syntax) and it can accept all values from the “MUI System“. This is a vague name for their extensive list of rapid styling shortcuts.
  • As mentioned above, it reduced the amount of code required for styling by getting rid of the makeStyles hook
  • Theme aware – theme values can be accessed quickly. sx={{ zIndex: 'modal' }} is accessing theme.zIndex.modal.
  • Easy responsive styling – properties in sx can accept an object of with breakpoints as the key and CSS values as the values (an example is in the next section)

Example Code for the New MUI 5 SX Prop

I created the below TextField components only using styles passed to the sx prop. The first is the ‘filled’ variant and the second is the ‘standard’ variant.

Material-UI TextField with sx prop

In each section below I’ll break down the different aspects of the styling code in the sx props of these TextFields.

import * as React from "react";
import TextField from "@mui/material/TextField";
import { SxProps } from "@mui/material/styles";

const style = {
  mt: 2,
  ml: 2,
  width: { sm: 200, md: 300 },
  backgroundColor: { xs: "secondary.light", sm: "#0000ff" },
  boxShadow: 6
};

export default function CustomStyledTextField() {
  return (
    <>
      <TextField
        sx={{
          ...style,
          mb: 2,
          mr: 2,
          border: "solid black 2px",
          "& .MuiFilledInput-input": { color: "white" }
        }}
        id="standard-basic"
        label="Filled"
        variant="filled"
      />
      <TextField
        sx={{
          ...style,
          "& .MuiOutlinedInput-root::before": {
            content: `"$"`
          },
        }}
        id="standard-basic"
        label="standard"
        variant="outlined"
      />
    </>
  );
}

(Here’s a guide to adding box shadow to MUI components)

Extracting Shared Styles With Consts and Object Destructuring

An important syntax option available in es6 is object destructuring. It gives us a quick way to extract shared styles to a constant that can be reused.

const style = {//shared styling goes here}

sx={{
  ...style,
  mb: 2,
  mr: 2,
  //etc
}}

Both of the TextFields have common styling. We certainly don’t want to copy/paste code, se we extract it. In the sx prop after destructuring the style const, simply include any additional styling specific to that TextField.

Superset and CSS Values in MUI SX

Below are some of the values in the ‘filled’ variant.

mb: 2, //System
mr: 2, //System
border: "solid black 2px" //CSS

mb is margin-bottom and mr is margin-right. These are shorthands available in the “MUI System”. Next is border, which is standard CSS. These properties coexist and are equally viable in the sx prop. This is why the prop is a ‘superset’ of CSS: all CSS values are valid, plus additional values from MUI’s styling system are valid.

Breakpoints in MUI SX

See 5 more examples of MUI sx breakpoints here.

Breakpoints in the sx prop are actually objects within a style value that map to theme breakpoints.

backgroundColor: { xs: "secondary.light", sm: "#0000ff" }

The xs and sm above have values of 0 and 600, respectively, in my code. These are the default values of the MUI theme object’s breakpoints. These can be customized.

Theme in MUI SX

In the breakpoints code above, notice the xs value: "secondary.light". This is shorthand for theme.palette.secondary.light.

Even the way I accessed the breakpoints is a shorthand for accessing theme.breakpoints.values.xs (or .sm).

This screenshot from the MUI v5 theme object docs shows all the different theme values that can be quickly accessed using the sx prop.

MUI sx Theme
MUI sx Theme

Styling Nested Components with SX

One of my favorite aspects of the sx component is that it has the capability to use complex CSS selectors.

"& .MuiFilledInput-input": { color: "white" }

This selects children elements with class .MuiFilledInput-input.

The TextField is composed of several components, which means in the DOM it is composed of several elements. It’s important to know that sx styles are applied to the topmost element possible in the DOM.

Material-UI sx prop nested selectors

The screenshot couldn’t quite capture all the styling, but further down in the list of stylings we would see the styles we gave to the sx prop. They are all applied to the root div of the TextField. A child element further down in the DOM has class .MuiFilledInput-input.

MUI SX Pseudo Selectors (‘before’ and ‘hover’)

See 4 examples of hover in MUI sx here.

I created a complex selector that applies a special character to the ::before pseudo-element of the Input element of outlined variant TextFields.

sx={{
  ..styles,
  "& .MuiOutlinedInput-root::before": {
     content: `"$"`
  }
}}

Notice the double colon. This is new in CSS3 to distinguish between pseudo-elements and pseudo-classes. If I was adding hover, it would have only a single colon like "& .MuiOutlinedInput-root:hover". I would also target the fieldset element, and you can see exactly how I add hover to the TextField with MUI sx here.

Read about changing MUI TextField border color on focus, disabled, and more here.

SxProps: TypeScript Typing for the MUI `sx` Prop

Special thanks to reader “AC” who reminded me to include TypeScript typing in this post. If you are using TypeScript, you need typing for your sx prop values if you abstract them to a constant. Here’s an example:

import { SxProps } from "@mui/system";

const style: SxProps = {
  mt: 2,
  ml: 2,
  width: { sm: 200, md: 300 },
  backgroundColor: { xs: "secondary.light", sm: "#0000ff" },
  boxShadow: 6
};

The style const would be passed to the sx prop in the JSX.

Interestingly, the docs recommend (or used to recommend) a different import:

import { SxProps } from '@mui/material/styles';

I got an error that this was an invalid import when I tried it in CodeSandbox. Others have gotten this error as well.

At the time of writing this post, I recommend importing from "@mui/system".

MUI SX API vs MUI Styled() API

If you’ve upgraded to MUI 5 and are wondering which of the two styling options are better, review this rundown of relative strengths:

styled API:

  • With styled, You get to write CSS….using CSS syntax. sx still uses JSS because it lives in JSX world.
  • styled is a simpler abstraction. In this example, all the Root component code is pulled out of the JSX. In practice, it should be in its own file and the Root component would simply be imported where needed. Similar abstraction can be accomplished with sx but it’s not the purpose of the sx API.
  • The styled library is a popular library with about 3 million weekly downloads (Sept 2021). Many devs will be familiar with it.

sx API:

  • It can be passed typical CSS attributes as well as all in-house MUI spacing shorthands (see the list here)
  • It simplifies access to the theme, i.e. 'primary.main' instead of theme.palette.primary.main.
  • Responsive styling is incredibly easy and requires very little code

Resources

This MUI v5 tutorial shows an app created with both styling APIs.

Learn how MUI uses Emotion to support the sx prop.

Code Sandbox Link

MUI sx prop docs

The MUI ‘system’ docs

Share this post:

7 thoughts on “The Ultimate Guide to the MUI ‘sx’ Prop”

  1. Excellent, I was looking for updated information since I was using makestyles with mui 5 and it was not working for me, I see why, thank you very much.

    Reply
  2. if you are on tsx (typescript) files, ensure you do it as

    import { SxProps } from ‘@mui/material’
    ..

    const style = {
    mt: 2,
    ml: 2,
    width: { sm: 200, md: 300 },
    backgroundColor: { xs: “secondary.light”, sm: “#0000ff” },
    boxShadow: 6
    } as SxProps;

    Reply
  3. styled isn’t *really* supported – React 18 breaks LOTS of things and they will NOT fix them. So if you want React 18 goodness, then you have to migrate or use something like tss-react (even there there is lots that isn’t implemented, so still lots of work to do…)

    Reply

Leave a Comment

This site uses Akismet to reduce spam. Learn how your comment data is processed.