How to use styled components with Material UI in a React app

Benjamin Stirrup
Jan 14, 2019 · 5 min read

We will see how to style Material UI components with the library styled-components. Among the edge cases we will cover are: overriding Material UI's theme, prioritize the CSS rules of styled components and override classes other than root of Material UI components.

You can play with the code snippets present in this tutorial with the following codesandbox link: https://codesandbox.io/embed/6lmnv4457z

Why Material UI and styled-components?

Material UI is a great component library that emulates Google’s Material Design. I choose to use it on each of my React web apps. And I am not alone: with more than 42k stars on github, it is the most popular component library for React.

Styled-components is another great library used to style React components. We do so by defining React “styled” components without CSS classes. Indeed, these styled components take CSS rule blocks as input. With 20k stars on github, it seems to be a no-brainer for many other web app developers too.

Some of the advantages of styled-components:

  • Large and active community.
  • Explicit and exhaustive documentation.
  • Template literal syntax for CSS. That means if you can write normal CSS, you can style components without having to learn a new syntax.
  • Sass support: write your style in a easier way to understand and with less lines of code.
  • The components’ code base is reduced: no style object in the render() method, no need of a multitude of conditional class names. This means you can focus on the logical structure of your React components.
  • Render CSS conditionally using props.

The problem

Material UI was designed to be used from the get-go with its own styling solution, implemented over JSS, as opposed to using styled-components.

Fortunately, Material UI has made it simple to use other styling solutions. Therefore, if you want to leverage the advantages of both Material UI and styled-components, wait no longer and read the rest of this article.

The 5 steps to mastery

Even though our objective is to style our web app using styled-components, we should not be afraid of using Material UI’s theme feature. The theme specifies the default style rules of the MUI components, such as color, level of shadow, etc…The theme enables us to create a pretty good base for our style. To illustrate the usage of Material UI’s theme, we will give a red background color to all our buttons, with a green background color on hover.

First create a theme.js file in your root folder:

Then, we have to provide the theme defined above to the app, using the MuiThemeProvider. The MuiThemeProvider takes as prop a theme and injects it into the application. We encapsulate our app in theMuiThemeProvide as follow:

As you have just seen, to customize a specific instance of material UI components within our app, we provided to our theme the name and class of the component. This name and the class can be found in the CSS section of the API page of the Material UI components, for example https://material-ui.com/api/button/#css.

The styled() method from styled-components takes as input a React component and outputs another React component with a different style. It is useful as it enables you to style your component using the exact same syntax as in your typical CSS stylesheet. It works as follow:

❗️❗️❗️ Warning ❗️❗️❗️ : if you made your app exactly as in the previous steps, you should see that some of the CSS rules defined in the styled component are overridden by the defaults of Material UI, such as color and background-color. This is because the CSS injected by Material-UI to style a component has the highest specificity possible as the <link> is injected at the bottom of the <head> in the index.html file, in order to ensure the components always render correctly.

You might, however, want to override these styles if you intend to fully use styled-components. This leads us to the next step.

1st method: increase specificity by repeating the class name

To ensure styled-components styles are applied before JSS styles, you can use use the ampersand (&) character in styled-components, which is equivalent to repeating the class name. The ampersand character is used to refer back to the main component. This solution applied to our example gives the following:

The disadvantage of this approach is that you have to use it for every styled component whose style specificity does not suit your needs. Not very DRY (Don't Repeat Yourself)!

2nd method: modify the CSS injection order

JSS provides a mechanism to handle specificity issues. By adjusting the placement of the insertionPoint within your HTML <head>, you can control the order in which the CSS rules are applied to your components.

The simplest approach is to add an HTML comment that determines where JSS will inject the styles. However, you may have been using create-react-app to kickstart your project. Create React App strips HTML comments when creating the production build. To get around the issue, you can provide a DOM element as the JSS insertion point.

First, place the insertion point as a DOM element at the top of <head>:

Then, import JssProvider and other utility functions in your root component. You have to wrap your root component as follow:

Your styled components are still components: you can pass them props to style them dynamically! However, to avoid warnings related to props passed directly to the underlying DOM element, you have to decompose what props you actually pass to the overriden Material UI component. An example of such decomposition follows:

There are two things you might do while doing a “complex” styling of your Material UI component:

  1. Style the child of your component. For example, the <span> element that wraps the children of a Material UI Button can be styled through the class label. However, this is not the root element of Button and therefore styled-components customization as above will not work.
  2. Style your component with a different style according to the class used, such as disabled. Similarly as above, if you target only the root class, you will not be able to style your Button in its disabled state.

The most reliable approach is to use the classes property to introduce an override style, and then style it with higher specificity with selectors. Note that the styled-components' CSS preprocessor is stylis, which supports css-like syntax for automatically nesting styles.

The following example overrides the label and disabled styles of Button in addition to the custom styles on the button itself:

Endnotes

I believe I have shown you all the possible edge-cases that can happen when using the Material UI with styled components. While I chose Material UI as my component collection, you should be able to use the same styling techniques for any other component library.

Therefore, you should not have any problem styling your components in a React app from now on!


I conceive and develop tailor-made web applications in record time for my French and European clients. Whether you are an entrepreneur, corporate innovator or agency, let’s work together on the delivery of your project at benjaminstirrup.com.

Sipios

Sipios conceives and develops tailored products in record time that shape tomorrow’s financial industry. We take on our clients’ most exciting technical and business challenges which we share in our publications.

Thanks to Alex-Adrien Auger and Laurent Ros

Benjamin Stirrup

Written by

I conceive and develop tailor-made web applications in record time for my French and European clients. Let’s launch your project at benjaminstirrup.com

Sipios

Sipios

Sipios conceives and develops tailored products in record time that shape tomorrow’s financial industry. We take on our clients’ most exciting technical and business challenges which we share in our publications.

Welcome to a place where words matter. On Medium, smart voices and original ideas take center stage - with no ads in sight. Watch
Follow all the topics you care about, and we’ll deliver the best stories for you to your homepage and inbox. Explore
Get unlimited access to the best stories on Medium — and support writers while you’re at it. Just $5/month. Upgrade