I am just learning Material UI with react. Starting with V5.
I have a basic 12 column grid just to learn this.
The spacing is just not working properly. It is just creating a weird padding on the grid items where the items themselves are getting internal padding and I don't see the gutters.
I tested it on the most basic example to ensure its as simple to see:
Here is the code:
//MuiGrid.js
import React from 'react'
import {Grid, Typography, Box} from '#mui/material';
export default function MuiGrid() {
return (
<Box>
<Typography variant='h2'>MUI Grid!</Typography>
{/* Testing Grid Spacing */}
<Box component='section'>
<Typography variant='h5'>Testing Spacing</Typography>
<Box>
<Grid container spacing={2}>
<Grid item sx={{backgroundColor: 'primary.dark'}}>Item 1</Grid>
<Grid item sx={{backgroundColor: 'primary.main'}}>Item 2</Grid>
<Grid item sx={{backgroundColor: 'primary.light'}}>Item 3</Grid>
</Grid>
</Box>
</Box>
</Box>
)
}
I have managed to reproduce this with my first sandbox.
Here is the link:
https://codesandbox.io/s/quirky-lake-50pqf5?file=/src/Demo.tsx
Here are the screenshots before & after spacing is applied, it shows just odd padding:
All the documentation is very vague and only shows basic information & I can't see what I have done wrong here
Edit 2:
I tried to make spacing 0 and add padding as suggested by the answer, that works well to provide padding but I can't get gutters
See code:
<Box component='section'>
<Typography variant='h5'>Testing Spacing</Typography>
<Box>
<Grid container spacing={0}>
<Grid p={1} item sx={{backgroundColor: 'primary.dark'}}> <Box>Item 1</Box></Grid>
<Grid p={1} item sx={{backgroundColor: 'primary.main'}}><Box>Item 2</Box></Grid>
<Grid p={1} item sx={{backgroundColor: 'primary.light'}}><Box>Item 3</Box></Grid>
</Grid>
</Box>
</Box>
Result:
Also here is the link to GitHub issue I have created: https://github.com/mui/material-ui/issues/31244
I have added background to the container and coloured the box inside the items, this provides a better idea about what is happening:
<Box component='section'>
<Typography variant='h5'>Testing Spacing</Typography>
<Box>
<Grid container spacing={2}
sx={{backgroundColor: 'secondary.main'}}
>
<Grid item> <Box sx={{backgroundColor: 'primary.dark'}}>Item 1</Box></Grid>
<Grid item><Box sx={{backgroundColor: 'primary.main'}}>Item 2</Box></Grid>
<Grid item><Box sx={{backgroundColor: 'primary.light'}}>Item 3</Box></Grid>
</Grid>
</Box>
</Box>
Result:
Spacing can indeed be a bit confusing with Grid.
I usually set spacing(0) for the Grid container and handle padding / margin by the content of each Grid item
<Grid container spacing={0}>
<Grid item>
<Box p={1}>Item 1</Box> // use m={1} if you want margin
</Grid>
<Grid item>
<Box p={1}>Item 2</Box>
</Grid>
<Grid item>
<Box p={1}>Item 3</Box>
</Grid>
</Grid>
Alternatively, if you want to use spacing(2) you can account for the spacing's offset and wrap your Grid container in a Box that manages this offset.
<Box m={xs ? -1 : -3}> // pseudo code check
<Grid container spacing={2}>
<Grid item xs={12} sm={4}>Item 1</Grid>
<Grid item xs={12} sm={4}>Item 2</Grid>
<Grid item xs={12} sm={4}>Item 3</Grid>
</Grid>
</Box>
Personally, I'm not a huge fan of this approach. I like using Grid for mobile flexibility and with the margin-offset approach, you have to keep good track of how many grid items you have per row, and then adjust the box margin based on this.
The behavior of the MUI grid spacing is a bit unexpected since it moves the grid items to the bottom right. To keep the grid items centered you'll need to manually add paddings to the right and bottom of the container or items.
One option is simply to add the same amount of spacing as padding to the right and bottom of the grid. The drawback is that you' ll have to calculate the proper amount of padding, if your grid container itself has already a padding.
The second option is to make the grid items context aware and add right padding to the last items in a grid row when the row is full. This will still leave you with the task to calculate the proper bottom padding of the grid.
It would be more intuitive if the calculations of the right and bottom paddings were done internally by the MUI grid.
However, here is a simple Wrapper component that adjusts the right padding of the outer grid items in order to center the items horizontally. You'll only have to add addtional padding at the bottom of the grid.
EDIT
Actually I realized that the intial approach with adding padding just to the last columns also changes the width of the last element. So here is a much simpler approach by overriding the MUI spacing and just add half of the spacing to the left and right of all the elements. The code becomes also much simpler.
import { Breakpoint, GridSize, GridSpacing } from '#mui/material';
import { FC, ReactElement, cloneElement } from 'react';
type GridWrapperSettings = {
spacing: GridSpacing;
columns: { [key in Breakpoint]?: GridSize };
};
export const GridWrapper: FC<GridWrapperSettings & { children?: ReactElement }> = (props) => {
if (!props.children) {
return <></>;
}
// remove MUI spacing
const grid = cloneElement(props.children, {
spacing: 0,
});
// adjust items
const items = grid.props.children.map((c) => {
return cloneElement(c, {
// assign responsive column settings
xs: props.columns.xs,
sm: props.columns.sm,
md: props.columns.md,
lg: props.columns.lg,
xl: props.columns.xl,
// assign half of the spacing on each side and a full spacing at the bottom
sx: {
pr: 0.5 * (props.spacing as number),
pl: 0.5 * (props.spacing as number),
pb: props.spacing,
},
},
});
});
return cloneElement(grid, {
children: items,
});
};
When using you only have to set the spacing and columns once in the wrapper:
<GridWrapper spacing={4} columns={{ xs: 12, md: 6}}>
<Grid
container
direction="row"
justifyContent="center"
alignItems="stretch"
>
<Grid item>My Item</Grid>
<Grid item>My Item</Grid>
</Grid>
</GridWrapper>
Related
I want to design my layout something like this using material UI, I have look into it and thinking of using Grid component, but how do I implement something like this for the middle column into two rows??
Example Code
I'm using Material UI's Grid component in the following code.
import React from "react";
import { makeStyles } from "#material-ui/core/styles";
import Grid from "#material-ui/core/Grid";
import clsx from "clsx";
const useStyles = makeStyles({
container: {
height: "100%", // So that grids 1 & 4 go all the way down
minHeight: 150, // Give minimum height to a div
border: "1px solid black",
fontSize: 30,
textAlign: "center"
},
containerTall: {
minHeight: 250 // This div has higher minimum height
}
});
export default function App() {
const classes = useStyles();
return (
<Grid container direction="row" spacing={2}>
<Grid item xs>
<div className={classes.container}>1</div>
</Grid>
<Grid item container direction="column" xs spacing={2}>
<Grid item xs>
<div className={classes.container}>2</div>
</Grid>
<Grid item xs>
<div className={clsx(classes.container, classes.containerTall)}>
3
</div>
</Grid>
</Grid>
<Grid item xs>
<div className={classes.container}>4</div>
</Grid>
</Grid>
);
}
The above code will generate the following result:
Explanation
The overall grid structure looks like:
<Grid container direction="row">
<Grid item xs />
<Grid item xs container direction="column">
<Grid item xs />
<Grid item xs />
</Grid>
<Grid item xs />
</Grid>
We first create a grid container with flex direction of row. Inside the container, we put 3 Grid item components so that they align from left to right. For the second (middle) Grid item, we also define it as a container with flex direction of column. Inside it, we place two Grid items such that one is on top and one is on bottom.
Note that particularly for grid 3's code, I added className={clsx(classes.container, classes.containerTall)}. This is basically saying that we would apply classes.container and classes.containerTall to this grid. You can read this section on more about clsx().
To make grid 3 slightly taller than grid 2, I've set the minHeight of grid 2 to be 150px while the minHeight of grid 3 is set to be 250px.
You can use Auto layout from here
https://material-ui.com/components/grid/#auto-layout
Structure should be
Col
Col
---- Row (3 size)
---- Row (3 size)
Col
I want to use MUI Grid and I wanted to hide one item Grid if the screen is small, so I found something called Display. My code looks like this:
function CRUDView() {
return (
<Grid
container
spacing={1}
direction="row"
justify="center"
alignItems="center"
>
<Grid item xs={12} lg={6}>
<span>XX</span>
</Grid>
<Grid item xs={6} display={{ xs: "none", lg: "block" }} >
<span>YY</span>
</Grid>
</Grid>
);
}
I donĀ“t uderstand why it doesn't work (the text YY still appears) . Can't I use display with Grid maybe? If yes then why?
The style functions are not automatically supported by the Grid component.
The easiest way to leverage the style functions is to use the Box component. The Box component makes all of the style functions (such as display) available. The Box component has a component prop (which defaults to div) to support using Box to add style functions to another component.
The Grid component similarly has a component prop, so you can either have a Grid that delegates its rendering to a Box or a Box that delegates to a Grid.
The example below (based on your code) shows both ways of using Box and Grid together.
import React from "react";
import ReactDOM from "react-dom";
import Grid from "#material-ui/core/Grid";
import Box from "#material-ui/core/Box";
import { makeStyles } from "#material-ui/core/styles";
const useStyles = makeStyles({
gridItem: {
border: "1px solid red"
}
});
function App() {
const classes = useStyles();
return (
<Grid
container
spacing={1}
direction="row"
justify="center"
alignItems="center"
>
<Grid className={classes.gridItem} item xs={12} lg={6}>
<span>XX</span>
</Grid>
<Box
component={Grid}
className={classes.gridItem}
item
xs={3}
display={{ xs: "none", lg: "block" }}
>
<span>YY</span>
</Box>
<Grid
component={Box}
className={classes.gridItem}
item
xs={3}
display={{ xs: "none", lg: "block" }}
>
<span>ZZ</span>
</Grid>
</Grid>
);
}
const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);
For MUI v5:
In MUI v5 the <Hidden> tag got deprecated in favor for sx.display property withing <Grid> and <Box> tags - display documentation.
For MUI v4 and earlier:
MUI exposes a <Hidden> component to achieve this. Just wrap component you want to hide for specific screen size:
<Hidden xsDown >
<p>Hide me on XS view port width.</p>
</Hidden>
You can find more examples in the hidden documentation.
In MUI v5, you can change the display value directly on Grid without having to use Box anymore:
<Grid
item
xs={3}
sx={{
display: { xs: "none", lg: "block" }
}}
>
<span>YY</span>
</Grid>
Grid Items just setup your layout.
They don't actually display anything. The MUI display option is for hiding specific elements.
Try this:
function CRUDView() {
return (
<Grid
container
spacing={1}
direction="row"
justify="center"
alignItems="center"
>
<Grid item xs={12} lg={6}>
<span>XX</span>
</Grid>
//removed from the below Grid Item
<Grid item xs={12} lg={6}>
<span display={{ xs: "none", lg: "block" }}>YY</span>
</Grid>
</Grid>
);
}
That will hide the individual span element even though the grid is still there.
I am trying to have 3 horizontal cards with the same height and it must be responsive. So the issue is coming that if the content of one card is larger than the other's, the card's height is not the same and one card look's bigger in height than the other. So I generally want a fixed height of these 3 cards so that whether the content is less or more, all the 3 cards must have the same height accordingly.
I am using "Material-UI" in this and used the Card component from it.
<Grid container spacing={2}>
<Grid item>
<Card>
Card 1
</Card>
</Grid>
<Grid item>
<Card>
Card 2
</Card>
</Grid>
<Grid item>
<Card>
Card 3
</Card>
</Grid>
</Grid>
If I tried using Grid's component as "Card", then it works fine with the height of all the cards are constant regardless of content present inside them. But then I cannot provide spacing between the cards and hence the structure looks quite compact.
<Grid container spacing={2}>
<Grid item component="Card">
Card 1
</Grid>
<Grid item component="Card">
Card 2
</Grid>
<Grid item component="Card">
Card 3
</Grid>
</Grid>
You can try
<Card style={{ height: '100%' }}>
I'm using the material UI react components, particularly the problem seems to be about the Grid component. I'm getting a very weird space as shown in the image and I cannot find out where it is coming from.
I've reduced the problem to the minimum possible and now it's just a Grid inside a Grid that contains two images.
<Grid container direction={"column"} style={{ "background-color": "red" }}>
<Grid item>
<Grid container style={{ "background-color": "blue" }}>
<Grid item xs={11} style={{ "background-color": "purple" }}>
<CustomImg />
<CustomImg />
</Grid>
</Grid>
</Grid>
</Grid>
I don't understand where the red space is coming from.
A clue: If I change the <Grid item xs={11} to be xs={12} or remove the whole xs={...} then the space goes away....
Here is the codesanbox so you can hopefully tell me what I am doing wrong:
https://codesandbox.io/s/x7q8q0rr5z
After playing in your sandbox, I believe it's caused by you having the two CustomImg components in the inner Grid item. If you have one, it goes away. Hopefully this helps.
I'm using Material-UI version 1. installed by this command:
npm install -S material-ui#next
Everytime I want to use , an unwanted horizontal scroll appears in the page.
Code:
import React from 'react';
import PropTypes from 'prop-types';
import { withStyles, createStyleSheet } from 'material-ui/styles';
import Paper from 'material-ui/Paper';
import Grid from 'material-ui/Grid';
/* project imports */
import NavMenu from './Page-Parts/NavMenu';
import LoginPanel from './Login-Parts/LoginPanel';
const styleSheet = createStyleSheet('FullWidthGrid', theme => ({
root: {
flexGrow: 1,
marginTop: 0,
},
paper: {
padding: 16,
textAlign: 'center',
color: theme.palette.text.secondary,
marginTop: "3rem"
},
}));
function Login(props) {
const classes = props.classes;
return (
<div className={classes.root}>
<Grid container gutter={24} justify='center'>
<Grid item xs={12} md={12} sm={12} lg={12}>
<NavMenu/>
</Grid>
<Grid item xs={6} sm={6} md={6} lg={6}>
<Paper className={classes.paper}>
<LoginPanel />
</Paper>
</Grid>
</Grid>
</div>
);
}
Login.propTypes = {
classes: PropTypes.object.isRequired,
};
export default withStyles(styleSheet)(Login);
Bootstrap and other grid layout options are in conflict with this library. When I use <Grid> in other parts of a component(for example in drawer), horizontal scroll appears makes the UI ugly
NavMenu and LoginPanel are some self-made components and they work and using them without doesn't cause horizontal scroll.
I had the same issue. I figured out a couple solutions but neither feel very elegant:
Disable spacing
Unfortunately this removes all padding from child grid items within the container:
<Grid container
spacing={0}>
Manually fix the CSS
This is what I ended up doing:
<Grid container
style={{
margin: 0,
width: '100%',
}}>
Copied the easy solution from comment:
added xs={12} to <Grid container>
<Grid container spacing={3} xs={12}>
credit to https://github.com/mui-org/material-ui/issues/7466#issuecomment-509150645
This is caused by spacing. Sometimes we can still use spacing by limiting the Grid under a Container.
<Container maxWidth={false}>
<Grid container spacing={6}>
Omit
</Grid>
</Container>
The best solution here is to wrap the grid in a container with the max width
<Container>
<Grid container spacing={2}>
<Grid item sm={6}></Grid>
<Grid item sm={6}></Grid>
<Grid item sm={6}></Grid>
<Grid item sm={6}></Grid>
</Grid>
</Container>
This way the overflow is taken care by the container and the grid always expands responsively into the parent. This by far is the most elegant solution I have found.
Tip: If your are using this library to create something like a dashboard then always have the parent for content area as <Container>, This way the overflow problem never occurs. Give it a shot. Worked well for me after struggling for some time and only finding non elegant solution everywhere. I must say this should be documented well in the react Material UI pages.
This worked for me!
<Box style={{overflow: 'auto'}}>
<Grid>...</Grid>
</Box>
The root issue is now fixed in the latest version of Material-UI (v5.0.0-alpha.30). See https://github.com/mui-org/material-ui/issues/7466#issuecomment-820736245.
I was facing the same issue. Remove spacing from the Grid container didn't solve it.
Solution:
Instead of setting with on the parent of the Grid container, setting maxWidth fixes the issues and assigns the desired width. For example, if we set maxWidth on the Box that is the parent of Grid container, then the Grid doesn't overflows horizontally.
We don't need to set width 100% on the Grid container because its purpose is to adapt to 100% width by default.
<Box style={{ maxWidth: 600}}>
<Grid container spacing={3}>
...
</Grid>
</Box>
well the idea i came up is
<Grid container>
<Grid item xs={12} md={4}>
<div style={{width:"97%",margin:"0 auto"}}>
.....Your content
</div>
</Grid>
<Grid item xs={12} md={4}>
<div style={{width:"97%",margin:"0 auto"}}>
.....Your content
</div>
</Grid>
<Grid item xs={12} md={4}>
<div style={{width:"97%",margin:"0 auto"}}>
.....Your content
</div>
</Grid>
</Grid>
This is a known limitation of the grid with negative margins. https://material-ui.com/components/grid/#limitations.
Don't use Grid spacing and manually configure your spacing.
Add padding equal to at least half of the spacing to the parent, For Example:
12 = 3 (spacing) * 8 (theme spacing pixels) / 2
<Box p={12}> {/* or style={{ padding: 12 }} */}
<Grid ... spacing={3}>
..additional configuration
</Grid>
</Box>
The downside to this solution is that it changes the look of the component.
set overflow-x: hidden
<Box style={{overflowX: "hidden"}}>
<Grid ... spacing={3}>
..additional configuration
</Grid>
</Box>
The downside to this solution is that it (in my testing) causes issues with touchscreens trying to scroll vertically...
For some reason none of the answers worked for me, I fixed it in Container like this:
<Container component="div" sx={{ maxWidth: "100vw" }}>
<Grid container spacing={3}>
...
</Grid>
</Container>