Material UI Table not being responsive while using example Responsive Drawer

10,091

Solution 1

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

Solution 2

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%
}
Share:
10,091
AKrush95
Author by

AKrush95

Not really sure what to put here.. :)

Updated on June 12, 2022

Comments

  • AKrush95
    AKrush95 about 2 years

    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.

  • AKrush95
    AKrush95 over 5 years
    Thanks for the response! So this works when the screen is below the breakpoint of showing the drawer, but doesn't work when the drawer is present codesandbox.io/s/6zl7r2lx0r
  • Gaurav Rana
    Gaurav Rana over 5 years
    change this(<Grid item xs={12} md={10} style={{ padding: "8px" }}>) to (<Grid item xs={12} style={{ padding: "8px" }}>) in index.js
  • AKrush95
    AKrush95 over 5 years
    thanks for the response, but this didn't solve the issue either. The problem is that when the sidebar is still visible, but the width of the screen is small enough that the table doesn't fit, the table scrolls under the sidebar