Material-ui: Definition order in style object breaks component functionality

Created on 17 Feb 2019  ·  5Comments  ·  Source: mui-org/material-ui

  • [x] This is not a v0.x issue.
  • [x] I have searched the issues of this repository and believe that this is not a duplicate.

Expected Behavior 🤔

Order shouldn't matter when defining the style object, should it?

Current Behavior 😯

Order of definition results in different behavior.

Steps to Reproduce 🕹

  1. Go to: https://codesandbox.io/s/5yjzpym1zp
  2. Notice that the arrow-button correctly expands and minimizes the sidebar.
  3. In the styles definition of src/index.js, swap the order of the two fields.
  4. Notice that the sidebar is no longer correctly minimized/expanded (it stays expanded all the time).

More specifically:

Working:

const useStyles = makeStyles({
  drawer: { width: 250 },
  drawerClose: { width: 48 }
});

Broken:

const useStyles = makeStyles({
  drawerClose: { width: 48 },
  drawer: { width: 250 }
});

Notice that this isn't about the order of the CSS rules, but about the order of the objects that end up mapped to className strings.

If drawerClose is defined after drawer, it's all good.
If drawerClose is defined before drawer, the functionality gets broken.

Environment

From the package.json of the CodeSandbox example:

"@material-ui/core": "^3.9.2",
"@material-ui/icons": "3.0.2",
"@material-ui/styles": "3.0.0-alpha.10",
"react": "^16.8.2",
"react-dom": "^16.8.2",

Tested on Chrome & Firefox, Windows 10.

question

All 5 comments

@dandrei Yes, the style rules are injected in the same order as they are defined. CSS specificity makes the last injected rule win. The order matters, a lot.

Alternatively, you can do:


const useStyles = makeStyles({
  drawer: {
    width: open => (open ? 250 : 48)
  }
});

export default () => {
  const [open, setOpen] = useState(true);
  const { drawer } = useStyles(open);

https://codesandbox.io/s/xl1zk3xmnz

Thanks, that does work and I didn't know about being able to send parameters to useStyles. It's extremely handy.

In my own example, why would the order they're defined in matter, if they're being applied in an order we define? e.g.

classes={{ paper: classNames(drawer, !open && drawerClose) }}

We're still applying drawerClose after drawer, no?

I'm sure I'm missing something about the way this is implemented under the hood, but in old school CSS, the order in which you'd define the classes wouldn't matter, just how you applied them to elements. I'm guessing this is no longer the case here?

Edit:

I wrote:

in old school CSS, the order in which you'd define the classes wouldn't matter, just how you applied them to elements.

Nope, turns out that wasn't the case.

Given these classes:

.red {
  color: red;
}

.blue {
  color: blue;
}

Which color would these divs be?

<div class="red blue">
<div class="blue red">

I could have sworn the first one would be blue and the second one red, but I went ahead and tested it and they were both blue. Turns out I've been misunderstanding CSS for at least a decade 😂

Thanks for taking the time to clear this out, it makes sense now.

@dandrei I'm happy to help 🙆‍♂️.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

chris-hinds picture chris-hinds  ·  3Comments

newoga picture newoga  ·  3Comments

revskill10 picture revskill10  ·  3Comments

ryanflorence picture ryanflorence  ·  3Comments

zabojad picture zabojad  ·  3Comments