I want to horizontally center Grid items inside a Grid container. Need some spacing between the Grid items as well. Please find the code below:
import React from "react";
import { makeStyles } from "#material-ui/core/styles";
import { Container, Grid } from "#material-ui/core";
import TextField from "#material-ui/core/TextField";
const useStyles = makeStyles((theme) => ({
topContainer: {
marginTop: theme.spacing(5),
},
}));
export const AddContact = () => {
const classes = useStyles();
return (
<Container fixed>
<Grid
container
spacing={3}
alignContent="center"
alignItems="center"
className={classes.topContainer}
>
<Grid item xs={4} style={{ border: "1px solid #ccc" }}>
<TextField id="name" label="Name" style={{ width: "100%" }} />
<TextField
id="userName"
label="User Name"
style={{ width: "100%" }}
/>
</Grid>
<Grid item xs={4} style={{ border: "1px solid #ccc" }}>
STEP 2
</Grid>
</Grid>
</Container>
);
};
The layout looks like below as of now.
The Grid items are not centrally aligned and there is no spacing between them as well. Could anyone please help me resolve.
Thanks
Instead of giving alignContent="center" provide justify="space-around" to the <Grid> container element. It'll align the items evenly and also separate them from each other according to the available space.
import React from "react";
import { makeStyles } from "#material-ui/core/styles";
import { Container, Grid } from "#material-ui/core";
import TextField from "#material-ui/core/TextField";
const useStyles = makeStyles((theme) => ({
topContainer: {
marginTop: theme.spacing(5),
},
}));
const AddContact = () => {
const classes = useStyles();
return (
<Container fixed>
<Grid
container
spacing={3}
// alignContent="center"
justify="space-around"
alignItems="center"
className={classes.topContainer}
>
<Grid item xs={4} style={{ border: "1px solid #ccc" }}>
<TextField id="name" label="Name" style={{ width: "100%" }} />
<TextField
id="userName"
label="User Name"
style={{ width: "100%" }}
/>
</Grid>
<Grid item xs={4} style={{ border: "1px solid #ccc" }}>
STEP 2
</Grid>
</Grid>
</Container>
);
};
export default AddContact
Here is the working sandbox link:- https://codesandbox.io/s/material-demo-forked-0sf86
You can try this also to play with grid alignment in #material-ui:- https://material-ui.com/components/grid/#interactive
Try something like this.
<Grid
container
spacing={2}
>
<Grid item md={4} lg={4}> </Grid>
<Grid item xs={12} sm={12} md={4} lg={4} style={{ border: "1px solid #ccc" }}>
<TextField id="name" label="Name" style={{ width: "100%" }} />
<TextField
id="userName"
label="User Name"
style={{ width: "100%" }}
/>
</Grid>
<Grid item xs={12} sm={12} md={4} lg={4} style={{ border: "1px solid #ccc" }}>
STEP 2
</Grid>
</Grid>
Related
I am building a website for my podcast network and while everything is working as expected in development, when I build the application for production, the build fails when building static pages, seemingly from gathering data from my Strapi backend. The pages are individual [slug].js pages for each cast member and for each show (though it appears to be failing only for the show pages).
Here is the code for the [slug].js:
import React from "react"
import Image from "next/image"
import Grid from "#mui/material/Grid"
import Typography from "#mui/material/Typography"
import Chip from "#mui/material/Chip"
import GMCard from "../../src/components/GMCard"
import PlayerCard from "../../src/components/PlayerCard"
import { fetchAPI } from "../../lib/api"
import { getStrapiMedia } from "../../lib/media"
const Game = ({ game, characters, people }) => {
let players = []
let pcs = []
const gameMaster = people.filter(
(person) => person.id === game.attributes.gameMaster.data.id
)
game.attributes.players.data.forEach((player) => {
const filtered = people.filter((person) => player.id === person.id)
players.push(filtered.pop())
})
game.attributes.characters.data.forEach((pc) => {
const filtered = characters.filter((char) => pc.id === char.id)
pcs.push(filtered.pop())
})
return (
<Grid container direction="column">
<Grid item>
<Grid container direction="column" alignItems="center">
<Grid item sx={{ marginBottom: "3rem" }}>
<Typography variant="h1">Our Games and Shows</Typography>
</Grid>
<Grid item sx={{ marginBottom: "3rem" }}>
<Typography variant="h2">{game.attributes.name}</Typography>
</Grid>
<Grid container justifyContent="center">
<Grid item sx={{ marginBottom: "3rem", marginLeft: "3rem" }}>
<Image
src={getStrapiMedia(game.attributes.image)}
alt={`${game.attributes.name} logo`}
style={{ height: "25rem" }}
></Image>
</Grid>
<Grid item sx={{ marginBottom: "3rem", marginLeft: "3rem" }}>
<Grid container direction="column" sx={{ width: "50rem" }}>
<Grid item>
<Typography variant="h2">{game.attributes.system}</Typography>
</Grid>
<Grid item>
{game.attributes.season1 ? (
<Chip
label={"Season 1"}
sx={{
padding: 0,
marginRight: "0.5rem",
marginBottom: "0.5rem",
color: "#ffffff",
backgroundColor: "green",
}}
/>
) : null}
{game.attributes.season2 ? (
<Chip
label={"Season 2"}
sx={{
padding: 0,
marginRight: "0.5rem",
marginBottom: "0.5rem",
color: "#000000",
backgroundColor: "#ffff00",
}}
/>
) : null}
</Grid>
<Grid item>
<Typography variant="body1">
{game.attributes.description}
</Typography>
</Grid>
</Grid>
</Grid>
</Grid>
<Grid container direction="column" alignItems="center">
<Grid item sx={{ marginBottom: "3rem" }}>
<Typography variant="h2">Game Master</Typography>
</Grid>
<Grid item sx={{ marginBottom: "3rem" }}>
<Grid container direction="column">
<Grid item>
<GMCard person={gameMaster[0]} />
</Grid>
</Grid>
</Grid>
</Grid>
<Grid container direction="column" alignItems="center">
<Grid item sx={{ marginBottom: "3rem" }}>
<Typography variant="h2">Players</Typography>
</Grid>
<Grid container justifyContent="center">
{players.map((player) => {
const pc = pcs.filter(
(char) => char.attributes.player.data.id === player.id
)
return (
<Grid item key={`char_${player.id}`}>
<PlayerCard person={player} character={pc[0]} />
</Grid>
)
})}
</Grid>
</Grid>
</Grid>
</Grid>
</Grid>
)
}
export async function getStaticPaths() {
const gamesres = await fetchAPI("/games", { fields: ["slug"] })
return {
paths: gamesres.data.map((game) => ({
params: {
slug: game.attributes.slug,
},
})),
fallback: false,
}
}
export async function getStaticProps({ params }) {
const [peopleRes] = await Promise.all([
fetchAPI("/people", { populate: "*" }),
])
const [charactersRes] = await Promise.all([
fetchAPI("/characters", { populate: "*" }),
])
const gamesRes = await fetchAPI("/games", {
filters: {
slug: params.slug,
},
populate: "*",
})
return {
props: {
game: gamesRes.data[0],
characters: charactersRes.data,
people: peopleRes.data,
},
revalidate: 1,
}
}
export default Game
GMCard.js:
import React from "react"
import Grid from "#mui/material/Grid"
import Typography from "#mui/material/Typography"
import Card from "#mui/material/Card"
import CardActions from "#mui/material/CardActions"
import CardContent from "#mui/material/CardContent"
import CardMedia from "#mui/material/CardMedia"
import Button from "#mui/material/Button"
import { getStrapiMedia } from "../../lib/media"
import ArrowForwardIcon from "#mui/icons-material/ArrowForward"
const GMCard = ({ person }) => {
return (
<Grid item sx={{ margin: "1rem" }}>
<Card
sx={{
width: 400,
minHeight: 400,
display: "flex",
flexDirection: "column",
}}
>
<CardMedia
sx={{ height: 400 }}
image={getStrapiMedia(person.attributes.headshot)}
title={`${person.attributes.lastName} headshot`}
/>
<CardContent>
<Typography variant="h3" component="div">
{`${person.attributes.firstName} ${person.attributes.lastName}`}
</Typography>
<Grid item>
<Typography variant="h4" component="div">
{`Game Master`}
</Typography>
</Grid>
</CardContent>
<CardActions sx={{ justifyContent: "flex-end", marginTop: "auto" }}>
<Button
href={`/about/${person.attributes.slug}`}
endIcon={<ArrowForwardIcon />}
>
Bio
</Button>
</CardActions>
</Card>
</Grid>
)
}
export default GMCard
PlayerCard.js:
import React, { useState } from "react"
import Image from "next/image"
import Grid from "#mui/material/Grid"
import Typography from "#mui/material/Typography"
import Card from "#mui/material/Card"
import CardActions from "#mui/material/CardActions"
import CardContent from "#mui/material/CardContent"
import CardMedia from "#mui/material/CardMedia"
import Button from "#mui/material/Button"
import Modal from "#mui/material/Modal"
import { getStrapiMedia } from "../../lib/media"
import ArrowForwardIcon from "#mui/icons-material/ArrowForward"
const PlayerCard = ({ person, character }) => {
const [open, setOpen] = useState(false)
const handleOpen = () => setOpen(true)
const handleClose = () => setOpen(false)
return (
<Grid item sx={{ margin: "1rem" }}>
<Card
sx={{
width: 400,
minHeight: 400,
display: "flex",
flexDirection: "column",
}}
>
<CardMedia
sx={{ height: 400 }}
image={getStrapiMedia(person.attributes.headshot)}
title={`${person.attributes.lastName} headshot`}
/>
<CardContent>
<Typography variant="h3" component="div">
{`${person.attributes.firstName} ${person.attributes.lastName} as`}
</Typography>
<Grid item>
<Typography variant="h3" component="div">
{`${character.attributes.name}`}
</Typography>
</Grid>
</CardContent>
<CardActions sx={{ justifyContent: "flex-end", marginTop: "auto" }}>
<Grid container direction="column" alignItems="flex-end">
<Button
href={`/about/${person.attributes.slug}`}
endIcon={<ArrowForwardIcon />}
>
Bio
</Button>
<Button onClick={handleOpen} endIcon={<ArrowForwardIcon />}>
Character Info
</Button>
</Grid>
</CardActions>
</Card>
<Modal open={open} onClose={handleClose}>
<Grid container direction="column">
<Grid
item
sx={{
position: "absolute",
top: "50%",
left: "50%",
transform: "translate(-50%, -50%)",
width: 600,
bgcolor: "background.paper",
border: "2px solid #000",
boxShadow: 24,
p: 4,
}}
>
<Grid container>
<Grid item>
<Image
src={getStrapiMedia(character.attributes.image)}
alt={`${character.attributes.name} art`}
style={{ height: 225, width: 225 }}
/>
</Grid>
<Grid item>
<Grid
container
direction="column"
justifyContent="space-between"
sx={{ height: 225, marginLeft: "0.5rem" }}
>
<Grid item>
<Grid container direction="column">
<Grid item>
<Typography variant="h3" component="div">
{`${character.attributes.name}`}
</Typography>
</Grid>
<Grid item>
<Typography variant="h4" component="div">
{`${character.attributes.role}`}
</Typography>
</Grid>
<Grid item>
<Button
href={`/team/${character.attributes.player.data.attributes.slug}`}
sx={{
textTransform: "none",
padding: 0,
color: "#000",
}}
>
{`Played by ${character.attributes.player.data.attributes.firstName} ${character.attributes.player.data.attributes.lastName}`}
</Button>
</Grid>
</Grid>
</Grid>
<Grid item>
<Grid container direction="column">
<Grid item>
<Typography
variant="h3"
component="div"
sx={{
color: "#000",
}}
>
{`${character.attributes.game.data.attributes.name}`}
</Typography>
</Grid>
<Grid item>
<Button
endIcon={<ArrowForwardIcon />}
sx={{ textTransform: "none", padding: 0 }}
>
{`About ${character.attributes.game.data.attributes.name}`}
</Button>
</Grid>
</Grid>
</Grid>
</Grid>
</Grid>
</Grid>
<Grid item>
<Typography variant="body1">
{character.attributes.bio}
</Typography>
</Grid>
</Grid>
</Grid>
</Modal>
</Grid>
)
}
export default PlayerCard
And here's the errors:
$ npm run build
> frontend#0.1.0 build
> next build
info - Loaded env from C:\Users\gmrpr\Desktop\Code_Projects\VibeTribe\frontend\.env
info - Linting and checking validity of types
info - Creating an optimized production build
info - Compiled successfully
Warning: You have opted-out of Automatic Static Optimization due to `getInitialProps` in `pages/_app`. This does not opt-out pages with `getStaticProps`
Read more: https://nextjs.org/docs/messages/opt-out-auto-static-optimization
info - Collecting page data
[== ] info - Generating static pages (0/45)
Error occurred prerendering page "/games/call-of-the-deep". Read more: https://nextjs.org/docs/messages/prerender-error
TypeError: Cannot read properties of undefined (reading 'id')
at C:\Users\gmrpr\Desktop\Code_Projects\VibeTribe\frontend\.next\server\pages\games\[slug].js:212:109
at Array.filter (<anonymous>)
at C:\Users\gmrpr\Desktop\Code_Projects\VibeTribe\frontend\.next\server\pages\games\[slug].js:212:52
at Array.map (<anonymous>)
at Game (C:\Users\gmrpr\Desktop\Code_Projects\VibeTribe\frontend\.next\server\pages\games\[slug].js:211:51)
at Wc (C:\Users\gmrpr\Desktop\Code_Projects\VibeTribe\frontend\node_modules\react-dom\cjs\react-dom-server.browser.production.min.js:68:44)
at Zc (C:\Users\gmrpr\Desktop\Code_Projects\VibeTribe\frontend\node_modules\react-dom\cjs\react-dom-server.browser.production.min.js:70:253)
at Z (C:\Users\gmrpr\Desktop\Code_Projects\VibeTribe\frontend\node_modules\react-dom\cjs\react-dom-server.browser.production.min.js:76:89)
at $c (C:\Users\gmrpr\Desktop\Code_Projects\VibeTribe\frontend\node_modules\react-dom\cjs\react-dom-server.browser.production.min.js:78:98)
at bd (C:\Users\gmrpr\Desktop\Code_Projects\VibeTribe\frontend\node_modules\react-dom\cjs\react-dom-server.browser.production.min.js:77:404)
Error occurred prerendering page "/games/the-academy". Read more: https://nextjs.org/docs/messages/prerender-error
TypeError: Cannot read properties of undefined (reading 'attributes')
at C:\Users\gmrpr\Desktop\Code_Projects\VibeTribe\frontend\.next\server\pages\games\[slug].js:212:72
at Array.filter (<anonymous>)
at C:\Users\gmrpr\Desktop\Code_Projects\VibeTribe\frontend\.next\server\pages\games\[slug].js:212:52
at Array.map (<anonymous>)
at Game (C:\Users\gmrpr\Desktop\Code_Projects\VibeTribe\frontend\.next\server\pages\games\[slug].js:211:51)
at Wc (C:\Users\gmrpr\Desktop\Code_Projects\VibeTribe\frontend\node_modules\react-dom\cjs\react-dom-server.browser.production.min.js:68:44)
at Zc (C:\Users\gmrpr\Desktop\Code_Projects\VibeTribe\frontend\node_modules\react-dom\cjs\react-dom-server.browser.production.min.js:70:253)
at Z (C:\Users\gmrpr\Desktop\Code_Projects\VibeTribe\frontend\node_modules\react-dom\cjs\react-dom-server.browser.production.min.js:76:89)
at $c (C:\Users\gmrpr\Desktop\Code_Projects\VibeTribe\frontend\node_modules\react-dom\cjs\react-dom-server.browser.production.min.js:78:98)
at bd (C:\Users\gmrpr\Desktop\Code_Projects\VibeTribe\frontend\node_modules\react-dom\cjs\react-dom-server.browser.production.min.js:77:404)
// ...repeating errors for each page
info - Generating static pages (45/45)
> Build error occurred
Error: Export encountered errors on following paths:
/games/[slug]: /games/a-walk-among-gods
/games/[slug]: /games/brave-new-wild
/games/[slug]: /games/call-of-the-deep
/games/[slug]: /games/duskvale
/games/[slug]: /games/friday-night-fights
/games/[slug]: /games/furusato
/games/[slug]: /games/heckna
/games/[slug]: /games/neon-memories
/games/[slug]: /games/nights-of-payne-town
/games/[slug]: /games/red-harvest
/games/[slug]: /games/tavern-tales
/games/[slug]: /games/the-academy
/games/[slug]: /games/the-crystal-city
/games/[slug]: /games/the-hunt-for-glory
at C:\Users\gmrpr\Desktop\Code_Projects\VibeTribe\frontend\node_modules\next\dist\export\index.js:409:19
at processTicksAndRejections (node:internal/process/task_queues:96:5)
at async Span.traceAsyncFn (C:\Users\gmrpr\Desktop\Code_Projects\VibeTribe\frontend\node_modules\next\dist\trace\trace.js:79:20)
at async C:\Users\gmrpr\Desktop\Code_Projects\VibeTribe\frontend\node_modules\next\dist\build\index.js:1345:21
at async Span.traceAsyncFn (C:\Users\gmrpr\Desktop\Code_Projects\VibeTribe\frontend\node_modules\next\dist\trace\trace.js:79:20)
at async C:\Users\gmrpr\Desktop\Code_Projects\VibeTribe\frontend\node_modules\next\dist\build\index.js:1205:17
at async Span.traceAsyncFn (C:\Users\gmrpr\Desktop\Code_Projects\VibeTribe\frontend\node_modules\next\dist\trace\trace.js:79:20)
at async Object.build [as default] (C:\Users\gmrpr\Desktop\Code_Projects\VibeTribe\frontend\node_modules\next\dist\build\index.js:66:29)
Let me know if there is any more info you need, but I could use all the help I can get. I'm out of ideas.
I have a Grid container containing four Grid items. The first Grid item is full width and contains a title. The other three Grid items contain avatars. I want to align the avatars to the right of the page and I would like the title to align with the left-most avatar. However, it is currently further to the left than the avatars. The other issue is that the number of avatars can vary (likely between 1 and 3 but possibly more). How can I ensure the left-most avatar and title align?
Here is the result I am getting:
And here is what I would like to achieve:
Here is my code:
import React from "react";
import { Grid, makeStyles, Typography, Divider, Avatar } from "#material-ui/core";
const useStyles = makeStyles((theme) => ({
header: {
paddingTop: theme.spacing(3),
paddingBottom: theme.spacing(3),
flexGrow: 1,
},
}));
const Header = ({ padding }) => {
const classes = useStyles();
return (
<>
<Grid
container
item
direction="row"
justify="space-between"
align-items="center"
xs={12}
className={`${padding} ${classes.header}`}
>
{/*Page title and description*/}
<Grid item xs>
<Typography variant="h1" component="h1">
Page Title
</Typography>
<Typography variant="body1">
This is a description of what the page is about
</Typography>
</Grid>
{/*People container*/}
<Grid item xs className={classes.smeSection} alignItems="bottom">
{/*People profiles*/}
<Grid container item justify="flex-end" alignItems="bottom">
<Grid item xs={12}>
<Typography variant="h5">People</Typography>
</Grid>
<Grid item>
<Avatar/>
</Grid>
<Grid item>
<Avatar/>
</Grid>
<Grid item>
<Avatar />
</Grid>
</Grid>
</Grid>
</Grid>
<Divider />
</>
);
};
export default Header;
Many thanks!
Katie
By continuously nesting flexbox components it is very easy to make mistakes and get lost in the code.
If it was that I understood your requirement well, here is the code with which I managed to get that layout:
import React from "react";
import { Grid, Typography, Divider, Avatar } from "#material-ui/core";
const Header = () => {
return (
<>
<Grid container direction="row" align-items="center">
{/*Page title and description*/}
<Grid item xs={9}>
<Typography variant="h1" component="h1">
Page Title
</Typography>
<Typography variant="body1">
This is a description of what the page is about
</Typography>
</Grid>
{/*People container*/}
<Grid container item xs={3}>
{/*People profiles*/}
<Grid container item>
<Grid item>
<Typography variant="h5">People</Typography>
</Grid>
<Grid container>
<Grid item>
<Avatar />
</Grid>
<Grid item>
<Avatar />
</Grid>
<Grid item>
<Avatar />
</Grid>
</Grid>
</Grid>
</Grid>
</Grid>
<Divider />
</>
);
};
export default Header;
A grid can be "container", "item" or both. The most important changes I made to your code was to make all grid parents "containers" and add a width size to the first two grid items (xs={9} and xs={3}).
Here's a CodeSandbox with a working example: https://codesandbox.io/s/upbeat-banzai-0gp10?file=/src/Header.js:0-1119
In my opinion, I think a better alternative is to use a combination of Grid (for general layout) and Flexbox to align the nested elements.
UPDATE:
With the new data you added as a reference I made the layout again using flexbox.
import React from "react";
import {
Typography,
makeStyles,
Avatar,
Card,
CardHeader,
Divider
} from "#material-ui/core";
const useStyles = makeStyles((theme) => ({
root: {
display: "flex",
justifyContent: "space-between"
},
usersHeader: {
marginLeft: theme.spacing(2)
},
personCards: {
display: "flex"
}
}));
const Header = () => {
const classes = useStyles();
return (
<>
<div className={classes.root}>
<div>
<Typography variant="h3" component="h1">
Page Title
</Typography>
<Typography variant="body1">
This is a description of what the page is about
</Typography>
</div>
<div>
<Typography className={classes.usersHeader} variant="subtitle">
Users
</Typography>
<div className={classes.personCards}>
<Card elevation={0}>
<CardHeader
avatar={<Avatar />}
title="Person name"
subheader="Person role"
/>
</Card>
<Card elevation={0}>
<CardHeader
avatar={<Avatar />}
title="Person name"
subheader="Person role"
/>
</Card>
<Card elevation={0}>
<CardHeader
avatar={<Avatar />}
title="Person name"
subheader="Person role"
/>
</Card>
</div>
</div>
</div>
<Divider />
</>
);
};
export default Header;
CodeSandbox reproduction: https://codesandbox.io/s/condescending-cartwright-grxhj?file=/src/Header.js
I'm trying to create a grid system with a gradient background color. However, the background color also applies to the empty spaces not taken up by grid cells. I want just the grid cells to share this gradient. Is there any way to do this?
Image: https://imgur.com/a/WHVhFg1
You should set a linear background color for your container and set background: 'inherit' for your grid item. Inside your grid item, you should use an image with a no background color.
Try this:
import React from "react";
import { makeStyles } from "#material-ui/core/styles";
import Paper from "#material-ui/core/Paper";
import Grid from "#material-ui/core/Grid";
const useStyles = makeStyles(theme => ({
root: {
flexGrow: 1,
background:
"linear-gradient(90deg, rgba(34,193,195,1) 0%, rgba(253,187,45,1) 100%)"
},
paper: {
padding: theme.spacing(2),
textAlign: "center",
color: theme.palette.text.secondary,
background: "inherit"
}
}));
export default function AutoGrid() {
const classes = useStyles();
return (
<div className={classes.root}>
<Grid container spacing={3}>
<Grid item xs={3}>
<Paper className={classes.paper}>
<img
height="100px"
alt="cat"
src="http://assets.stickpng.com/thumbs/584c3c8a1fc21103bb375ba7.png"
/>
</Paper>
</Grid>
<Grid item xs={3}>
<Paper className={classes.paper}>
<img
height="100px"
alt="cat"
src="http://assets.stickpng.com/thumbs/584c3c8a1fc21103bb375ba7.png"
/>
</Paper>
</Grid>
<Grid item xs={3}>
<Paper className={classes.paper}>
<img
height="100px"
alt="cat"
src="http://assets.stickpng.com/thumbs/584c3c8a1fc21103bb375ba7.png"
/>
</Paper>
</Grid>
<Grid item xs={3}>
<Paper className={classes.paper}>
<img
height="100px"
alt="cat"
src="http://assets.stickpng.com/thumbs/584c3c8a1fc21103bb375ba7.png"
/>
</Paper>
</Grid>
</Grid>
<Grid container spacing={3}>
<Grid item xs>
<Paper className={classes.paper}>
<img
height="100px"
alt="cat"
src="http://assets.stickpng.com/thumbs/584c3c8a1fc21103bb375ba7.png"
/>
</Paper>
</Grid>
</Grid>
</div>
);
}
I need some help with positioning my Grid Items while using Material UI.
Codesandbox is where I am so far (roughly).
And my question is quite simple - how do I get 2 & 3 to go to the right of 1? I kinda do it but there are all those weird spaces to the left and down that, I cannot figure out how to deal with.
That's the end result I'm after:
Thank you.
import React from "react";
import { makeStyles } from "#material-ui/core/styles";
import Typography from "#material-ui/core/Typography";
import Paper from "#material-ui/core/Paper";
import Divider from "#material-ui/core/Divider";
import Grid from "#material-ui/core/Grid";
const useStyles = makeStyles(theme => ({
container: {
// display: "grid",
gridTemplateColumns: "repeat(12, 1fr)",
gridGap: theme.spacing(3)
},
paper: {
padding: theme.spacing(1),
textAlign: "center",
color: theme.palette.text.secondary,
whiteSpace: "nowrap",
marginBottom: theme.spacing(1)
},
w: {
height: "100px"
},
divider: {
margin: theme.spacing(2, 0)
}
}));
export default function CSSGrid() {
const classes = useStyles();
return (
<div>
<Grid container spacing={3}>
<Grid container direction="column">
<Grid item xs={8}>
<Paper className={classes.paper + " " + classes.w}>xs=8</Paper>
</Grid>
</Grid>
<Grid
container
style={{ display: "table", height: "100%" }}
direction="row"
>
<Grid item xs={4}>
<Paper className={classes.paper}>xs=4</Paper>
</Grid>
<Grid item xs={4}>
<Paper className={classes.paper}>xs=4</Paper>
</Grid>
</Grid>
</Grid>
<Divider className={classes.divider} />
</div>
);
}
Some notice points from your code
use one container for one grid field structure
remove direction setting direction="column"
xs sum needs to lower or equal to 12 if you want to set them in one row.
Kindly check the material-ui grid document for better understanding
<Grid container spacing={3}>
<Grid item xs={8}>
<Paper className={classes.paper + " " + classes.w}>xs=8</Paper>
</Grid>
<Grid item xs={2}>
<Paper className={classes.paper}>xs=2</Paper>
</Grid>
<Grid item xs={2}>
<Paper className={classes.paper}>xs=2</Paper>
</Grid>
</Grid>
<Divider className={classes.divider} />
Update:
<Grid container spacing={3}>
<Grid item xs={8}>
<Paper className={classes.paper + " " + classes.w}>xs=8</Paper>
</Grid>
<Grid item xs={4}>
<Grid container>
<Grid item xs={12}>
<Paper className={classes.paper}>xs=4</Paper>
</Grid>
<Grid item xs={12}>
<Paper className={classes.paper}>xs=4</Paper>
</Grid>
</Grid>
</Grid>
</Grid>
<Divider className={classes.divider} />
Try it online:
I'm working on a map with an image overlay that has adjustable opacity. Here is the component code:
import React from 'react'
import PropTypes from 'prop-types'
import { MapWithGroundOverlay } from './MapWithGroundOverlay'
import { withStyles } from '#material-ui/core/styles'
import Box from '#material-ui/core/Box'
import FormLabel from '#material-ui/core/FormLabel'
import Slider from '#material-ui/lab/Slider'
import Grid from '#material-ui/core/Grid'
import Paper from '#material-ui/core/Paper'
const styles = theme => ({
root: {
flexGrow: 1,
},
paper: {
padding: theme.spacing(2),
textAlign: 'center',
color: theme.palette.text.secondary,
},
label: {
padding: theme.spacing(3),
}
})
class AdjustableGroundoverlay extends React.PureComponent {
constructor(props, context) {
super(props, context)
this.state = {opacity: 0.5}
this.handleChange = this.handleChange.bind(this);
}
handleChange(event, value) {
this.setState(state => ({
opacity: value
}));
}
render() {
return (
<Grid container className={this.props.classes.root} spacing={2}>
<Grid item xs={12}>
<MapWithGroundOverlay
googleMapURL={`https://maps.googleapis.com/maps/api/js?key=${process.env.REACT_APP_GOOGLE_MAPS_API_KEY}&v=3.exp&libraries=geometry,drawing,places`}
loadingElement={<div style={{ height: `100%` }} />}
containerElement={<div style={{ height: `600px` }} />}
mapElement={<div style={{ height: `100%` }} />}
opacity={this.state.opacity}
/>
</Grid>
<Grid item xs={6}>
<Paper className={this.props.classes.paper}>
<Box flexDirection="column">
<FormLabel className={this.props.classes.label}>Overlay opacity</FormLabel>
<Slider
value={this.state.opacity}
min={0}
max={1}
onChange={this.handleChange}
/>
</Box>
</Paper>
</Grid>
</Grid>
);
}
}
AdjustableGroundoverlay.propTypes = {
classes: PropTypes.object.isRequired,
}
export default withStyles(styles)(AdjustableGroundoverlay)
The problem is that the FormLabel and Slider are too close together. If I hover over them, I see that the Slider has a negative margin of -24px:
It seems like the content of the FormLabel therefore sits directly on top of it:
I've tried to change the styling of the Slider by adding these classes to the component in accordance with https://material-ui.com/api/slider/#css:
<Slider
classes={{container: {marginTop: -12}}}
value={this.state.opacity}
min={0}
max={1}
onChange={this.handleChange}
/>
but the spacing between the FormLabel and the Slider remains the same. Any idea what is wrong with this implementation?
Update
I've noticed in the console that there is this error:
I'm not sure why the key 'container' is not valid though since it is mentioned in https://material-ui.com/api/slider/#css.
I resolved this by putting the slider in a Box with mt set to 1:
<Paper className={this.props.classes.paper}>
<Box flexDirection="column">
<FormLabel className={this.props.classes.label}>Overlay opacity</FormLabel>
<Box mt={1}>
<Slider
value={this.state.opacity}
min={0}
max={1}
onChange={this.handleChange}
/>
</Box>
</Box>
</Paper>
Now there is more spacing between the label and the slider: