The value of the className property is not the last class name applied to a button.
This seems to be a transpile issue problem because the source code clearly puts the className value last. See: https://github.com/mui-org/material-ui/blob/master/packages/material-ui/src/Button/Button.js#L307
When passing a className property:
<Button variant="contained" color="primary" className="test-class">Test</Button>
The class test-class should be after all the button classes. However it appears before some of the button classes:
<button class="MuiButtonBase-root MuiButton-root MuiButton-contained test-class MuiButton-containedPrimary" tabindex="0" type="button"><span class="MuiButton-label">Test</span><span class="MuiTouchRipple-root"></span></button>
https://codesandbox.io/s/button-classname-issue-bs6m2
Steps:
Note that in Material v3 it works as expected. I was able to reproduce the problem in v4.0.0 and v4.9.5 (I didn't check with intermediate versions).
This seems to be a bug in transpile. The original code from Button (https://github.com/mui-org/material-ui/blob/master/packages/material-ui/src/Button/Button.js#L307https://github.com/mui-org/material-ui/blob/master/packages/material-ui/src/Button/Button.js#L307) is transpiled to this:
return React.createElement(ButtonBase, _extends({
className: clsx(classes.root, classes[variant], className, color === 'inherit' ? classes.colorInherit : color !== 'default' && classes[`${variant}${capitalize(color)}`], size !== 'medium' && [classes[`${variant}Size${capitalize(size)}`], classes[`size${capitalize(size)}`]], disableElevation && classes.disableElevation, disabled && classes.disabled, fullWidth && classes.fullWidth),
component: component,
disabled: disabled,
focusRipple: !disableFocusRipple,
focusVisibleClassName: clsx(classes.focusVisible, focusVisibleClassName),
ref: ref,
type: type
}, other), React.createElement("span", {
className: classes.label
}, startIcon, children, endIcon));
Note the className attribute that appears before color === 'inherit'.
Is this a Babel bug?
| Tech | Version |
| ----------- | ------- |
| Material-UI | v4.9.5 |
| React | 16.12.0 |
| Browser | Chrome |
Isn't the order irrelevant? If two selectors have the same specificity then the first one that appears in the declaration wins. I don't think order in classNames matters ever. Do you have an example that showcases the issue you have?
@eps1lon I don't think that the issue is incomplete. There is an example in the original report: https://codesandbox.io/s/button-classname-issue-bs6m2
I also included the code generated from the babel transform which clearly doesn't respect the order of the original code (it may be an issue with babel-plugin-optimize-clsx).
Even if you have the same specificity the order in the class attribute matters:
https://codepen.io/dfernandez-asapp/pen/mdJBQOX
I just confirmed that this is a bug in babel-plugin-optimize-clsx. Related issue: https://github.com/merceyz/babel-plugin-optimize-clsx/issues/18
@eps1lon About real world use cases:
styled(Button) the overrides will come before some MUI classes and you need to resort to specificity tricks too.I found a slight difference in one of our pages that was caused by the order
The order of the classes in the class attribute has no effect on styling. Only specificity and order of the declarations has an effect. Could you share an example where the order affects styles?
Ok, my bad the order doesn't matter. I got an instant of craziness due to hours of bug fixing. Probably the issue is caused by a declaration order change between versions. Going to close this, and dig more on why the computed CSS is different in my case. Sorry for the back and forward.
Most helpful comment
Ok, my bad the order doesn't matter. I got an instant of craziness due to hours of bug fixing. Probably the issue is caused by a declaration order change between versions. Going to close this, and dig more on why the computed CSS is different in my case. Sorry for the back and forward.