I have a problem with the order of stacking of grid items whenever browser shrinks.
This is what I want on the normal desktop screen(lg):
---------------------------------------------
| col 1 | col 2 | col 3 |
---------------------------------------------
But After Shrinking the browser I am getting the following result:
-------------------------
| col 1 |
-------------------------
-------------------------
| col 2 |
-------------------------
-------------------------
| col 3 |
-------------------------
Can I with material ui Grid layout achieve this on a mobile screen:
-------------------------
| col 1 |
-------------------------
-------------------------
| col 3 |
-------------------------
-------------------------
| col 2 |
-------------------------
I have read articles on changing the order of CSS-grids for the same topic but how to achieve this using material-ui Grid layout.
Edit: I have revised the answer for MUI Core v5
<Grid container spacing={16} justify="flex-start">
<Grid item xs={12} sm={6} md={4} lg={4}>
<Paper>
<h1>{1}</h1>
</Paper>
</Grid>
<Grid item xs={12} sm={6} md={4} lg={4} order={{ xs: 3, sm: 2 }}>
<Paper>
<h1>{2}</h1>
</Paper>
</Grid>
<Grid item xs={12} sm={6} md={4} lg={4} order={{ xs: 2, sm: 3 }}>
<Paper>
<h1>{3}</h1>
</Paper>
</Grid>
</Grid>
https://codesandbox.io/s/xvv7o07614?file=/src/GridStacking.js
Extending to Olivier's answer Material-UI heavily uses the CSS flexbox layout within its implementation. As the documentation quotes
A flex container is the box generated by an element with a computed display of flex or inline-flex. In-flow children of a flex container are called flex items and are laid out using the flex layout model.
So Grid items are flex items and Grid Container is flexbox container in laymans language. Hence we can use the order property on Grid items to change their relative order of appearance when the Box or Grid Container resizes. So passing the style in the following manner to the grid item should work out
itemStyle: {
order: ${Desired_order_before_Shrinking},
[theme.breakpoints.up(`${DesiredScreenSize}`)]: {
order: ${Desired_order_after_Shrinking},
},
}
Finally doing <Grid item xs={12} md={6} className={this.props.classes.itemStyle}> will reorder that item. Hope it creates better understanding.
UPDATE:
Material UI V5. Thanks to #Adam Cooper's answer below
<Grid container spacing={2}>
<Grid item md={12} lg={4} order={{ md: 1, lg: 1 }}>col 1</Grid>
<Grid item md={12} lg={4} order={{ md: 3, lg: 2 }}>col 2</Grid>
<Grid item md={12} lg={4} order={{ md: 2, lg: 3 }}>col 3</Grid>
</Grid>
With material-ui v5 this can be achieved more elegantly using the order prop together with the new responsive style system:
<Grid container spacing={2}>
<Grid item md={12} lg={4} order={{ md: 1, lg: 1 }}>col 1</Grid>
<Grid item md={12} lg={4} order={{ md: 3, lg: 2 }}>col 2</Grid>
<Grid item md={12} lg={4} order={{ md: 2, lg: 3 }}>col 3</Grid>
</Grid>
Related
In the following image the blue block is rendered under the red and green blocks. I would like the blue block to render directly underneath the red block.
Is there a way to achieve this with MUI grid?
import * as React from "react";
import Box from "#mui/material/Box";
import Grid from "#mui/material/Grid";
export default function BasicList() {
return (
<Box>
<Grid container>
<Grid item alignContent="center" justifyContent="center" md={6}>
<Box style={{backgroundColor:"red"}} height={200}>
MD = 6 Height = 200
</Box>
</Grid>
<Grid item md={6}>
<Box style={{backgroundColor:"green"}} height={600}>
MD = 6 Height = 600
</Box>
</Grid>
<Grid item md={6}>
<Box style={{backgroundColor:"blue"}} height={200}>
MD = 6 Height = 200
</Box>
</Grid>
</Grid>
</Box>
);
}
You should put both Red and Blue boxes together as one grid. something like this can solve the problem:
import * as React from "react";
import Box from "#mui/material/Box";
import Grid from "#mui/material/Grid";
export default function BasicList() {
return (
<Box>
<Grid container>
<Grid item alignContent="center" justifyContent="center" md={6}>
<Box style={{backgroundColor:"red"}} height={200}>
MD = 6 Height = 200
</Box>
<Box style={{backgroundColor:"blue"}} height={200}>
MD = 6 Height = 200
</Box>
</Grid>
<Grid item md={6}>
<Box style={{backgroundColor:"green"}} height={600}>
MD = 6 Height = 600
</Box>
</Grid>
</Grid>
</Box>
);
}
Each grid can be responsible for a column in your design.
Here's what I am able to create
My UI
And here is what I want to achieve:
The aspiration
Here's my code:
<Grid container spacing={3}>
<Grid item md={4} xs={15}></Grid>
<Grid item md={4} xs={15}></Grid>
<Grid item md={4} xs={15}></Grid>
<Grid item md={3} xs={15}><TrashIcon> <AddIcon></Grid>
</Grid>
Additional (Edited)
How do I align the grid fields in the bottom to the ones on top rows?
new confusion but have a limit on questions per hour
You can use auto-layout feature of the Grid:
The Auto-layout makes the items equitably share the available space.
That also means you can set the width of one item and the others will
automatically resize around it.
<Grid container spacing={3}>
<Grid item md xs={12}>
<input style={{ width: "100%" }} />
</Grid>
<Grid item md xs={12}>
<input style={{ width: "100%" }} />
</Grid>
<Grid item md xs={12}>
<input style={{ width: "100%" }} />
</Grid>
<Grid item md="auto" xs={12}>
<TrashIcon /> <AddIcon />
</Grid>
</Grid>
Working example
I am using MUI Grid structure in ReactJs to display 5 columns like this:
In smaller screens the columns are moving in the next row. But In smaller screens I also want all the columns to show in one row only and I can access other columns by scrolling horizontally.
<Grid
container
spacing={2}
style={{
maxHeight: "100vh",
overflowY: "auto",
overflowX: "hidden",
height: "440px",
overflow: "auto",
}}
>
<Grid item xs={2.1}>
{cards.map((card) => <Card props={card} /> )}
</Grid>
</Grid>
Because Grid uses flexbox under the hood. You can simply set the wrap value to nowrap in your Grid container, you can see the full API of Grid component here.
<Grid
container
wrap="nowrap" // --> add this line to disable wrap
sx={{ overflow: "auto" }} // --> add scrollbar when the content inside is overflowed
spacing={8}
>
{...}
</Grid>
Live Demo
The Grid is based on a 12-column grid layout. Therefore xs accepts only the following values:
'auto' | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12.
I would recommend you to place an empty grid with an xs size equal to 1 at the beginning and end. That brings you to a total size of xs equal to 12.
<Grid
container
spacing={2}
style={{
maxHeight: "100vh",
overflowY: "auto",
overflowX: "hidden",
height: "440px",
overflow: "auto",
}}
>
<Grid item xs={1}/>
{cards.map((card) => (
<Grid item xs={2}>
<Card props={card} />
</Grid>
))}
<Grid item xs={1}/>
</Grid>
I am designing a page that needs to be rendered in large, medium and small screens responsively. I am using Material ui Grid container and inside that displaying Chips with style={{ marginLeft: 60 }} from second chip onward to keep a distance between first-second,second-third and so on but as soon as my screen size changes, these chips are getting overlapped on each other but no responsive behavior. Below is my code
<Grid container item xs={12}>
<Grid container item xs={11}>
<Grid item xs={2}>
<Chip/>
</Grid>
<Grid item xs={2} style={{ marginLeft: 60 }}>
<Chip/>
</Grid>
<Grid item xs={2} style={{ marginLeft: 60 }}>
<Chip/>
</Grid>
<Grid item xs={2} style={{ marginLeft: 60 }}>
<Chip/>
</Grid>
<Grid item xs={2} style={{ marginLeft: 57 }}>
<Chip/>
</Grid>
</Grid>
</Grid>
How to get my design correct? Please suggest. Thanks..
You're declaring static margin sizes in pixels which will not shrink with the screen size. Either change them to relative sizes (e.g., style={{ marginLeft: '5%' }}), or assign the grids a className property and use media queries in your CSS file to set breakpoints at the required screen sizes.
The latter option will provide you with much more control if responsiveness is a requirement.
I am trying to understand Material-UI#next grid layout system.
My goal is to have two papers that expand through the whole width screen and break whenever the screen gets smaller to just one paper. The documentation has the following code snippet:
<Container>
<Grid container spacing={24}>
<Grid item xs={12}>
<Paper>xs=12</Paper>
</Grid>
<Grid item xs={12} sm={6}>
<Paper>xs=12 sm=6</Paper>
</Grid>
<Grid item xs={12} sm={6}>
<Paper>xs=12 sm=6</Paper>
</Grid>
<Grid item xs={6} sm={3}>
<Paper>xs=6 sm=3</Paper>
</Grid>
<Grid item xs={6} sm={3}>
<Paper>xs=6 sm=3</Paper>
</Grid>
<Grid item xs={6} sm={3}>
<Paper>xs=6 sm=3</Paper>
</Grid>
<Grid item xs={6} sm={3}>
<Paper>xs=6 sm=3</Paper>
</Grid>
</Grid>
</Container>
This results in the following:
I then modified the code to try to achieve my goal of just two papers, as this:
<Container>
<Grid container spacing={24}>
<Grid item xs={12} sm={6}>
<Paper>xs=12 sm=6</Paper>
</Grid>
<Grid item xs={12} sm={6}>
<Paper>xs=12 sm=6</Paper>
</Grid>
</Grid>
</Container>
But as you can see, this results into two papers which are not taking the whole screen:
Can someone point me to a working example snippet that allows me to have two elements that take the full width?
I suspect the Container component is causing you problems. Since you haven't linked its implementation, see below for a working example of what you want.
Since Material uses flexbox they make use of property flexGrow
The flex-grow CSS property specifies the flex grow factor of a flex item. It specifies what amount of space inside the flex container the item should take up. The flex grow factor of a flex item is relative to the size of the other children in the flex-container.
This is the property that governs the growth of elements in the grid.
import React from 'react';
import PropTypes from 'prop-types';
import { withStyles } from 'material-ui/styles';
import Paper from 'material-ui/Paper';
import Grid from 'material-ui/Grid';
const styles = theme => ({
root: {
flexGrow: 1,
},
paper: {
padding: theme.spacing.unit * 2,
textAlign: 'center',
color: theme.palette.text.secondary,
},
});
function CenteredGrid(props) {
const { classes } = props;
return (
<div className={classes.root}>
<Grid container spacing={24}>
<Grid item xs={12} sm={6}>
<Paper>xs=12 sm=6</Paper>
</Grid>
<Grid item xs={12} sm={6}>
<Paper>xs=12 sm=6</Paper>
</Grid>
</Grid>
</div>
);
}
CenteredGrid.propTypes = {
classes: PropTypes.object.isRequired,
};
export default withStyles(styles)(CenteredGrid);
Best practice is to test out all break points and specify the allocation of space for each screen width.
<Grid item xs={12} sm={12} md={12} lg={6} xl={4}>
</Grid>
xs, extra small 0px
sm, small: 600px
md, medium: 960px
lg, large: 1280px.
xl,extra-large: 1920px
https://material-ui.com/customization/breakpoints/
xs Defines the number of grids the component is going to use. It's applied for all the screen sizes with the lowest priority.
sm Defines the number of grids the component is going to use. It's applied for the sm breakpoint and wider screens if not overridden.
md Defines the number of grids the component is going to use. It's applied for the md breakpoint and wider screens if not overridden.
(and so forth)
more here: https://material-ui.com/api/grid/
For those using Material UI with styled-components, here's how I was able to get the grid items to grow correctly:
import GridBase from "#material-ui/core/Grid";
const Grid = styled(GridBase)`
.MuiGrid-root {
flex-grow: 1;
}
`
Now you can use Grid normally in your components.
I know this is old question , but just want to share.
The problem from your code is spacing={24}
based on documentation Spacing . By default, the spacing between two grid items follows a linear function: output(spacing) = spacing * 8px
e.g. spacing={24} creates a 192px wide gap. so at the end , the space available for the content very small.
<Grid container spacing={2}> // usually 2 or 3 is quite enough for me
<Grid item xs={12} sm={6}>
<Paper>xs=12 sm=6</Paper>
</Grid>
<Grid item xs={12} sm={6}>
<Paper>xs=12 sm=6</Paper>
</Grid>
</Grid>
I was also experiencing this issue. What solved it for me is using the "sx" property to make the width of the parent grid = 100%. See code below:
<Box sx={{ width: '100%' }}>
<Button variant="contained" fullWidth> myButton </Button>
</Box>