Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?

For example, to override the AppBar (https://material-ui-next.com/api/app-bar/) root class we can do the following:

First method (override Material UI classnames):

1 - Add the property classes in the AppBar component:

    <AppBar classes={{root: 'my-root-class'}}

2 - Override the styles with the styled components:

    styled(AppBar)`
      &.my-root-class {
        z-index: 1500;
      }
    `

Second method (force specificity):

    styled(AppBar)`
      && {
        z-index: 1500;
      }
    `

Third method (use a custom classname):

1 - Add the classname in the classname property:

    <AppBar className={`my-class ${this.props.otherClassesFromPropertiesIfNeeded}`}

2 - Override the styles with the styled components:

    styled(AppBar)`
      &.my-class {
        z-index: 1500;
      }
    `

Fourth method (use a custom classname generator)

You can control the classenames that will be generated by MaterialUI. Maybe it will require a little more effort but it can also bring more flexibility.

Please see these sections of the documentation:

/path/to/the/theme/provider/ThemeProvider.js:

import React from "react"
import MuiThemeProvider from "material-ui/styles/MuiThemeProvider"
import {createGenerateClassName} from "material-ui/styles"
import JssProvider from "react-jss/lib/JssProvider"

import {yourTheme} from "/path/to/your/theme"

const generateClassName = createGenerateClassName({
  dangerouslyUseGlobalCSS: true,
  productionPrefix: 'mui',
})

const ClassNameGenerator = (p) =>
  <JssProvider generateClassName={generateClassName} {...p}>
    {p.children}
  </JssProvider>

export class ThemeProvider {

  render() {
    return (
      <ClassNameGenerator>
        <MuiThemeProvider theme={yourTheme}>
          {this.props.children}
        </MuiThemeProvider>
      </ClassNameGenerator>
    )
  }
}

/path/to/the/root/component/Root.js

import React from "react"
import {Provider} from "react-redux"

import {ThemeProvider} from "/path/to/the/theme/provider/ThemeProvider"
import {Router} from "/path/to/your/router/definitions/Router"
import {reduxStore} from "/path/to/your/redux/store"

export class Root {

  render() {
    return (
      <Provider store={reduxStore}>
        <ThemeProvider>
          <Router />
        </ThemeProvider>
      </Provider>
    )
  }
}
@leoyli

This comment has been minimized.

Copy link

leoyli commented Feb 14, 2019

Although a bit dirty, here is my version to enforce the specificity at the very first place (logic can be wrapped in a component so React can pick it up):

  const setBeforeRepaint = 'requestAnimationFrame' in window ? requestAnimationFrame : setTimeout;
  setBeforeRepaint(() => {
    const styledComponents = document.querySelector('style[data-styled]');
    if (styledComponents) {
      styledComponents.parentNode.append(styledComponents);
    }
  });

This ensure CSS injected by the styled-components will always win, and it only need to be exercise once and before browser start to paint the next frame.

@JimVanEeden

This comment has been minimized.

Copy link

JimVanEeden commented Jun 5, 2019

In material-ui v4, you can simply do:

import { StylesProvider } from '@material-ui/styles';
// [other imports]

// [code]

function App() {
    return (
        <StylesProvider injectFirst> // this
            <MuiThemeProvider theme={theme}
                <Routes />
            </MuiThemeProvider>
        </StylesProvider>
    );
}

Took me a bit to find it, because it's not in the migration guide. The original technique as described above doesn't work anymore in v4. Hope this helps somebody else.

@mikew

This comment has been minimized.

Copy link

mikew commented Jul 25, 2019

What if you need to pass the class name down deeper, like to InputProps.className, from TextField?

@panuavakul

This comment has been minimized.

Copy link

panuavakul commented Jul 29, 2019

@mikew Did you figure it out? I'm also looking for the solution to the same answer.

@shilangyu

This comment has been minimized.

Copy link

shilangyu commented Aug 13, 2019

@JimVanEeden you saved my life, first time seeing this solution. Where did you find that? Its the simplest yet not in the docs

@JimVanEeden

This comment has been minimized.

Copy link

JimVanEeden commented Aug 14, 2019

@shilangyu I can't remember honestly :'). I think I just looked through the source or something.

