Global CSS with Material-UI Done Correctly in React Apps

Johann Blake
5 min readMar 7, 2020

I just recently started out using React.js and wanted to implement a material design UI for my entire app. I came across a well known open source library called material-ui:

While the library comes with a pre-defined theme, I really needed to change the styles to match up with what I wanted. In a standard web app, you just create a css file and include it in your HTML. But with React, this is generally not possible and css is handled differently. When you create a css file and import it using the import statement, React uses Webpack to compile the css into Javascript code that is automatically loaded when your app runs. In many cases, this is just fine since it really shouldn’t matter how the css styles get loaded.

But material-ui doesn’t work with css files. The library does provide many ways of customizing the styles, either on a component-by-component basis or even globally. When looking at their solution to implementing a global css theme, I was disturbed to discover that they had placed the css styles directly in code as strings, mixed in with Javascript. Personally, I found this one of the dumbest things I’ve ever seen. What kind of weed were these guys smoking to think that this was some kind of good idea to place css directly in code? Having css styles in code makes it impossible to use any tools to edit and manage your styles. Almost all IDEs come with built-in support for editing css files, including Visual Studio Code (VSC) and IntelliJ. I quickly came to the conclusion that there was no way in hell I was going to put css styles into Javascript code. So I came up with a solution that lets me keep the css in separate files while still allowing me to use the material-ui library. This solution also addresses another major issue which is the need to perform setup stuff prior to the web app launching. So even if you are not interested in using this approach to handle css styles, you can use it to execute startup code that is normally performed prior to the initial page being displayed.

The solution consists of the following steps:

  1. Create your css file
  2. Load the css file using jQuery
  3. Parse the css using the parsecss jQuery plugin
  4. Use withStyles and the parsed css to override the default theme of material-ui

It is assumed at this point that you have already installed material-ui.

Load jQuery and CSS Parser Plugin

Before you freak out about using jQuery, keep in mind that jQuery isn’t used exclusively for manipulating the DOM. It has a lot of other useful non-ui functions that you won’t get with React. I certainly would avoid using jQuery for UI-related stuff where possible although React does support it as long as you follow their rules. But we’ll only be using it to load the css file.

In your index.html file, add jQuery as follows:

The css parser jQuery plugin is available at:

http://bililite.com/inc/jquery.parsecss.js

You must copy the file to your app’s public folder. Don’t place it in a sub folder within the public folder as React will not recognize it. Finally, reference the plugin in your index.html file as follows:

Create CSS File

You create your css file as you normally do. However, you must store it under the src folder or a sub folder of src. I stored mine under:

src > res > css

You must not give the file the extension .css. If you do that, React will recognize it as a css file and build it into Javascript that gets automatically loaded into your app during startup. I chose to give my file the extension .cssstyles. So I called my file app.cssstyles

Your IDE will almost certainly not recognize your file extension making it impossible to edit the file with its built in css editor. But IDEs like VSC and IntelliJ have a feature that lets you associate a file extension with a built-in supported type. In VSC, click on:

Code > Preferences > Settings

In the Search box, type in the word “associate” and then click on the link:

Edit in settings.json

Under files.extensions, add a mapping from your custom extension to “css”:

settings.json

Here is what my css file looks like. It overrides the styles for the Tabs component in material-ui:

app.cssstyles

To know what styles to override, just run your app with the default theme from material-ui and use DevTools to inspect what css classes are being used for each of the component’s styles and override those styles in your css file.

Load Your CSS File

The following code, which is launched in your index.js file, loads the css file and parses the css data:

Notice the comment at the top of the code:

/* global $ */

This is necessary to help React identify the $ character that is reserved for jQuery. The final step is to use the globalCss variable in a React component that will be applied to the entire app. This is done in Main.js

And that’s it. Now you can use your IDE to modify your css data and React will automatically update your app’s UI automatically without the need to rebuild your app. Back to css, the way it was meant to be…

--

--