Material-UI makeStyles, useStyles, createStyles, and withStyles Explained

Styling hooks in Material-UI are an effective and exceptional tool for customizing components. However, the similarly-named hooks can be confusing to use.

In this post, I’ll explain what each hook does, when to use it, and which hooks are recommended for certain situations.

***MUI 5 UPDATE: There is a new styling system in MUI 5. I have updated this post with information about the new styling system.

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

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

x
Material UI Styles Explained: makeStyles, useStyles, withStyles, and createStyles

Material-UI withStyles

React had not yet introduced hooks back when Material-UI 3 was first released. Higher-order components were still a common method of adding functionality to base components.

Material-UI withStyles was the primary method for wrapping a component and passing style props to it. It is still a valid method to use today if for some reason you are still using higher-order components or still using React lifecycle methods.

However, it is not the ideal method. Preferably, you are using React hooks and the MUI makeStyles hook (more on that below). Another recommended method of component styling is to use StyledComponents. Here’s a very basic example of creating a StyledComponent.

Below is an example of using withStyles:

Material-UI withStyles Example
Material-UI withStyles
const styles = {
  root: {
    borderRadius: 12,
    backgroundColor: "blue"
  }
};

function HOCComponent(props) {
  const { classes } = props;
  return (
    <Button variant="contained" className={classes.root}>
      Higher-Order Button
    </Button>
  );
}

HOCComponent.propTypes = {
  classes: PropTypes.object.isRequired
};

export default withStyles(styles)(HOCComponent);

In my opinion, this is more confusing and verbose than the newer makeStyles hook.

Material-UI makeStyles

***UPDATE makeStyles is still supported in MUI 5 but is considered “legacy”. There is a new styling system. It is actually really easy to use and requires less code. I highly recommend taking a look.

The makeStyles hook is the current (V4) “proper” way to create styles for components. The underlying logic is the same as withStyles according to the docs.

There’s one less import needed for makeStyles compared to withStyles (not shown in my code below). It’s also a few lines less of code and more readable in my opinion.

Material-UI makeStyles Example
Material-UI makeStyles
const useStyles = makeStyles({
  root: {
    borderRadius: 12,
    backgroundColor: "blue"
  }
});

function HookComponent(props) {
  const classes = useStyles();
  return (
    <Button variant="contained" className={classes.root}>
      Hook Button
    </Button>
  );
}

export default HookComponent;

Importantly, makeStyles can be passed parameters to make styling dynamic. For example, I passed a prop for height in order to position a Material-UI Drawer inside a container in the linked article.

Material-UI’s styles can also be used in React applications independently of the rest of the MUI package. If you export @material-ui/core/styles it will include a default theme; @material-ui/styles will not.

Material-UI useStyles

In the docs we find detailed explanations of different styling syntax, and we always see makeStyles paired with useStyles. However, we never get an explanation of useStyles.

useStyles is simply the naming convention of the hook created and returned by makeStyles. useStyles definitely is a hook; try calling it outside of the function component and you will get an error.

useStyles can be used to pass params to makeStyles, as mentioned above.

Material-UI createStyles

createStyles is perhaps the most interesting of the four topics in this post because it is a fix to make TypeScript play nicely with MUI.

“Its only purpose is to defeat TypeScript‘s type widening when providing style rules to makeStyles/withStyles which are a function of the Theme.”

MUI Docs

The docs even mention that the createStyles function doesn’t do anything at runtime.

The docs go into a pretty long explanation here. Suffice to say, I appreciate that the MUI team came up with a quick way to appease TypeScript.

Here’s example usage from the docs quoted above:

const useStyles = makeStyles((theme: Theme) => createStyles({
  root: {
    backgroundColor: theme.color.red,
  },
}));

MUI 5 ‘sx’ Prop, styled() API, and the Styling System

MUI 5 offers a new styling system that has many advantages:

  • Less boiler-plate code
  • All CSS attributes and all MUI style shorthands are accessible in one prop
  • Easier access to the MUI theme
  • Easier responsive styling with breakpoints

While it can be a headache to switch, the MUI team created some great documentation. Furthermore, I think the new system has some great benefits.

You can read my detailed guide to the sx prop here, and my essential guide to the styled() API here. The sx prop is meant for quick local styling, while the styled() API is intended for creating components for reuse and export. Furthermore, the styled() API should be familiar to developers who have used the styled-components library.

How to use makeStyles in MUI v5

My article “The Ultimate Guide to Material-UI Grid Containers and Items (MUI v5)” has a direct comparison of how to style the root of a Grid using makeStyles and how to style using the sx prop. I pasted the significant code differences below:

//makeStyles

import { makeStyles } from "@mui/styles";

const useStyles = makeStyles({
  root: {
    backgroundColor: "blue",
    paddingBottom: 16,
    paddingRight: 16,
    marginTop: 16,
    marginLeft: "auto",
    marginRight: "auto",
    maxWidth: 500
  }
});

export default function FullWidthGrid() {
  const classes = useStyles();
  return (
    <>
      <Grid
        container
        className={classes.root}
    //Additional JSX
      </Grid>
  );
}



//sx prop

const gridStyles = {
  backgroundColor: "blue",
  paddingBottom: 2,
  paddingRight: 2,
  marginTop: 2,
  marginLeft: "auto",
  marginRight: "auto",
  maxWidth: 500
};

export default function FullWidthGrid() {
  const classes = useStyles();
  return (
    <>
      <Grid
        container
        sx={gridStyles}
    //Additional JSX
      </Grid>
  );
}

The primary change in MUI v5 for makeStyles is that now it is imported using import { makeStyles } from "@mui/styles"; . Notice also that it does not plug directly into the system values. For example, I had to use paddingRight: 16 with makeStyles, but I was able to use paddingRight: 2 with the sx prop.

Resources

Are you looking for training in Material-UI? Check out my review of the best Material-UI course in Udemy, which has 40+ hours of content and a 30-day money back guarantee.

Code Sandbox Link

Share this post:

Leave a Comment

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