Material UI Overriding styles with increased specificity
Asked Answered
L

2

5

How can I override a rule of a class which has high specificity?

For example, the .MuiAccordionSummary-content.Mui-expanded class in the AccordionSummary

const useStyles = makeStyles(() => ({
    expanded: {
        marginBottom: 0,
    },
}));

in combination with:

<AccordionSummary classes={{
    expanded: classes.expanded,
}}/>

is applied but overridden.

Note: marginBottom: '0 !important' works, but doesn't feel like an optimal solution.

Lioness answered 14/9, 2020 at 8:36 Comment(0)
P
15

You could use global overrides to change the default margin of the AccordionSummary. However, this will affect all AccordionSummary components in your application.

The better approach (the one you are already using) is to wrap the component and alter its classes. If you look into the source of the AccordionSummary, you will find that the expanded property is an empty block. The margin gets set by the referencing selector in the content property:

    content: {
      display: 'flex',
      flexGrow: 1,
      transition: theme.transitions.create(['margin'], transition),
      margin: '12px 0',
      '&$expanded': {
        margin: '20px 0',
      },
    },

If you add the same reference in your custom styles, the priority becomes higher and you won't need !important. You will have to add the expanded className to your custom styles though:

import React from 'react';
import makeStyles from '@material-ui/core/styles/makeStyles'
import Accordion from '@material-ui/core/Accordion';
import AccordionDetails from '@material-ui/core/AccordionDetails';
import AccordionSummary from '@material-ui/core/AccordionSummary';

const useStyles = makeStyles(() => ({
  expanded: {},
  content: {
    '&$expanded': {
      marginBottom: 0,
    },
  },
}));

const MyAccordion = ({ summary, details }) => {
  const classes = useStyles();

  return (
    <Accordion>
      <AccordionSummary classes={{ content: classes.content, expanded: classes.expanded }}>
        {summary}
      </AccordionSummary>
      <AccordionDetails>
        {details}
      </AccordionDetails>
    </Accordion>
  )
};

export default MyAccordion;
Panlogism answered 14/9, 2020 at 9:20 Comment(3)
Ty, it works! The empty "expanded" class seems a bit odd though.Lioness
I agree, but it is a common pattern of "modifier classNames" in the material-ui repository.Panlogism
If you don't want the empty expanded: {} style rule, the $expanded pseudo class transforms into .Mui-expanded - so you can use that instead without the empty classes - though not quite sure I understand why having it there makes $expanded workSchopenhauer
R
0

If you are using material-ui v5+ with tss-react then you can use the & to increase specificity of CSS declarations as follows:

import { makeStyles } from 'tss-react/mui';

const useStyles = makeStyles()(() => ({
    expanded: {
      '&&':{
        marginBottom: 0,
      }
    },
}));

The more & used, the higher the specificity and the chance to override other styles.

Read more: https://docs.tss-react.dev/increase-specificity

Rolle answered 25/9 at 11:20 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.