Responsive Material-UI

Getting started with Responsive Material-UI

Responsive Material-UI

by John Vincent


Posted on May 30, 2018


This article describes basic usage of Responsive Material-UI.

General

Material-UI

Responsive UI Guidelines

Basic Layout

Breakpoints

An example of how to access breakpoints from the theme.

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

import { withStyles } from 'material-ui/styles';
import Hidden from 'material-ui/Hidden';

import HomeLayoutStyles from './HomeLayoutStyles';

class HomeLayout extends React.Component {

    render() {
        const { classes, theme } = this.props;
        ...
    }
}

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

export default withStyles(HomeLayoutStyles, { withTheme: true })(HomeLayout);

For example

theme.breakpoints.values =
    {xs: 0, sm: 600, md: 960, lg: 1280, xl: 1920}

Thus

xs, extra-small: 0px or larger
sm, small: 600px or larger
md, medium: 960px or larger
lg, large: 1280px or larger
xl, xlarge: 1920px or larger

Also see

theme.breakpoints.between
theme.breakpoints.down
theme.breakpoints.up
theme.breakpoints.width

Styles

Basic usage, for example

const styles = theme => ({
    contentContainer: {
        width: '100%',
        maxWidth: '70%',
        [theme.breakpoints.down('md')]: {
            maxWidth: '85%'
        },
        [theme.breakpoints.down('sm')]: {
            maxWidth: '95%'
        }
    },
    logo: {
        justifyContent: 'space-between',
        [theme.breakpoints.down('xs')]: {
            justifyContent: 'center'
        },
        [theme.breakpoints.up('md')]: {
            display: 'none'
        },
        [theme.breakpoints.between('sm', 'md')]: {
            margin: 25%
        }
        ...
    },
    iconSearch: {
        [`${theme.breakpoints.up('sm')} and $           {theme.breakpoints.down('md')}`]: {
                margin: 10%
    }
});
const md = theme.breakpoints.width('md');

Hidden

The rules follow

innerWidth  |xs      sm       md       lg       xl
            |--------|--------|--------|--------|-------->
width       |   xs   |   sm   |   md   |   lg   |   xl

smUp        |   show | hide
mdDown      |                     hide | show

Examples follow

<Hidden xsDown>
    <Button color="inherit" component={Link} to="/logout">
        Logout
    </Button>
</Hidden>

<Hidden smUp>
    <div>
        <IconButton
            color="inherit"
            aria-label="open drawer"
            onClick={this.handleDrawerToggle}
            className={classes.navIcon}
        >
            <MenuIcon />
        </IconButton>
    </div>
</Hidden>

<Hidden mdUp>
    <Drawer
        variant="temporary"
        anchor="left"
        open={this.state.mobileOpen}
        onClose={this.handleDrawerToggle}
        classes={ {
            paper: classes.drawerPaper
        } }
        ModalProps={ {
            keepMounted: true
        } }
    >
        {drawer}
    </Drawer>
</Hidden>

Responsive

Get the package

npm i react-responsive --save

Include the package

import Responsive from 'react-responsive';

Usage, for example

const Desktop = props => <Responsive {...props} minWidth={992} />;
const Tablet = props => <Responsive {...props} minWidth={768} maxWidth={991} />;
const Mobile = props => <Responsive {...props} maxWidth={767} />;

render() {
...
    return (
        <Fragment>
            <Desktop>
                <DesktopMain text="DesktopMain" />
            </Desktop>
            <Tablet>
                <TabletMain text="TabletMain" />
            </Tablet>
            <Mobile>
                <MobileMain text="MobileMain" />
            </Mobile>
        </Fragment>
    );
}

MediaQuery

Get the package

npm i react-responsive --save

Include the package

import Responsive from 'react-responsive';

Usage, for example

import MediaQuery from 'react-responsive';

<MediaQuery maxWidth={580}>
    <div className="header-grid--icon header-icon-parent">
        {this.state.navOpen ? (
            <ButtonIcon
                svgName="cancel"
                cssIcon="close-menu"
                cssButton="header-icon"
                onClick={this.handleClickMenu}
            />
        ) : (
            <ButtonIcon
                svgName="hamburger"
                cssIcon="open-menu"
                cssButton="header-icon"
                onClick={this.handleClickMenu}
            />
        )}
    </div>
</MediaQuery>

<MediaQuery maxWidth={580}>
    {this.state.navOpen && (
        <div className="header-grid--nav">
            <HeaderNav loggedin={this.props.loggedin} />
        </div>
    )}
</MediaQuery>

<MediaQuery minWidth={580}>
    <div className="header-grid--nav">
        <HeaderNav loggedin={this.props.loggedin} />
    </div>
</MediaQuery>
</header>

Window

The usual techniques are still available. For example

function isDesktop() {
    return window.matchMedia('(max-width: 767px)').matches;
}

function isMdUp() {
    return window.matchMedia('(min-width: 960px)').matches;
}

with example usage

class MemberLayout extends React.Component {
    state = {
        open: !!isMdUp()
    };