When to use the MUI ‘sx’ Prop, Styled API, or Theme Override

Material-UI offers several different APIs or systems for styling components. It can be difficult to know which is the right to use from a clean code perspective. In this post I will explain the similarities and differences between sx, styled, and theme overrides in MUI.

Here’s an important point: all three styling options can accomplish the same goals from a technical perspective. However, choosing which to use has a ‘right’ or ‘wrong’ answer based on clean code and good practice standards.

Here’s the short answer for when to use sx, styled, or theme overrides:

  • Use sx for ‘one-time’ styling
  • Create a styled component with the styled API if you need multiple components of the same type to have the same styling
  • Use a theme override if you want ALL of the components of the same type to have the same styling
MUI SX vs Styled Components vs Theme Override
MUI SX vs Styled Components vs Theme Override

Why do I say sx requires the most code in the graphic above? Because if I have three Buttons that all need a green border, and I use sx, I have to write the code three times (or at least pass a const value to three Buttons).

Why is overriding the theme the most abstract? Because after overriding a component in the theme, the code to use the component has not been changed.

In the sections below, I will create the form below and explain the pros and cons of theme overrides, styled components, and sx for different sections of the form. I include full code in each section.

MUI Form with Styled Radio and Buttons
MUI Form with Styled Radio and Buttons

These posts individually explore each styling option:

Watch a video version of this post on YouTube or below (desktop only):

Pros and Cons of the ‘sx’ Prop

The sx prop feels a little bit like inline styling, and a little bit like class styling. It is intended for styling a single component and has replaced makeStyles from Material-UI v4.

sx accomplishes the same things as makeStyles, but requires less boilerplate code. There’s no hook, no import, and no extra variables required. However, it also does not place a custom class name on the component in the DOM, so it doesn’t add a useful selector. In this way, sx is more like inline styling.

Here’s something interesting though: I can style a component with sx and then export it, just like with styled (but it requires more code). I can also create a const with style values and quickly apply this to several components of the same type that need styling. This adds a degree of abstraction.

In the code below, I styled the Paper component with sx. This was the perfect time to use the sx prop because only one component needed this particular styling.

<Paper sx={{ padding: 4, minWidth: 300, boxShadow: 12, backgroundColor: 'rgba(173,255,47,0.2)' }}>

Here’s a summarized pros and cons list for sx:

-Pros:

  • Requires the least code
  • No overhead or boilerplate code
  • Requires the least knowledge of MUI styling systems and syntax
  • ^ Only requires knowledge of CSS
  • Has access to style shorthands such as m (margin shorthand) and p (padding shorthand)

-Cons:

  • It can be considered ‘inline styling’ by some and may be discouraged
  • It is not the best option for extending component styling for reuse
  • It is the least abstract

Full code for the form is below, except for the export file for the StyledRadio component and the custom theme.

import FormLabel from "@mui/material/FormLabel";
import FormControl from "@mui/material/FormControl";
import FormControlLabel from "@mui/material/FormControlLabel";
import FormHelperText from "@mui/material/FormHelperText";
import RadioGroup from "@mui/material/RadioGroup";
import { StyledRadio } from "./StyledRadio";
import Paper from "@mui/material/Paper";
import Stack from "@mui/material/Stack";
import Button from "@mui/material/Button";
import { StyledFormTheme } from "./FormTheme";
import {
    ThemeProvider
} from "@mui/material/styles";

export default function MUIForm() {
    return (
        <ThemeProvider theme={StyledFormTheme}>
            <form>
                <Paper sx={{ padding: 4, minWidth: 300, boxShadow: 12, backgroundColor: 'rgba(173,255,47,0.2)' }}>
                    <FormControl >
                        <FormLabel component="legend" htmlFor="residence-type-radio">
                            Pool Type
                        </FormLabel>
                        <RadioGroup
                            aria-label="pool"
                            id="pool-type-radio"
                            defaultValue="above-ground"
                            name="radio-buttons-group"
                        >
                            <FormControlLabel
                                value="above-ground"
                                control={<StyledRadio />}
                                label="Above Ground"
                            />
                            <FormControlLabel
                                value="in-ground"
                                control={<StyledRadio />}
                                label="In Ground"
                            />
                            <FormControlLabel
                                value="hot-tub"
                                control={<StyledRadio />}
                                label="Hot Tub"
                            />
                        </RadioGroup>
                        {/*I can still use Radio instead of StyledRadio if needed */}
                        <FormHelperText>Pick One</FormHelperText>
                    </FormControl>
                    <Stack direction="row" display="flex" justifyContent="space-around">
                        <Button>Help</Button>
                        <Button>Clear</Button>
                        <Button>Submit</Button>
                    </Stack>
                </Paper>
            </form>
        </ThemeProvider>
    );
}

MUI ‘sx’ Docs

Pros and Cons of Styled Components With the ‘styled’ API

