Search code examples
reactjsmaterial-uistyled-components

Setting priority between MUI System Props and Styled Components


When using Styled Components with MUI System Props I found that the styled component styling takes precedence, for example in the snippet below the box would render with justify content set as space-around:

const CustomBox = styled(Box)(() => ({
  display: 'flex',
  justifiyContent: 'center'
}));

function MyComponent() (
  <CustomBox justifyContent='space-around'>
    <span className='some-icon'></span>
    <span>some text</span>
  </CustomBox>
)

I could manage this "the styled components way" and pass a prop to CustomBox, but I find it counter-intuitive that the MIUI system prop looks like a local override, but is overriden by the component it's being applied to.

Is there some configuration available in MUI that would make MUI System Props take precedence over Styled Components stylings?


Solution

  • If you want the props passed to the CustomBox to win over your style overrides, then you should take the props into account in your styling:

    import * as React from "react";
    import Box from "@mui/material/Box";
    import { styled } from "@mui/material/styles";
    const CustomBox = styled(Box)(({ display, justifyContent }) => ({
      display: display === undefined ? "flex" : display,
      justifyContent: justifyContent === undefined ? "center" : justifyContent
    }));
    export default function BoxSx() {
      return (
        <>
          <CustomBox>
            <span>Span 1 - no changes</span>
            <span>Span 2 - no changes</span>
          </CustomBox>
          <CustomBox justifyContent="space-around">
            <span>Span 1 - justifyContent="space-around"</span>
            <span>Span 2 = justifyContent="space-around"</span>
          </CustomBox>
          <CustomBox
            justifyContent="space-around"
            sx={{ justifyContent: "space-between" }}
          >
            <span>Span 1 - sx justifyContent="space-between"</span>
            <span>Span 2 = sx justifyContent="space-between"</span>
          </CustomBox>
          <CustomBox display="none">
            <span>Span 1 - display="none"</span>
            <span>Span 2 - display="none"</span>
          </CustomBox>
        </>
      );
    }
    

    Edit CustomBox

    As far as why the props don't automatically take precedence -- the props change the default styling for the Box and that default styling is what the styled API is then overriding. Since the styled API gives you access to those props, it allows you to decide how those props interact with your styling.

    In contrast, the sx prop provides styles that are applied with a different precedence than the default styles, so providing justifyContent within sx wins over both the props and styles provided via styled.