How to use conditional styles with MUI v5 using emotion styled

Viewed 2646

I'm migrating from MUI v4 to v5. In v4 I was using clsx with TextField to add conditional styles.

export const useStyles = makeStyles((theme: Theme) =>
  createStyles({
    root: {
      // ...
    },
    valid: {
      "& fieldset": {
        borderColor: theme.palette.success.main,
        borderWidth: 2
      }
    }
  })
);

const classes = useStyles();
<TextField
  {...props}
  className={clsx(classes.root, { [classes.valid]: isValid })}
/>

I'm trying to find a similar approach in MUI v5. Is there any alternative for conditional styles in MUI v5 other than with clsx and makestyles.

Let me know if more information is required.

2 Answers

There are multiple ways to do that:

1. Conditional operator

Use this if you want to conditionally set a property based on a boolean value.

const Box1 = styled(Box, {
  shouldForwardProp: (prop) => prop !== "showBorder"
})(({ showBorder }) => ({
  border: showBorder ? "solid red 5px" : "none"
}));
<Box1 />
<Box1 showBorder />

2. Dictionary

Use this if you want to conditionally set a property based on multiple values.

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

const colors = {
  hauntedForest: "#0b5b38",
  redLust: "#b20608",
  spaceExplorer: "#1244a1",
  default: "#000000"
};

const Box2 = styled(Box, {
  shouldForwardProp: (prop) => prop !== "variant"
})(({ variant }) => ({
  backgroundColor: colors[variant] ?? colors.default,
  border: "5px solid " + darken(colors[variant] ?? colors.default, 0.3)
}));
<Box2 variant="hauntedForest" />
<Box2 variant="redLust" />
<Box2 variant="spaceExplorer" />
<Box2 />

3. Short-circuit evaluation + Spread operator

Use this if you want to conditionally set multiple properties.

const Box3 = styled(Box, {
  shouldForwardProp: (prop) => prop !== "isFancy" && prop !== "isFancyBorder"
})(({ theme, isFancy, isFancyBorder }) => ({
  ...(isFancy && {
    borderRadius: theme.shape.borderRadius,
    boxShadow: "0 4px 6px gray, 0 1px 3px rgba(0, 0, 0, 0.08)",
    backgroundImage: "linear-gradient(90deg, #be5af7, #165b91)"
  }),
  ...(isFancyBorder && {
    backgroundColor: "transparent",
    border: "5px solid transparent",
    borderImage: "linear-gradient(90deg, #be5af7, #165b91)",
    borderImageSlice: 1
  })
}));
<Box3 isFancy />
<Box3 isFancyBorder />

All of the methods above can also be applied when using sx props since they use JS object to describe the styles.

Live Demo

Codesandbox Demo

This seem to work for me

Using sx

sx={{ px: variable ? 8 : null }}

sx with breakpoint

sx={{ px: { md: variable ? 8 : null } }}

prop

 <Typography align={variable ? 'center' : 'inherit'}>

Using className

    className={ variable ||'class-name'}
Related