skip to Main Content

I have created a web app with the base coming from the Material-UI Example on a responsive drawer

I am trying to get a table to resize responsively to the screen width, but, for some reason, the ResponsiveDrawer container provided by Material-UI is breaking the responsiveness of the contents (i.e. the table)

Here is an example that I wrote that is perfectly responsive:

App.js

import React from "react";
import ReactDOM from "react-dom";
import Table from "@material-ui/core/Table/Table";
import TableHead from "@material-ui/core/TableHead/TableHead";
import TableRow from "@material-ui/core/TableRow/TableRow";
import TableCell from "@material-ui/core/TableCell/TableCell";
import TableBody from "@material-ui/core/TableBody/TableBody";
import Paper from "@material-ui/core/Paper/Paper";
import Grid from "@material-ui/core/Grid/Grid";

import "./styles.css";

function App() {
  return (
    <div className="App">
      <Grid container justify={"center"}>
        <Grid item xs={12} md={10} style={{ padding: "8px" }}>
          <Paper style={{ overflowX: "auto" }}>
            <Table style={{ minWidth: "340px" }}>
              <TableHead>
                <TableRow>
                  <TableCell>Name</TableCell>
                  <TableCell>Column</TableCell>
                  <TableCell>Operating System</TableCell>
                  <TableCell>Status</TableCell>
                  <TableCell>CPU Cores</TableCell>
                  <TableCell>Memory (MB)</TableCell>
                  <TableCell>IP Address</TableCell>
                </TableRow>
              </TableHead>
              <TableBody>
                <TableRow>
                  <TableCell>Content</TableCell>
                  <TableCell>Content</TableCell>
                  <TableCell>Content</TableCell>
                  <TableCell>Content</TableCell>
                  <TableCell>Content</TableCell>
                  <TableCell>Content</TableCell>
                  <TableCell>Content</TableCell>
                </TableRow>
                <TableRow>
                  <TableCell>Content</TableCell>
                  <TableCell>Content</TableCell>
                  <TableCell>Content</TableCell>
                  <TableCell>Content</TableCell>
                  <TableCell>Content</TableCell>
                  <TableCell>Content</TableCell>
                  <TableCell>Content</TableCell>
                </TableRow>
              </TableBody>
            </Table>
          </Paper>
        </Grid>
      </Grid>
    </div>
  );
}

const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);

And here is that same example using a modified (changed the content to this.props.children instead of static) version of Material-UI’s ResponsiveDrawer

ResponsiveDrawer.js

import React from "react";
import PropTypes from "prop-types";
import AppBar from "@material-ui/core/AppBar";
import CssBaseline from "@material-ui/core/CssBaseline";
import Divider from "@material-ui/core/Divider";
import Drawer from "@material-ui/core/Drawer";
import Hidden from "@material-ui/core/Hidden";
import IconButton from "@material-ui/core/IconButton";
import InboxIcon from "@material-ui/icons/MoveToInbox";
import List from "@material-ui/core/List";
import ListItem from "@material-ui/core/ListItem";
import ListItemIcon from "@material-ui/core/ListItemIcon";
import ListItemText from "@material-ui/core/ListItemText";
import MailIcon from "@material-ui/icons/Mail";
import MenuIcon from "@material-ui/icons/Menu";
import Toolbar from "@material-ui/core/Toolbar";
import Typography from "@material-ui/core/Typography";
import { withStyles } from "@material-ui/core/styles";

const drawerWidth = 240;

const styles = theme => ({
  root: {
    display: "flex"
  },
  drawer: {
    [theme.breakpoints.up("sm")]: {
      width: drawerWidth,
      flexShrink: 0
    }
  },
  appBar: {
    marginLeft: drawerWidth,
    [theme.breakpoints.up("sm")]: {
      width: `calc(100% - ${drawerWidth}px)`
    }
  },
  menuButton: {
    marginRight: 20,
    [theme.breakpoints.up("sm")]: {
      display: "none"
    }
  },
  toolbar: theme.mixins.toolbar,
  drawerPaper: {
    width: drawerWidth
  },
  content: {
    flexGrow: 1,
    padding: theme.spacing.unit * 3
  }
});

class ResponsiveDrawer extends React.Component {
  state = {
    mobileOpen: false
  };

  handleDrawerToggle = () => {
    this.setState(state => ({ mobileOpen: !state.mobileOpen }));
  };

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

    const drawer = (
      <div>
        <div className={classes.toolbar} />
        <Divider />
        <List>
          {["Inbox", "Starred", "Send email", "Drafts"].map((text, index) => (
            <ListItem button key={text}>
              <ListItemIcon>
                {index % 2 === 0 ? <InboxIcon /> : <MailIcon />}
              </ListItemIcon>
              <ListItemText primary={text} />
            </ListItem>
          ))}
        </List>
        <Divider />
        <List>
          {["All mail", "Trash", "Spam"].map((text, index) => (
            <ListItem button key={text}>
              <ListItemIcon>
                {index % 2 === 0 ? <InboxIcon /> : <MailIcon />}
              </ListItemIcon>
              <ListItemText primary={text} />
            </ListItem>
          ))}
        </List>
      </div>
    );

