How to use styled components with Material UI in a React app
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.
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
1. Use Material UI’s JSS classes once for overriding Material UI original theme
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 takes as prop a theme and injects it into the application. We encapsulate our app in the
MuiThemeProvide 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.
2. Use the styled() method to style your Material UI components
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
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.
3. Prioritize the CSS rules of your styled-components over those of the JSS
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
JssProvider and other utility functions in your root component. You have to wrap your root component as follow:
4. Dynamically style your components while avoiding warnings related to DOM attributes
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:
5. Override other classes than root
There are two things you might do while doing a “complex” styling of your Material UI component:
- 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
Buttonand therefore styled-components customization as above will not work.
- Style your component with a different style according to the class used, such as
disabled. Similarly as above, if you target only the
rootclass, 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
disabled styles of
Button in addition to the custom styles on the button itself:
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.