I am trying to create a grid with a bunch of elements but there seems to be a problem when I add spacing to the elements. Here's a picture with spacing={0} on the Grid container:
Grid container with no spacing
Here's the result when adding spacing :
Grid container with spacing = 3
I am trying to keep the grid the same width as the buttons above (see picture). I tried different solutions but it does not seem to work on my side. Here is my code :
return (
<Grid
sx={{
width: "100vw",
overflowX: "hidden",
padding: { xs: "20px", md: "50px" },
margin: 0,
background: "hsl(0, 0%, 98%)",
}}
container
>
<Grid
sx={{ width: "100%", marginBottom: "30px" }}
item
display="flex"
flexWrap={"wrap"}
justifyContent={"space-between"}
gap={"25px"}
>
<SearchInput />
<FilterMenu />
</Grid>
<Grid container spacing={3} xs={12}>
{countries?.map((country, idx) => (
<Grid item xs={3}>
<CountryCard key={idx} country={country} />
</Grid>
))}
</Grid>
</Grid>
The easiest and correct way in my opinion based on your images, would be to separate your Grid containers. One Grid containing the Search and Filter inputs and another to contain your flags. In this way you can keep a better control of your spacing and use let css customisations in the Grid items. Have a look in this codesandbox where i have left a few comments and let me know it it helps.
Related
I'm stuck with a CSS grid issue. I've it in a React application using <Grid /> inMaterial UI with a legend and a data table under it.
The chart, for different students, shows all the courses they have taken during their stay at the university. Number of courses a student has taken can vary from 1 to 40 something. Hence the legend is required to be dynamic in size.
This is the code for the component:
import Grid from '#material-ui/core/Grid';
<Grid item xs={12} className={classes.courseList}>
<Grid container>
{courses.map((e, i) => (
<Grid key={i}>
<Grid container justifyContent="center">
<Button
className={classes.course}
>
<span style={{ color: colorList[i] }}>⬤</span>
{`${i + 1} - ${UpperFirst(e.courseName)}`}
</Button>
</Grid>
</Grid>
))}
</Grid>
</Grid>
I've the following code in my styles.ts for the legend's div:
root: {
flexGrow: 1,
},
courseList: {
height: 120,
borderTop: '1px solid #f2d9f2',
"float": 'left',
},
course: {
padding: '0 4px',
cursor: 'pointer',
border: 'none',
selected: {
backgroundColor: 'white',
},
},
The height in this case is fixed to 120px, which makes the rest of the legend hide behind the data table if data overflows 3 rows.
How can I make it dynamic so that its height can grow/shrink to accommodate large number of dynamic legend data?
Here are two screenshots, first one showing data hidden behind data table, while the second one has width increased to show more data.
More Data Visible On Expansion:
I'm using material UI and I have a grid sitting on top of a Paper element. The first column in the grid is a text input field that I'd to be the same height as the paper and I'd like it pushed left so that it shares the left border with the paper element but I'm not sure how to achieve this affect, I've tried setting 0 margins, changing the position, and messing with the height and width to no affect.
Code pen: https://codesandbox.io/s/laughing-ardinghelli-7cutft?file=/src/App.js
code
import * as React from "react";
import { styled } from "#mui/material/styles";
import Grid from "#mui/material/Grid";
import Paper from "#mui/material/Paper";
import { TextField } from "#mui/material";
export default function ComplexGrid() {
return (
<Paper
sx={{
p: 2,
margin: "auto",
maxWidth: 500,
flexGrow: 1,
backgroundColor: "#1A2027"
}}
>
<Grid container spacing={2}>
<Grid item xs={4} sx={{ alignSelf: "flex-start" }}>
<TextField
id="outlined-basic"
label=""
variant="outlined"
sx={{
backgroundColor: "white",
padding: "0",
flex: 0
}}
/>
</Grid>
<Grid sx={{ alignSelf: "flex-end", color: "white" }} item xs={6}>
<span>test v. test</span>
</Grid>
</Grid>
</Paper>
);
}
edit: I found that if I disable padding-left for all the classes MuiGrid-root.Muigrid-item in inspect element it will push it to the left, but I only want to disable the padding for this first grid item. Overriding it with sx={{paddingLeft: 0}} doesn't seem to do anything
edit2: setting sx={{paddingLeft: "0 !important", paddingTop: "0 !important"}} has gotten the position I wanted, now I just want it to stretch to the size of the paper
The padding: 2 on my paper was the issue, removing this gave me a text input field the same size as my paper
I've been stuck on this part, and I've been struggling how can I manage to make it row, I tried to make it flexWrap, but it's going down instead of going its side.
<Box sx={{display: {xs: 'flex'},
gap: {xs: '0px', md:'20px',
flexWrap: 'wrap',
alignItems: 'center' }}}
>
{products.map((product) => (
<CardProduct key={product._id} product={product}/>
))}
</Box>
outcome
this is I want to achieve, the first and second product must be align, and then have a gap between or spacing, then the 3rd product will automatically wrap... I tried to call the
flexWrap:'wrap'
but it failed. should I just the height ? or is it because the button is too big?
want to achieve
This is what it looks like when it only have two products
two images
Try using a Grid:
<Grid container spacing={2}>
{products.map((product) => (
<Grid item xs={6} key={product._id}>
<CardProduct product={product} />
</Grid>
))}
</Grid>;
To make 2 columns you can use flex-basis property, flex-basis: 50%; , do remove any padding or margin before.
with flex-basis property you can set any width or get number of columns.
<Box sx={{display: {xs: 'flex'},
gap: {xs: '0px', md:'20px',
flex-basis: '50%',
alignItems: 'center' }}}
>
{products.map((product) => (
<CardProduct key={product._id} product={product}/>
))}
There is on more property in css that helps us to achieve any number of coumns without using flexbox.
.div {
column-count: 2;
}
you can try Grid. Material-UI has a very good and clear example exactly as you want.
link
<Grid container spacing={2}>
<Grid item xs={12}>
<Grid container justifyContent="center" spacing={spacing}>
{[0, 1, 2].map((value) => (
<Grid key={value} item>
<Paper className={classes.paper} />
</Grid>
))}
</Grid>
</Grid>
I've been trying to horizontally center a div on the screen of an Iphone. The div is a bit narrower than the phone screen. I have been googling and searching this site and trying every combination of display, flex, margin, width, justify*, align*, placeself, etc. etc. in the container as well as item style and nothing has worked. Here is the code, with all my attempts removed from the style since none of it worked and I assume may interfere with correct solution. No matter what I try, the div just stays on the left side of the screen.
{left} and {right} are divs, with width: 400px
<Mobile>
<Grid container style={{ }} >
<Grid item xs={12} style={{ }}>{left}{right}</Grid>
</Grid>
</Mobile>
const Mobile = ({ children }) => useMediaQuery({ maxWidth: 799 }) && children
Here is what finally worked for me after lots of trial and error.
<Mobile>
<Grid container style={{ justifyItems: 'center', alignItems: 'center', display: 'inline-grid', width: '100%' }} >
<Grid item xs={12} style={{ width: '400px' }}>{left}{right}</Grid>
</Grid>
</Mobile>
To clarify, my question was probably inaccurate. What I needed to do was center the grid item in the grid container.
So I have the following situation:
From a certain point on the darkblue color of the boxes just doesn't align anymore. These two boxes are currently being rendered in a flex container. What would be a solution for this problem? I want the upper container to always be aligned with the one next to it. It is also possible that it will be more than 2 components next to each other.
Flex container (material ui Grid component uses Flex)
<Box>
<Grid container>
{resultField.fields?.map((blockField, index) => {
return (
<Grid item xs={12} md={6}>
<DarkValueBox label={blockField.label} value={blockField.value} />
</Grid>
);
})}
</Grid>
DarkValueBox
export const DarkValueBox = ({ label, value, index }) => {
const classes = useStyles();
return (
<Box sx={{ borderRadius: 5 }}>
<Box
sx={{
backgroundColor: "#0A7BB1",
color: "#fff",
px: 2,
py: 3,
borderRight: "1px solid #fff",
}}
>
<Typography fontWeight={600} variant="subtitle1">
{label}
</Typography>
</Box>
<Box sx={{ px: 2, py: 2, border: "1px solid lightgrey" }}>
<Typography variant="subtitle1">
{value}
</Typography>
</Box>
</Box>
);
};
Here's a codesandbox where I recreated the problem:
https://codesandbox.io/s/add-material-ui-forked-ge42z?file=/src/index.js
An approach would be - if you do not want to cut the labels for showing the user as much information as possible - to ensure the blue box is always taking the height of the highest container in the row.
You can do this with adding a wrapper class to the container DarkValueBox with following specification:
wrapper: {
height: "100%",
display: "flex",
flexDirection: "column"
}
Then, tell your box class to take 100%:
box: {
backgroundColor: "darkblue",
border: "1px solid grey",
color: "white",
wordBreak: "break-word", // btw: its `break-word`, not `word-break`
height: "100%"
},
That is it, find it working in a forked sandbox:
https://codesandbox.io/s/add-material-ui-forked-24zg7?file=/src/index.js
Ok, so I was going through your Sandbox and instead of writing the code I decided to point you in the right direction.
You have declared a Grid with material UI which is a type of container similar to FlexBox.
You have not declared a size or width for the box or the containers inside.
Once you set the grid size and wrap direction for the outer 'main' container you will be able to set the sizes for the containers inside, your label boxes.
This will align them.
For the text, there is a 'textOverflow' property which will stop any additional text wrapping over the component and instead replace it with '...'
Material UI Grid - https://mui.com/components/grid/
Textoverflow - CSS: text-overflow: ellipsis with reactJS and IE