    return (
      <div className={classes.root}>
        <CssBaseline />
        <AppBar position="fixed" className={classes.appBar}>
          <Toolbar>
            <IconButton
              color="inherit"
              aria-label="Open drawer"
              onClick={this.handleDrawerToggle}
              className={classes.menuButton}
            >
              <MenuIcon />
            </IconButton>
            <Typography variant="h6" color="inherit" noWrap>
              Responsive drawer
            </Typography>
          </Toolbar>
        </AppBar>
        <nav className={classes.drawer}>
          {/* The implementation can be swapped with js to avoid SEO duplication of links. */}
          <Hidden smUp implementation="css">
            <Drawer
              container={this.props.container}
              variant="temporary"
              anchor={theme.direction === "rtl" ? "right" : "left"}
              open={this.state.mobileOpen}
              onClose={this.handleDrawerToggle}
              classes={{
                paper: classes.drawerPaper
              }}
            >
              {drawer}
            </Drawer>
          </Hidden>
          <Hidden xsDown implementation="css">
            <Drawer
              classes={{
                paper: classes.drawerPaper
              }}
              variant="permanent"
              open
            >
              {drawer}
            </Drawer>
          </Hidden>
        </nav>
        <main className={classes.content}>
          <div className={classes.toolbar} />
          {this.props.children}
        </main>
      </div>
    );
  }
}

ResponsiveDrawer.propTypes = {
  classes: PropTypes.object.isRequired,
  // Injected by the documentation to work in an iframe.
  // You won't need it on your project.
  container: PropTypes.object,
  theme: PropTypes.object.isRequired
};

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

App.js

import React from "react";
import ReactDOM from "react-dom";
import Table from "@material-ui/core/Table/Table";
import TableHead from "@material-ui/core/TableHead/TableHead";
import TableRow from "@material-ui/core/TableRow/TableRow";
import TableCell from "@material-ui/core/TableCell/TableCell";
import TableBody from "@material-ui/core/TableBody/TableBody";
import Paper from "@material-ui/core/Paper/Paper";
import ResponsiveDrawer from "./ResponsiveDrawer";
import Grid from "@material-ui/core/Grid/Grid";

import "./styles.css";

function App() {
  return (
    <div className="App">
      <ResponsiveDrawer>
        <Grid container justify={"center"}>
          <Grid item xs={12} md={10} style={{ padding: "8px" }}>
            <Paper style={{ overflowX: "auto" }}>
              <Table style={{ minWidth: "340px" }}>
                <TableHead>
                  <TableRow>
                    <TableCell>Name</TableCell>
                    <TableCell>Column</TableCell>
                    <TableCell>Operating System</TableCell>
                    <TableCell>Status</TableCell>
                    <TableCell>CPU Cores</TableCell>
                    <TableCell>Memory (MB)</TableCell>
                    <TableCell>IP Address</TableCell>
                  </TableRow>
                </TableHead>
                <TableBody>
                  <TableRow>
                    <TableCell>Content</TableCell>
                    <TableCell>Content</TableCell>
                    <TableCell>Content</TableCell>
                    <TableCell>Content</TableCell>
                    <TableCell>Content</TableCell>
                    <TableCell>Content</TableCell>
                    <TableCell>Content</TableCell>
                  </TableRow>
                  <TableRow>
                    <TableCell>Content</TableCell>
                    <TableCell>Content</TableCell>
                    <TableCell>Content</TableCell>
                    <TableCell>Content</TableCell>
                    <TableCell>Content</TableCell>
                    <TableCell>Content</TableCell>
                    <TableCell>Content</TableCell>
                  </TableRow>
                </TableBody>
              </Table>
            </Paper>
          </Grid>
        </Grid>
      </ResponsiveDrawer>
    </div>
  );
}

const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);

I just can’t seem to figure out what it is inside the ResponsiveDrawer container that is causing the responsiveness to break.

All help appreciated.

UPDATE (1/7/2019):
It looks like removing display: flex from the root solves the issue, but then I have the issue of it not honoring the left drawer.

UPDATE (1/9/2019):
As suggested by @Gaurav Rana, I have added width: 100%; to the main element and it has half solved the problem. Now, the table will overflow / scroll properly when the sidebar is not visible. But, when the sidebar is still visible but the screen isn’t wide enough for the whole table, the table scrolls under the sidebar.

3

Answers


  1. Chosen as BEST ANSWER

    After a bit of troubleshooting, I have come up with a solution:

    The styles for content need to be updated as follows (This will force the width of the content element to fit the width of the screen minus the drawer if necessary):

      content: {
        [theme.breakpoints.up("sm")]: {
          marginLeft: drawerWidth,
          width: `calc(100% - ${drawerWidth}px)`
        }
      },
    

    And display: flex needs to be removed from root

    https://codesandbox.io/s/1zxp2qjmoj


  2. add style below style in your styles.css . hope this will solve your issue.

    main {
      width: 100%;
    }
    
    Login or Signup to reply.
  3. this is a problem width css width. You must specify whole parents width: 100% like this

    body {
      width: 100%
    }
    .grandparent {
      width: 100%
    }
    .parent {
      width: 100%
    }
    .tableContainer {
      width: 100%
    }
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search