@DylanSp

This comment has been minimized.

Copy link

DylanSp commented Aug 26, 2019

@JimVanEeden Thanks a ton for that solution! It makes things a lot easier.

@shilangyu It's in the docs, in the Advanced section under Styles.

@TomPfundt

This comment has been minimized.

Copy link

TomPfundt commented Oct 5, 2019

@JimVanEeden Thanks, thats exactly what I've been looking for, just wish I found it an hour or two ago!

@sladg

This comment has been minimized.

Copy link

sladg commented Dec 23, 2019

In material-ui v4, you can simply do:

import { StylesProvider } from '@material-ui/styles';
// [other imports]

// [code]

function App() {
    return (
        <StylesProvider injectFirst> // this
            <MuiThemeProvider theme={theme}
                <Routes />
            </MuiThemeProvider>
        </StylesProvider>
    );
}

Took me a bit to find it, because it's not in the migration guide. The original technique as described above doesn't work anymore in v4. Hope this helps somebody else.

Thx! It worked!

import { StylesProvider } from '@material-ui/styles';
import App from 'next/app';
import React from 'react';
import { ThemeProvider } from 'styled-components';

const theme = {
  colors: {
    primary: '#037Ef3',
    textLight: '#F3F4F7',
  },
};

class MyApp extends App {
  render() {
    const { Component, pageProps } = this.props;
    return (
      <StylesProvider injectFirst>
        <ThemeProvider theme={theme}>
          <Component {...pageProps} />
        </ThemeProvider>
      </StylesProvider>
    );
  }
}

export default MyApp;
@wasinsandiego

This comment has been minimized.

Copy link

wasinsandiego commented Mar 14, 2020

@mikew @panuavakul
You can use the typical sass-like nested selectors. Selector as keys and value as object with css properties.

Only thing you need to know is the class names you want to target. If you render the input you can inspect and see the class names of the element you want to target. There may also be some info in the docs, but I haven't noticed it.

For the MUI within TextField I can see these class names on the input.

.MuiInputBase-input
.MuiInput-input

Here's an example.

Notice the empty space between the & and the class name.

const Search = styled(TextInput)({
  width: '100%',
  marginBottom: '15px',
  background: '#fff',
  '& .MuiInputBase-input': {
    background: '#ff00ff',
    color: '#fff',
    fontWeight: '900',
  },
})

If you need more specificity it's best to simply chain more class names.

const Search = styled(TextInput)({
  width: '100%',
  '& input.MuiInputBase-input.MuiInput-input': {
    background: '#ff00ff',
  },
})
@garyanikin

This comment has been minimized.

Copy link

garyanikin commented Mar 24, 2020

Easiest way https://material-ui.com/ru/guides/interoperability/#styled-components
To provide injectFirst property to StylesProvider component

import { StylesProvider } from '@material-ui/core/styles';

<StylesProvider injectFirst>
  {/* Your component tree.
      Now, you can override Material-UI's styles. */}
</StylesProvider>
@webcoderkz

This comment has been minimized.

Copy link

webcoderkz commented Apr 23, 2020

All the above mentioned methods are ugly, if you want to pass classes object, just do it this way:

const ModifiedAppBar = styled(({...rest}) => (
  <AppBar classes={{root: 'my-root-class'}} {...rest}/>
))`
  .my-root-class {
    z-index: 1500;
  }  
`
@shilangyu

This comment has been minimized.

Copy link

shilangyu commented Apr 23, 2020

All the above mentioned methods are ugly, if you want to pass classes object, just do it this way:

const ModifiedAppBar = styled(({...rest}) => (
  <AppBar classes={{root: 'my-root-class'}} {...rest}/>
))`
  .my-root-class {
    z-index: 1500;
  }  
`

this is literally what the gist is proposing as a solution

@juanbelieni

This comment has been minimized.

Copy link

juanbelieni commented May 15, 2020

@JimVanEeden Thank you, it worked.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.