The styled API is used to create “styled components”. These extend an existing component’s styling without permanently changing the original component.

-Pros:

  • Abstract all styling changes and package them into a new component
  • Styled Components” is a common design pattern so many devs will be familiar with it

-Cons:

  • Perhaps requires the most code and new files of any styling pattern
  • Not completely abstract: teammates need to be aware of the ‘new’ component
  • Using the API requires knowledge of it’s syntax

Styled components are often created in their own file and then exported for use throughout an application. In the form demo, I created a StyledRadio component and import it into the MUIForm.tsx file.

import Radio from "@mui/material/Radio";
import {
  styled
} from "@mui/material/styles";

export const StyledRadio = styled(Radio)(({ theme }) => ({
  color: 'green',
  "&.Mui-checked": {
    color: 'green'
  },
  '& svg[data-testid="RadioButtonCheckedIcon"]': {
    color: 'orange'
  }
}));

Pros and Cons of Theme Overrides

Theme overrides are the most abstract of the three options. To override the theme, create a new theme object and apply the desired styles to a particular component field within the theme. Then add a ThemeProvider to your code. Any child components inside the ThemeProvider will inherit the component overrides.

-Pros:

  • The most abstract option. Teammates might use components and not even know they had an overridden theme (this is usually a good thing but can cause problems)
  • The ThemeProvider allows the overridden styles to be applied to specific sections of the app

-Cons:

  • Overriding the theme requires knowledge of theme override syntax
  • It’s so abstract it might cause problems or surprises (i.e. I add a Button and can’t figure out why it doesn’t have default styling)

I created StyledFormTheme and overrode the Button’s root class styles (the root class is automatically applied to all Buttons). In MUIForm.tsx, I wrapped the form in a ThemeProvider and imported StyledFormTheme. All Button components in the form were automatically provided with the below theme values.

import { createTheme } from "@mui/material/styles";

const StyledFormTheme = createTheme({
  components: {
    MuiButton: {
      styleOverrides: {
        root: {
          color: "grey",
          border: '2px solid',
          textDecoration: 'italic',
          minWidth: 75,
          margin: 2
        }
      }
    }
  }
});

export { StyledFormTheme };
Share this post:

8 thoughts on “When to use the MUI ‘sx’ Prop, Styled API, or Theme Override”

    • I’m glad it’s helped! I have a course on Udemy if you want to create a full app and deeply learn MUI styling. It’s called “Advanced Material UI Component Styling: The Complete Course”.

      Reply
    • Hi Alex, thanks for reading. I forgot for this article! However, I did include TS on my DatePicker in my Udemy course. Here’s an example of the onChange handler typing, which I think was the hardest TS part. MUI’s value typing was difficult to use, so I made it what I needed:

      const handleDatePickerChange = (
      value: React.ChangeEvent | null,
      keyboardInputValue?: string | undefined
      ) => {
      const startDate = value as unknown as { month: () => string, date: () => string; year: () => string; };
      setStartDate: `${startDate.month() + 1}/${startDate.date()}/${startDate.year()}`
      }

      Reply
  1. Do you know how using each of these methods will affect performance? I am running into an issue transitioning from mui v4 to v5 where the performance of the app has dropped significantly. I did not use the theme overrides at all, and instead chose to use the styled and sx props as they are the most readable. The performance drop is most notable when I have a large number of components in a form.

    Reply
    • Hi Ben, good question. I don’t directly have an answer, but I would expect SX is faster than MUI v4 makeStyles simply because we no longer have the makeStyles import and useStyles const. Both SX and makeStyles applying styling via injecting a class on the element, so once again I wouldn’t expect a significant slowdown. I have never clocked it so I can’t be sure.

      Reply
    • An update to this question: I found this great post where they ran some performance metrics on different styling options in v5. Here’s the summary:
      SX System: Easy but slow
      Styled Components: Twice as fast as SX and you can still use the theme
      Pure CSS/LESS: Super fast but lacks access to theme

      Reply
  2. Hi Jon, congrats, and thanks for your posts and collaboration to understand MUI’s topics!

    I took your Udemy Advanced Material-UI Component Styling: The Complete Course and it was (is) very helpful.

    I’m on a project using MUI and facing a new challenge: We need to switch between themes, some of our clients need a brandingTheme, let’s say custom palettes and custom login layouts, then we need to switch between our customTheme and the clients brandingTheme.

    What do you think will be the best approach to achieve that goal in order to use MUI’s styling philosophy correctly?

    Thanks a lot in advance!

    Reply
    • Hi Gustavo, thanks for taking the course and I am glad it was helpful! For your question, my best thought on swapping themes would simply be to swap out the theme passed to your app’s theme provider. For example, if alpha client is logged in then your app passes that client’s theme (let’s say alphaTheme) to the ThemeProvider. If beta client is logged in, your app passes betaTheme.

      Reply

Leave a Comment

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