Search code examples
reactjsmaterial-uicreate-react-appemotion

Material-ui overrides react emotion rules


In my project I use Material-ui components along with react-emotion.

Let me give you an example that is problematic. I have this element:

<CardHeader title={stat} classes={{ root: statNumber }}/>

where

const statNumber = css`padding: 0;`

this way I get to override the default padding (16px) of CardHeader with 0 that is my intention.

In development mode everything works as expected but in production the padding: 0 rule gets overridden by the default padding 16px.

The reason this happens is that in development mode the styles are added in header dynamically. First come the Material-UI styles and then the emotion styles. Like this: Development mode

But in production the styles are laid out the other way around

production mode

This is the reason styles are overridden in production mode.

Material ui provides an explanation on this https://material-ui.com/styles/advanced/#css-injection-order

but with the solution proposed I cannot change the order of emotion and material-ui styles are ordered. I can only change material ui and move it further down

Anyone has an idea how to fix this??


Solution

  • The issue was resolved by changing the order of rendering the style rules. I created a wrapper that needs to wrap the entire app.

    import React from 'react'
    import { create } from 'jss'
    import JssProvider from 'react-jss/lib/JssProvider'
    import { createGenerateClassName, jssPreset } from 'material-ui/styles'
    
    const styleNode = document.createElement('style')
    styleNode.id = 'insertion-point-jss'
    document.head.insertBefore(styleNode, document.head.firstChild)
    
    // Configure JSS
    const jss = create(jssPreset())
    jss.options.createGenerateClassName = createGenerateClassName
    jss.options.insertionPoint = document.getElementById('insertion-point-jss')
    
    function Provider (props) {
      return <JssProvider jss={jss}>{props.children}</JssProvider>
    }
    
    export default Provider
    

    The wrapper creates an element as the first child inside head. All material ui styles are instructed to be placed there thus they are first in order and can be overridden by emotion rules that come next.