Material-UI Styling

Getting started with Material-UI Styling

Material-UI Styling

by John Vincent


Posted on May 31, 2018


This article describes basic usage of Material-UI Styling.

General

Material-UI

Styled Components

Getting Started with Themes

A standard index.jsx

import React from 'react';
import ReactDOM from 'react-dom';
import { Provider } from 'react-redux';

import { MuiThemeProvider } from 'material-ui/styles';
import CssBaseline from 'material-ui/CssBaseline';

import { baseTheme } from './themes/themes';

import Root from './root/Root'; // your app

import configureStore from './store/configureStore'; // redux
const store = configureStore();

document.addEventListener('DOMContentLoaded', () => {
	ReactDOM.render(
		<MuiThemeProvider theme={baseTheme}>
			<CssBaseline /> {/* initialize css */}
			<Provider store={store}>
				<Root />
			</Provider>
		</MuiThemeProvider>,
		document.getElementById('root')
	);
});

themes/themes.js

import { createMuiTheme } from 'material-ui/styles';

import deepOrange from 'material-ui/colors/deepOrange';
import blue from 'material-ui/colors/blue';

export const baseTheme = createMuiTheme({
	palette: {
		primary: {
			c100: blue[100],
			c200: blue[200],
			light: blue[300],
			main: blue[500],
			dark: blue[700]
		},
		secondary: {
			light: deepOrange[300],
			main: deepOrange[500],
			dark: deepOrange[700]
		}
	},
	typography: {
		fontFamily: '"Roboto", "Helvetica", "Arial", sans-serif',
		fontSize: 14,
		fontWeightLight: 300,
		fontWeightRegular: 400,
		fontWeightMedium: 500
	},
	anchor: {
		main: blue[500],
		selected: blue[700]
	},
});

Simple Styled Component

Simple example

import React from 'react';
import PropTypes from 'prop-types';
import { withStyles } from 'material-ui/styles';

const styles = theme => ({
	anchor: {
		color: theme.anchor.main,
		textDecoration: 'none',
		'&:hover': {
			color: theme.anchor.selected,
			cursor: 'pointer'
		}
	}
});

function Anchor(props) {
	const { classes, theme } = props; // example
	return (
		<a className={props.classes.anchor} href={props.href}>
			{props.text}
		</a>
	);
}

Anchor.propTypes = {
	classes: PropTypes.object.isRequired, // eslint-disable-line react/forbid-prop-types
	href: PropTypes.string.isRequired,
	text: PropTypes.string.isRequired
};

export default withStyles(styles, { withTheme: true })(Anchor);

Note that

withStyles(styles, { withTheme: true }

puts

  • styles as classes into props
  • theme into props

withTheme

If do not need the styles but only the theme

import { withTheme } from 'material-ui/styles'

export default withTheme(MyComponent);

will make theme available as a property.

Using Variables

Styling usually requires common variables, for example a navbar line height or a drawer width.

Add them to the theme.

...
	anchor: {
		main: blue[500],
		selected: blue[700]
	},
	text: {
		home: '#fff',
		main: '#3f5742'
	},
	drawerWidth: 240,
	topNavLineHeight: 32
});

Use these variables, for example

import React from 'react';
import PropTypes from 'prop-types';
import { withStyles } from 'material-ui/styles';

import Icon from '../../toolbox/Icon';

import { appTheme } from '../../themes/themes';

const { topNavLineHeight } = appTheme;

const styles = theme => ({
	logo: {
		[theme.breakpoints.down('xs')]: {
			justifyContent: 'center'
		},
		fill: theme.palette.common.white,
		height: `${topNavLineHeight}px`,
		width: `${topNavLineHeight}px`,
		margin: '0 0.5em'
	}
});

function LogoIcon(props) {
	return <Icon name="any" css={props.classes.logo} />;
}

LogoIcon.propTypes = {
	classes: PropTypes.object.isRequired // eslint-disable-line react/forbid-prop-types
};

export default withStyles(styles, { withTheme: true })(LogoIcon);

Separating Components and Styles

Styling code in the component code can quickly become unreadable. Let's change the above example, a simple example to illustrate the point.

LogoIconStyles.jsx

import { appTheme } from '../../themes/themes';

const { topNavLineHeight } = appTheme;

const LogoIconStyles = theme => ({
	logo: {
		[theme.breakpoints.down('xs')]: {
			justifyContent: 'center'
		},
		fill: theme.palette.common.white,
		height: `${topNavLineHeight}px`,
		width: `${topNavLineHeight}px`,
		margin: '0 0.5em'
	}
});

export default LogoIconStyles;

LogoIcon.jsx

import React from 'react';
import PropTypes from 'prop-types';
import { withStyles } from 'material-ui/styles';

import Icon from '../../toolbox/Icon';
import LogoIconStyles from './LogoIconStyles';

function LogoIcon(props) {
	return <Icon name="any" css={props.classes.logo} />;
}

LogoIcon.propTypes = {
	classes: PropTypes.object.isRequired // eslint-disable-line react/forbid-prop-types
};

export default withStyles(LogoIconStyles, { withTheme: true })(LogoIcon);

css Styles

For example

import React from 'react';
import PropTypes from 'prop-types';

import './app.css';

const App = () => (
	<div className="main">Hello</div>
);

export default App;

app.css

.main {
  background-color: red;
  height: 300px;
}

scss Styles

Basic usage, for example

import React from 'react';
import PropTypes from 'prop-types';

import './app.scss';

const App = () => (
	<div className="main">Hello</div>
);

export default App;

app.scss

@import '../scss/mixins';

@import '../scss/variables';

@import '../scss/base';

.main {
  background-color: red;
  height: 300px;
}

Styled Components

Installation

npm install styled-components --save

Basic usage, for example

import React from 'react';
import PropTypes from 'prop-types';

import styled from 'styled-components';

const Title = styled.h2`
	text-align: center;
	margin: 25px 0;
	font-weight: bold;
	font-size: 1.5em;
	line-height: 1.5em;
`;

const Header = styled.h3`
	margin: 20px 0;
`;

const App = ({ classes }) => (

...