Styling and theming with material-ui: React + Material Design

We’ve looked at building and styling with rmwc, now lets look a the king of the React Material libraries, Material-UI!

The implementation strategy here is different — instead of including a generated CSS file that applies to all of the elements, each component includes the CSS that it needs in an isolated way. import Button from ‘material-ui/Button’; will include all of the necessary CSS to render that element. This is done with webpack basically. If we want to style it in a special way, we’ll need to put style attributes on it directly or use another react-based way of doing this, keeping the styling, html, and JS tightly coupled. Which actually makes a lot of sense…

The basic way that material-ui does styling is with the withStyles higher order component. The complete system is explained in the documentation, but since I’m learning React as well I didn’t full understand how it worked at first. You can treat it as boilerplate code for now, but lets first get started rebuilding the same site as we did last time and seeing what looks like.

Create the app

First thing we do is to add material-ui@next and our favorite WebFont loader.

$ yarn add material-ui@next material-ui-icons webfontloader

And then we load the Roboto font from the Google mothership. The Material Icons will come in as part of the npm package above.

Now lets build out the nav bar component. This is going to look at lot more complicated than the rmwc version! On the other hand, absolutely everything you need to understand what is going to be displayed is self-contained in this file.

Lets walk through all the differences.

  1. The first thing you’ll notice is that each of the React components are in their own subpackage, which means that you’ll have a lot more import lines in your code
  2. The React Bits book is pretty awesome, and they have a section on using Higher Order Components for Styling, which is basically what we’re doing here.
  3. withStyles is the higher order component that you use to merge in the styles. We create a function that accepts a theme object, and then we set our special CSS in there. At the bottom of the file we export default withStyles(styles)(Navbar) to expose our code to the rest of the app. What this does is merge our style overrides with the overall theme, and then lets us access the generated class name when we do the render.
  4. const {classes} = this.props is how we pull those classes out. They can then be referenced in our components using, for example, <IconButton className={classes.menuButton}/>. We start with our style definitions, which get passes a theme object, and it gets wrapped onto the properties of our component using withStyles. Clever, but not that simple.
  5. I’m setting the elevation={0} of AppBar to make it look the same as the other example.
  6. Each of the MaterialIcons have their own component in the material-ui-icons package.

While material-ui doesn’t use the recompose library, I found reading through it’s docs very helpful in sorting out what withStyles actually is trying to accomplish.


Lets do the login form now, and we’ll do something similar with a HOC. In this case we’ll use withMobileDialog which will pass in the fullscreen property as true to our component if the screen is small. For example, on a mobile device. In that case will we show a full screen window. This is your src/login.js

Let us now recreate the drawer.js. (I’m using different Items in the drawer list since it’s just for example anyway, and this should give you a sense of how things are done.)

Now that we have the drawer in place, lets now build a simple little feed to start testing things on. I’m trying to recreate the same example that we did before, so I have two components defined in this class. This is for demo purposes only, and doesn’t really make sense.

  1. There’s some css to get through in this class, but on the other hand, it’s all in the same place. For simple components or projects this is a pain. I think for larger projects that having these things isolated so that everything you need to understand about a specific component is in one place is better. This file should be split into at least 4 probably: feed.js, feed.css.js, feed_item.js, and feed_item.css.js.
  2. I’m wrapping FeedItem with withStyles here to make it more explicit what the withStyles does. Alteratively, we could pass in the class name on <FeedItem className={classes.feedItem}/> inside of FeedItem itself, but this makes it more explicit that you are only dealing with styled components.
  3. Flexbox is pretty amazing once you get a hang of it.

And finally, lets update the App.js to wrap it all together.

  1. One thing is strange with this is that I’m handling the opening/closing CSS logic inside of the main container. If I wasn’t trying to follow the same structure as the last example, I would split this out into a Sidebar/Main component that figured out the CSS logic so it wouldn’t polute this page.
  2. `calc(100% — ${drawerWidth}px)` is pretty amazing

And this should look familiar!

Changing theme level properties

Themes in material-ui are top level objects that get set using the MuiThemeProvider component. This, in turn, will do some magic with the React context and the theme object will get passed into the function that you provided to withStyles. Lets have an example to see what I mean.

  1. I’ve defined 3 different themes. One default, one with basic colors, and one with different fonts.
  2. There’s a lot more to wrap your head around to make this work initially, but it feels cleaner and more direct.


The biggest take away from doing this various different ways is that the first three or four times I use a library I don’t have a great idea of how it works. So it’s important to keep going over the same thing again and again, starting from scratch once you figure something new out and reorganizing based upon what you’ve learned. Much like learning how to play an instrument, going back and repeating each section to learn it better makes the final performance that much easier.

Material-UI has a lot more activity on the project than rmwc does. It’s using a different version of material design, and we aren’t using the library that Google provided directly. Some of the tools that Google provides can’t be effectively leveraged. But if you are building in React, which we are, MaterialUI seems like a much more effective and powerful choice.

Final code can be found here: