Material-ui: [Grid] Extra width of container & scrollbar

Created on 19 Jul 2017  ·  49Comments  ·  Source: mui-org/material-ui

The <Grid container> extends beyond its parent, with half of spacing size.
I have marked the extra width in red, also setting spacing to zero fixes the problem.

mobile-padding

Here is a working example: https://codesandbox.io/s/Y8nzGm5W.
Similar code with a zero spacing works as expected: https://codesandbox.io/s/NxvYxvQpL.

bug 🐛 Grid important

Most helpful comment

Still have the same issue, but fixed by adding xs={12}.
<Grid container spacing={3} xs={12}>

All 49 comments

I have found the same issue on flexboxgrid. I think that it's a limitation of our negative margin solution that implements the spacing.
I have checked out what bootstrap is doing, they don't have this spacing feature, so no issue on their end.

So you have 3 available workarounds:

  • Not using the spacing feature and implementing it on userland spacing={0}, we could make this the default behavior.
  • Adding a padding on the parent with, at least, the spacing value: https://codesandbox.io/s/WnpKlQ32n
    <div style={{ padding: 20 }}>
      <Grid container spacing={40}>
  • Adding overflow-x: hidden; on the parent.

I'm closing as I can't think of a better alternative. If someone has a better solution for the spacing feature, please raise your voice :).

To me, it seems like spacing={0} should be the default behavior. At least until a better solution comes along, because it appears to be a bug with <Grid /> to first-time users of material-ui.

@hboylan In the light of all those issues open for this limitation, I'm starting to wonder! I wish we had access to some API usage analytics 📈 .

I have added the waiting for users upvotes tag. I'm not sure people would prefer having spacing={0}. So please upvote this issue if you are. We will prioritize our effort based on the number of upvotes.

At least 8 duplicated issues is a strong signal. I will add a note about this limitation in the documentation.

Just wondering: Are there any caveats using the 2nd workaround you described?

If not, you could add this in the Grid-container-Component per default?

update:
=> silly me ;) of course: we are loosing the space, sorry.

I'm unable to fix this in material-ui@next using spacing={0} in the container, or any of the other two solutions including overflowing-x and such. Maybe i'm missing something?

flexboxgrid (which @oliviertassinari mentioned having the same issues) has a fork that claims to have fixed it. https://github.com/kristoferjoseph/flexboxgrid/issues/144#issuecomment-321694572 I haven't dug into the code, but might be worth investigating to see if there's something we can use in Grid.

Hi,

We recently started adopting this library for one of our projects.

You can imagine our surprise when we found out this thread.

Basically this is a bug that's closed with no workarounds as of the latest material-next version. This is worrying.
Even more worrying is the idea that instead of fixing this bug, we now have text added in the docs talking about "a limitation".

Do you guys have any procedures regarding bugs and bugfixes? Or is everything decided on the spot?


This is the 1.0.0-prerelease:
https://github.com/mui-org/material-ui/issues?q=is%3Aopen+is%3Aissue+milestone%3Av1.0.0-prerelease

Extrapolating from this thread, shall we assume 1.0.0-prerelease actually has lots more bugs than what we see there? (i.e. this issue for example)

How many valid material-ui bugs did you guys close so far on github, and instead of fixing you added text in the docs?

Otherwise the framework is great. It's the procedures that are a bit worrying.

Thank you, and I apologise if I offended anyone and/or if I came a bit strong.

@kmlx

shall we assume 1.0.0-prereleasebeta actually has lots more bugs than what we see there?

You certainly should (see: Issues). And you should expect 1.0.0-rc.x to have bugs too, but the API will be mostly stable.

The timing of @ryanflorence's tweet is perfect.

I apologise if I offended anyone and/or if I came a bit strong.

If you know you're coming across a bit strong, don't apologize; rethink what it is you want to say, and how you want to say it. (And perhaps take a look at how much value you've got out of open source, vs. how much you've contributed, and decide if your complaint carries any weight.)

Better still, if the workarounds provided in the docs aren't sufficient, get stuck in to the CSS and see if you can resolve the limitation that's bothering you.

@mbrookes

Thank you for taking the time to reply.

You certainly should (see: Issues). And you should expect 1.0.0-rc.x to have bugs too, but the API will be mostly stable.

Glad to hear the API will be mostly stable. As any project, I assume there will be various undiscovered issues.

Still, at the moment the workarounds for this issue are not working and the issue itself is closed.
As per your previous message, this flexboxgrid fork might provide a solution.
I shall assume the commits starting from Aug 1st are the ones where one should be looking for a fix.

If the documented workarounds are no longer working, (I'm on mobile currently, so not able to test), then this issue needs to be reopened.

Thanks for looking into a fix.

I'm not having the issue btw, and my solution was to manually do spacing={0} in each <Grid container /> or <Grid item container /> component in my code.

@kmlx I have successfully tested the suggested workarounds with beta.22. Feel free to report back if you find a permanent solution.

I added spacing={0} but actually wanted spacing, so I added padding, and made it only add the padding above the medium breakpoint where it showed two columns:

const styles = theme => ({
  dividerRight: {
    [theme.breakpoints.up('md')]: {
      paddingRight: theme.spacing.unit * 0.5
    }
  },
  dividerLeft: {
    [theme.breakpoints.up('md')]: {
      paddingLeft: theme.spacing.unit * 0.5
    }
  },
});

Then I added className={classes.dividerRight} to the left column (since the divider is on the right) and className={classes.dividerLeft} to the right column

Just had this issue. Solved it with adding the following css to grid's container and it's looking good

.grid-container {
  width: 100% !important;
  margin: 0 !important;
}

@martjoao For me this resulted in unwanted padding around the outside of my grid container (I have elements inside that should be flush with the edges).

My quick and dirty solution to this was to just throw overflow-x: hidden; on the body element. But on certain browsers (mobile ones in particular) when you scroll the horizontal scrollbar flashes for a second, indicating to the user they can scroll right. This is still undesirable for me.


EDIT:

Just saw the the overflow approach was mentioned above. My bad.

I think it's worth noting that the intended usage of <Grid> is _not_ application/primary layout (e.g. app bar, side bar, content area etc). It's really intended for distributing content elements in a grid (e.g. a list of profiles). With that in mind, spacing elements with margins so that their content area is not affected - so you can e.g. add a background color or borders - makes sense.

But the documentation suggests that the <Grid> element should be used for primary layout by having a whole section named "Layout" describing the usage of <Grid>.

Another reason many people find this counterintuitive is because all other UI frameworks provide a mechanism for doing primary layout (which would be considered the 80% case, @oliviertassinari), and laying out a grid of content items is a secondary concern.

But the documentation suggests that the element should be used for primary layout by having a whole section named "Layout" describing the usage of .

@wmadden Why is using the layout wording makes you think it's about the app/primary layout?

Another reason many people find this counterintuitive

What's counterintuitive?

which would be considered the 80% case

I agree, we have: #10986 for that.

@wmadden Why is using the layout wording makes you think it's about the app/primary layout?

It's in a top-level section called "layout", rather than just a component demo. And phrasing like this:

The grid creates visual consistency between layouts while allowing flexibility across a wide variety of designs. Material Design’s responsive UI is based on a 12-column grid layout.

made me assume that it was appropriate to use it for laying out my application - where the negative margin limitation becomes a problem fast.

Another reason many people find this counterintuitive

I meant people find it counterintuitive that the Grid component shouldn't be used for primary layout, since UI frameworks typically provide a layout solution for that purpose - and it's usually in a top-level documentation topic called "layout".

It's a common assumption in React that children will be contained by their parent. The <Grid>'s negative margin breaks that assumption by extending beyond the boundaries of its parent, which makes its behavior look like a bug to anyone who's not aware that it's by design.

@vedant1811 The negative margin is no longer the default behavior. You should be able to use the Grid without it for your application level layout.

@oliviertassinari Was there an update that changed this? Just wondering if I need to update my version of the package. I was using the overflow: hidden; on the parent element workaround before.

@saricden Yes, by not providing a spacing property, most of the grid libraries available out there don't have this feature, they let people handle the margin.

I just ran into this. What seems to be another hacky but ok workaround is to put a width: 'calc(100% - 16px)' on the grid container... at least for my situation on small screen sizes.

Playing around with different widths for different breakpoints may improve this, but the problem far less noticeable when the screen yields a wider container.

Still have the same issue, but fixed by adding xs={12}.
<Grid container spacing={3} xs={12}>

This issue still occurs. Adding spacing={...} causes a horizontal scroll. Adding xs={12} doesn't solve it.

_For what it's worth:_
I'm running into this issue with Material-UI 4.5.0. For some reason I'm just now noticing this and I've been using Material-UI for over a year.

I tried the xs={12} suggestion above in addition to a margin style (because I was seeing extra margin on the right side), and the following produces the desired effect visually:

const useStyles = makeStyles(theme => ({
  grid: { margin: theme.spacing(0) }
}));
...
<Grid container spacing={2} xs={12} className={classes.grid}>

_However..._ I'm getting a warning in the console:

Warning: Failed prop type: The prop xs of Grid must be used on item.

So instead of using xs={12} on the container, I copied the styles it was adding to makeStyles(). The following seems to be doing the trick for me so far:

const useStyles = makeStyles(theme => ({
  grid: {
    margin: theme.spacing(0),
    flexGrow: 0,
    maxWidth: `100%`,
    flexBasis: `100%`
  }
}));
...
<Grid container spacing={2} className={classes.grid}>

It is only maxWidth: 100%, that made this work. however, the width is now stretched to the maximum. this will not work if i set a specific maxWidth value.

I've fixed this using styled components in order to set the Grid container margin to zero.

Styled Grid container:

const GridContainer = styled(Grid)`
  margin: 0;
`;

Now GridContainer is used, instead of the Grid component that was generating the extra width.

      <GridContainer
        container
        direction="column"
        justify="center"
        alignItems="center"
        xs={12}
        spacing={2}
      >

I used the component inside of a 100% width & height wrapper, but I ran into this issue where the container stretches the page out past 100vw and causes a horizontal overflow. I don't understand why a negative margin is used for this? I had to override the default styles to bring the page back into bounds:

const NormalizedGridContainer = withStyles(theme => ({
  root: {
    width: '100%',
    margin: '0px',
    padding: `${(spacing/2) * 8}px`
  }
}))(Grid);

IMO it should be made a little more obvious that Grid containers are not meant to be used as the wrapper of an application.

In desktop size I have images stretching all away to the side and fixing with xs={12} strangely made a padding appear. In my case the fix looks like @martjoao 's solution but only mobile width:
gridSpacingFix: { '@media (max-width:600px)': { width: '100% !important', margin: '0 !important', }, },

I met a similar issue, and fixed by:

body { margin: 0; padding: 0; }

Ended up doing below:

const theme = createMuiTheme({
  overrides: {
    MuiGrid: {
      container: {
        width: "100% !important",
        margin: "0 !important"
      }
    },
  }
});

This solves the issue.

was just facing that issue as well and looking at the amount related issues i was wondering if it makes sense to fix this in material-ui.

Couldn't we essentially do the same as they do here: https://github.com/evgenyrodionov/flexboxgrid2/commit/37e02fec7674495782098fb8e9a2c6d20a2786e1#diff-4b62e0ae269a54df45ab5eab9cb7821b ?

Ran into the same issue, found a semi-fix by doing

<Container maxWidth={false}>
  <Grid container spacing={3}>
    <Grid item />
  </Grid>
</Container>

Still have the same issue, but fixed by adding xs={12}.
<Grid container spacing={3} xs={12}>

This fixed it fo me... thanks!

Still have the same issue, but fixed by adding xs={12}.
<Grid container spacing={3} xs={12}>

This fixed it fo me... thanks!

Awesome solution! This fixed it for us, too. We had to add container item to prevent a container + xs warning.

issue resolved after adding overflow-x: hidden; on the parent, like inside Container have mui-datatable, so added overflowX: 'hidden' to container

Ended up doing below:

const theme = createMuiTheme({
  overrides: {
    MuiGrid: {
      container: {
        width: "100% !important",
        margin: "0 !important"
      }
    },
  }
});

This solves the issue.

Thanks, this was the only working solution for me.

_Seems_ to work for me to omit the margin 0 !important


const theme = createMuiTheme({
  overrides: {
    MuiGrid: {
      container: {
        width: "100% !important",
        // margin: "0 !important"
      }
    },
  }
});

It's baffles me this ui framework has so many bugs. Your

Grid should belong ANYWHERE. Bootstrap allows it everywhere without issues. They even have offsets to deal with these margin bugs.

Is this ever going to get fixed?

@SomnathKadam

issue resolved after adding overflow-x: hidden; on the parent, like inside Container have mui-datatable, so added overflowX: 'hidden' to container

The problem with this is that you can still scroll. overflow-x: hidden is not a good solution

MuiGrid: {
container: {
width: "100% !important",
margin: "0 !important"
}
},
@rag4214
This is forcibly modifying the structure of the whole framework and is not recommended. You might fix it on one place, break it on another.

I am shocked, I've been using MUI for maybe 2 years and never seen this before. Still not worked out why its happened.

Ended up doing below:

const theme = createMuiTheme({
  overrides: {
    MuiGrid: {
      container: {
        width: "100% !important",
        margin: "0 !important"
      }
    },
  }
});

This solves the issue.

This solution works for me.

This has been going on for so long it should be part of the documentation if a fix is not immediately possible.

Is there any fix yet?
I am having this issue and thinking of using overflow-x: hidden, What do you think?

The problem is still there. The solution overflow-x: hidden property on the parent

Just another hack for this, which works for me ;)

const useStyles = makeStyles((theme) => ({
 root: {
    '& .MuiGrid-root': {
      width: 'calc(100% - 2px)',
    },
  },
// [...]

those 2px seems to be added somewhere below my grid definition, so the actual value could be different for other people...

Was this page helpful?
0 / 5 - 0 ratings