Problem with using Material UI <Grid> for two column layout - javascript

I'm trying to achieve a two column layout, both of them equal height and each taking half of the screen. Picture explains it better, here is one.
The not working code is as follows:
import React from "react";
import { makeStyles } from "#material-ui/core/styles";
import CssBaseline from "#material-ui/core/CssBaseline";
import Grid from "#material-ui/core/Grid";
import Paper from "#material-ui/core/Paper";
const useStyles = makeStyles(theme => ({
root: {
flexGrow: 1,
alignItems: "stretch"
},
column: {
flexDirection: "column"
},
paper: {
padding: theme.spacing(2),
textAlign: "center",
color: theme.palette.text.secondary
}
}));
export default props => {
const classes = useStyles();
return (
<>
<CssBaseline />
<Grid container className={classes.root}>
{/* COLUMN ONE */}
<Grid container item className={classes.column}>
<Grid item xs={6}>
<Paper className={classes.paper}>1: xs=6</Paper>
</Grid>
<Grid item xs={6}>
<Paper className={classes.paper}>1: xs=6</Paper>
</Grid>
<Grid container item>
<Grid item xs={3}>
<Paper className={classes.paper}>1: xs=3 left</Paper>
</Grid>
<Grid item xs={3}>
<Paper className={classes.paper}>1: xs=3 right</Paper>
</Grid>
</Grid>
</Grid>
{/* COLUMN TWO */}
<Grid container item className={classes.column}>
<Grid item xs={6}>
<Paper className={classes.paper}>2: xs=6</Paper>
</Grid>
<Grid item xs={6}>
<Paper className={classes.paper}>2: xs=6</Paper>
</Grid>
</Grid>
</Grid>
</>
);
};
Obligatory codesandbox is here.
Could someone explain me what am I doing wrong here?

There's a bug with Material UI way of laying out nested grid containers, here. The workaround - found by #londonoliver - is to nest containers inside the grid items:
<Grid container direction="row">
<Grid item>
<Grid container direction="column">
<Grid item>1</Grid>
<Grid item>2</Grid>
</Grid>
</Grid>
<Grid item>
<Grid container direction="column">
<Grid item>3</Grid>
<Grid item>4</Grid>
</Grid>
</Grid>
</Grid>

Related

How to use reactjs material ui GRID layout

I'm trying to use #mui/material/Grid layout for a use case,
In my Report component, I want to have the Bar and Line charts in one block
and the Doughnut and PolarArea charts in another,
I tried applying CSS by adding, style = {{display: "inline-block"}},
But the UX looks like this -
By code is like this on a high level -
App.js -
function App() {
return (
<Router>
<Container style={{backgroundColor: '#F3F4F6'}}>
<Grid container spacing={0.5} >
<Grid item xs={12}>
<Routes>
<Route path='/' element={<SignIn />}/>
<Route path='/dashboard' element={<Dashboard/>}/>
</Routes>
</Grid>
</Grid>
</Container>
</Router>
);
}
Dashboard.js component -
const Dashboard = () => {
return (<>
<Grid item xs={12}>
<Table/>
</Grid>
<Grid item xs={12}>
<Report/>
</Grid>
</>
)}
Report.js component -
export function Report() {
return <>
<Grid item xs={6}>
<Bar options={barChartOptions} data={barChartData} style={{backgroundColor: 'white'}}/>
</Grid>
<Grid item xs={6}>
<Line options={areaChartOptions} data={areaChartData} style={{backgroundColor: 'white'}}/>
</Grid>
<Grid item xs={6}>
<Doughnut options={doughnutOptions} data={doughnutChatData} style={{backgroundColor: 'white'}}/>
</Grid>
<Grid item xs={6}>
<PolarArea options={polarAreaOptions} data={polarAreaData} style={{backgroundColor: 'white'}}/>
</Grid>
<Grid item xs={12}>
<Bar options={groupedBarOptions} data={groupedBarData} style={{backgroundColor: 'white'}}/>
</Grid>
</>
}
You should wrap up the Grid items with a Grid container.
export function Report() {
return <>
<Grid container>
<Grid item xs={6}>
<Bar options={barChartOptions} data={barChartData} style={{backgroundColor: 'white'}}/>
</Grid>
<Grid item xs={6}>
<Line options={areaChartOptions} data={areaChartData} style={{backgroundColor: 'white'}}/>
</Grid>
</Grid>
<Grid container>
<Grid item xs={6}>
<Doughnut options={doughnutOptions} data={doughnutChatData} style={{backgroundColor: 'white'}}/>
</Grid>
<Grid item xs={6}>
<PolarArea options={polarAreaOptions} data={polarAreaData} style={{backgroundColor: 'white'}}/>
</Grid>
</Grid>
<Grid item xs={12}>
<Bar options={groupedBarOptions} data={groupedBarData} style={{backgroundColor: 'white'}}/>
</Grid>
</>
}

Getting class as undefined for img tag in react.js

Getting class as undefined for img tag in react.js
This is the component Header.jsx,
Here is the Header.jsx I'm using <img>, but the CSS properties are not not being implemented in the image, and I'm getting error as class=undefined
import React from 'react';
import classes from './header.css';
import { Box,Grid, Typography} from '#mui/material';
const Header = () => {
return (
<>
<Box sx={{ flexGrow: 1 }}>
<Grid container spacing={3}>
<Grid item xs>
<img src='./images/logo.svg' className={`${classes.header__logo}`} alt='Logo'/>
</Grid>
<Grid item xs={6}>
<Typography>gbr</Typography>
</Grid>
<Grid item xs>
<Typography>gbr</Typography>
</Grid>
</Grid>
</Box>
</>
)
}
export default Header
This is the css file for the header
/* header.css */
.header__logo{
height: 20px;
width: 50px;
}
In the console I'm getting this error, class="undefined"
<img src="./images/logo.svg" class="undefined" alt="Logo">
Just do like that:Basic Concept
import React from 'react';
import './header.css';
import { Box,Grid, Typography} from '#mui/material';
const Header = () => {
return (
<>
<Box sx={{ flexGrow: 1 }}>
<Grid container spacing={3}>
<Grid item xs>
<img src='./images/logo.svg' className="header__logo" alt='Logo'/>
</Grid>
<Grid item xs={6}>
<Typography>gbr</Typography>
</Grid>
<Grid item xs>
<Typography>gbr</Typography>
</Grid>
</Grid>
</Box>
</>
)
}
export default Header
When im doing this naming convention I make sure there's a parent tag with the classname you're trying to extend, in this case "header", also helps if your using SCSS with this, try something like this:
import React from 'react';
import classes from './header.scss';
import { Box,Grid, Typography} from '#mui/material';
const Header = () => {
return (
<div className={`${classes.header}`>
<Box sx={{ flexGrow: 1 }}>
<Grid container spacing={3}>
<Grid item xs>
<img src='./images/logo.svg' className={`${classes.header__logo}`} alt='Logo'/>
</Grid>
<Grid item xs={6}>
<Typography>gbr</Typography>
</Grid>
<Grid item xs>
<Typography>gbr</Typography>
</Grid>
</Grid>
</Box>
</>
)
}
export default Header
Inside your './header.scss'
.header {
// css style for header class
&__logo {
// css style code for logo class
}
}
I find, it returns undefined because it wasn't properly placed in the correct spot within your style sheet. Your react code looks good just missing a few things.

How do I make a one of my elements in react position without overlapping using Grid Component?

I have 3 components on my react page
PageHeader,SideMenu & FeatureList (which is made up of Display Cards) here are the components below:-
App.js
import './App.css';
import { Grid } from '#mui/material';
import SideMenu from './components/home/SideMenu';
import Features from './components/home/Features';
import PageHeader from './components/home/PageHeader';
function App() {
return (
<Grid container spacing={10}>
<Grid item xs={3}>
<PageHeader></PageHeader>
<SideMenu></SideMenu>
</Grid>
<Grid item xs={8}>
<Features></Features>
</Grid>
</Grid>
// <div>
// <PageHeader></PageHeader>
// <SideMenu></SideMenu>
// <Features></Features>
// </div>
);
}
export default App;
PageHeader.js
import * as React from 'react';
import AppBar from '#mui/material/AppBar';
import Box from '#mui/material/Box';
import Toolbar from '#mui/material/Toolbar';
import Typography from '#mui/material/Typography';
import Button from '#mui/material/Button';
import IconButton from '#mui/material/IconButton';
import MenuIcon from '#mui/icons-material/Menu';
import { Grid } from '#mui/material';
var LOGGED_IN = false
const getButtons = (LOGGED_IN) => {
if (LOGGED_IN) {
return <Grid container>
<Grid item xs={7}></Grid>
<Grid item xs={2} >
<Button color="inherit">
<Typography variant="h6" component="div">
Profile
</Typography>
</Button>
</Grid>
<Grid item xs={2} >
<Button color="inherit">
<Typography variant="h6" component="div">
Logout
</Typography>
</Button>
</Grid>
</Grid>
}
else
return <Grid container>
<Grid item xs={9}></Grid>
<Grid item xs={2}>
<Button color="inherit">
<Typography variant="h6" component="div">
Login
</Typography>
</Button>
</Grid>
</Grid>
}
const drawerWidth = 240
export default function PageHeader(props) {
return (
<Grid item container>
<Grid container>
<AppBar
sx={{
width: { sm: `calc(100% - ${drawerWidth}px)` },
ml: { sm: `${drawerWidth}px` },
}}
>
<Toolbar>
<Grid item xs={4}>
<Typography variant="h3" component="div">
Stonks!
</Typography>
</Grid>
{getButtons(LOGGED_IN)}
</Toolbar>
</AppBar>
</Grid>
</Grid>
);
}
SideMenu.js
import * as React from 'react';
import { Divider, Drawer, Grid, List, ListItem, ListItemIcon, ListItemText } from '#mui/material';
import { styled, useTheme } from '#mui/material/styles';
import BusinessIcon from '#mui/icons-material/Business';
import ShowChartIcon from '#mui/icons-material/ShowChart';
import AppsIcon from '#mui/icons-material/Apps';
import SupervisedUserCircleIcon from '#mui/icons-material/SupervisedUserCircle';
import InfoIcon from '#mui/icons-material/Info';
import CreateIcon from '#mui/icons-material/Create';
const DrawerHeader = styled('div')(({ theme }) => ({
...theme.mixins.toolbar,
}))
const drawerWidth = 240
export default function SideMenu(props) {
const theme = useTheme();
const [open, setOpen] = React.useState(true)
const handleDrawerOpen = () => {
setOpen(true)
}
const handleDrawerClose = () => {
setOpen(false)
}
return (
<Grid container spacing={2}>
<Grid item xs={12} container direction="column">
<Drawer
sx={{
width: drawerWidth,
flexShrink: 0,
boxSizing: 'border-box',
'& .MuiDrawer-paper': {
width: drawerWidth,
boxSizing: 'border-box',
},
}}
variant="persistent"
anchor="left"
open={true}
>
<Grid item xs={0} container display='flex' alignItems='center' justifyContent='flex-end'>
<DrawerHeader display='flex'>
</DrawerHeader>
</Grid>
<Grid item xs={0}>
<Divider />
</Grid>
<Grid item container direction='column'>
<List>
{
['Companies', 'Exchanges', 'Sectors', 'Users'].map((text) => (
<Grid item xs={12}>
<ListItem button key={text}>
<ListItemIcon>
{(() => {
switch (text) {
case 'Companies':
return <BusinessIcon />
case 'Exchanges':
return <ShowChartIcon />
case 'Sectors':
return <AppsIcon />
case 'Users':
return <SupervisedUserCircleIcon />
}
})()}
{/* <MenuIcon /> */}
</ListItemIcon>
<ListItemText primary={text} />
</ListItem>
</Grid>
))
}
</List>
</Grid>
<Grid item>
<Divider />
</Grid>
<Grid item container direction='column'>
<List>
{
['About', 'Creators'].map((text) => (
<Grid item xs={12}>
<ListItem button key={text}>
<ListItemIcon>
{(() => {
switch (text) {
case 'About':
return <InfoIcon />
case 'Creators':
return <CreateIcon />
}
})()}
{/* <MenuIcon /> */}
</ListItemIcon>
<ListItemText primary={text} />
</ListItem>
</Grid>
))
}
</List>
</Grid>
</Drawer>
</Grid>
</Grid>
);
}
Features.js
import { Grid } from "#mui/material";
import React from "react";
import DisplayCard from "./DisplayCard";
import company from '../../static/company.jpg'
import stock_exchange from '../../static/stock_exchange.jpg'
import sector from '../../static/sector.png'
import user from '../../static/user.png'
export default function Features(props) {
return (
<Grid container spacing={3}>
<Grid item md={3}>
<DisplayCard name="Companies" brief="View All the Registerd Companies and Click on them to explore each of them in
detail" image={company}></DisplayCard>
</Grid>
<Grid item md={3}>
<DisplayCard name="Stock Exchanges" brief="View All the Registerd Stock Exchanges and Click on them to explore each of them in
detail" image={stock_exchange}></DisplayCard>
</Grid>
<Grid item md={3}>
<DisplayCard name="Sectors" brief="View All the Registerd Sectors and Click on them to explore each of them in
detail" image={sector}></DisplayCard>
</Grid>
<Grid item md={3}>
<DisplayCard name="Users" brief="View All the Registerd Users and Click on them to explore each of them in
detail" image={user}></DisplayCard>
</Grid>
</Grid>
)
}
DispalyCard.js
import React from "react";
import Card from '#mui/material/Card';
import CardContent from '#mui/material/CardContent';
import CardMedia from '#mui/material/CardMedia';
import Typography from '#mui/material/Typography';
import { Button, CardActionArea, CardActions, Grid } from '#mui/material';
export default function DisplayCard(props) {
return (
<Grid container spacing={2}>
<Card sx={{ border: "groove", maxWidth: 300, maxHeight: 400 }}>
<CardActionArea >
<Grid item xs={12}>
<CardMedia
component='img'
height='140'
image={props.image}
width='inherit'
/>
</Grid>
<Grid item container>
<CardContent>
<Grid item xs={12}>
<Typography gutterBottom variant='h4' component='div'>
{props.name}
</Typography>
</Grid>
<Grid item xs={12}>
<Typography variant='body2' color='text.secondary'>
{props.brief}
</Typography>
</Grid>
</CardContent>
</Grid>
</CardActionArea>
<Grid>
<CardActions>
<Button size='small' color='primary'>
Click Here
</Button>
</CardActions>
</Grid>
</Card >
</Grid >
);
}
Currently my output is
As u can see the Feature Cards are getting overlapped by the Header
I want to make them not overlap but I have tried a lot of things but as I am a beginner in Grid & Flexbox im not able to make it correct
Any help will be appreciated.
It looks like you have your header set to position: fixed which removes it from the normal flow of the page. There may be a more elegant solution but so far the best solution for me has been adding the following to my CSS:
body {
padding-top: *height of header*;
}

Add a blank column to Material UI Grid without using padding

I'm learning using Material UI Grid and I want to add a blank column (like padding from the right of the first element) on the right side of a column without using padding.
Consider the code :
import React from 'react';
import Grid from "#material-ui/core/Grid";
import Paper from "#material-ui/core/Paper";
import { makeStyles } from '#material-ui/core/styles';
const ExampleGridComponent = () => {
const useStyles = makeStyles(theme => ({
root: {
flexGrow: 1,
},
paper: {
padding: theme.spacing(2),
textAlign: 'center',
color: theme.palette.text.secondary,
},
}));
const classes = useStyles();
return (
<Grid container spacing={3}>
<Grid item xs={12}>
<Paper className={classes.paper}>xs=12</Paper>
</Grid>
<Grid item xs={12} sm={6}>
<Paper className={classes.paper}>xs=12 sm=6</Paper>
</Grid>
<Grid item xs={12} sm={6}>
<Paper className={classes.paper}>xs=12 sm=6</Paper>
</Grid>
<Grid item xs={6} sm={3}>
<Paper className={classes.paper}>xs=6 sm=3</Paper>
</Grid>
<Grid item xs={6} sm={3}>
<Paper className={classes.paper}>xs=6 sm=3</Paper>
</Grid>
<Grid item xs={6} sm={3}>
<Paper className={classes.paper}>xs=6 sm=3</Paper>
</Grid>
<Grid item xs={6} sm={3}>
<Paper className={classes.paper}>xs=6 sm=3</Paper>
</Grid>
</Grid>)
}
export default ExampleGridComponent;
It look like this :
How can we put a blank column on the right of all the elements (brown color in the picture) ?
Wrap your item grids with row and column.
<Grid container spacing={3}>
<Grid item xs={9}>
<Grid container>
<Grid item xs={12}>
<Paper className={classes.paper}>xs=12</Paper>
</Grid>
<Grid item xs={12} sm={6}>
<Paper className={classes.paper}>xs=12 sm=6</Paper>
</Grid>
<Grid item xs={12} sm={6}>
<Paper className={classes.paper}>xs=12 sm=6</Paper>
</Grid>
<Grid item xs={6} sm={3}>
<Paper className={classes.paper}>xs=6 sm=3</Paper>
</Grid>
<Grid item xs={6} sm={3}>
<Paper className={classes.paper}>xs=6 sm=3</Paper>
</Grid>
<Grid item xs={6} sm={3}>
<Paper className={classes.paper}>xs=6 sm=3</Paper>
</Grid>
<Grid item xs={6} sm={3}>
<Paper className={classes.paper}>xs=6 sm=3</Paper>
</Grid>
</Grid>
</Grid>
<Grid item xs={3}>
</Grid>
</Grid>
Refer to:
Document of Material UI Grid
Nested grid items: issue
import React from "react";
import "./styles.css";
import Grid from "#material-ui/core/Grid";
import Paper from "#material-ui/core/Paper";
import { makeStyles } from "#material-ui/core/styles";
const App = () => {
const useStyles = makeStyles(theme => ({
root: {
flexGrow: 1
},
paper: {
padding: theme.spacing(2),
textAlign: "center",
color: theme.palette.text.secondary
}
}));
const classes = useStyles();
return (
<>
<Grid container>
<Grid item xs={8}>
<Grid container spacing={3}>
<Grid item xs={12}>
<Paper className={classes.paper}>xs=12</Paper>
</Grid>
<Grid item xs={12} sm={6}>
<Paper className={classes.paper}>xs=12 sm=6</Paper>
</Grid>
<Grid item xs={12} sm={6}>
<Paper className={classes.paper}>xs=12 sm=6</Paper>
</Grid>
<Grid item xs={6} sm={3}>
<Paper className={classes.paper}>xs=6 sm=3</Paper>
</Grid>
<Grid item xs={6} sm={3}>
<Paper className={classes.paper}>xs=6 sm=3</Paper>
</Grid>
<Grid item xs={6} sm={3}>
<Paper className={classes.paper}>xs=6 sm=3</Paper>
</Grid>
<Grid item xs={6} sm={3}>
<Paper className={classes.paper}>xs=6 sm=3</Paper>
</Grid>
</Grid>
</Grid>
<Grid item xs={4}>
<Grid item xs={12}>
</Grid>
</Grid>
</Grid>
</>
);
};
export default App;

How to Align One Item Left, and Another Right using Material UI Grid Components

I'm having a very difficult time trying to achieve something simple with the Grid Component from MaterialUI. Specifically, I'd like to align one item to the left, and another to the right on one layout row.
I've searched extensively, and have not found any solutions that work. I've tried many suggestions, including the use of justifyContent and alignContent within a Grid component, and within JSS, and the flex: 1 technique of 'pushing' content.
Relevant Code Snippets
Trying to put the <Typography> element on the left, and the <FormGroup> on the right:
<Container>
<Grid container spacing={3}>
<Grid className={classes.rowLayout}>
// Goal is to align this to the LEFT
<Grid item xs={6}>
<Typography variant="h6" gutterBottom>Some Text</Typography>
</Grid>
// Goal is to align this to the RIGHT
<Grid item xs={3}>
<FormGroup>
// Simple `Switch` button goes here
</FormGroup>
</Grid>
</Grid>
</Grid>
</Container>
MaterialUI JSS styling:
const useStyles = makeStyles(theme => ({
root: {
flexGrow: 1,
width: '100%'
},
rowLayout: {
display: 'flex',
alignItems: 'baseline'
},
}));
I'm also finding that, generally speaking, this is requiring the use of many Grid components, and I'd love to write cleaner code if possible.
Do you have any tips or fixes to this problem?
Thanks a million,
Davis
I'm using this at the moment and it works well to align one to the far left, and one to the far right.
Inspired from: How to align flexbox columns left and right?
const useStyles = makeStyles((theme) => ({
right: {
marginLeft: 'auto'
}
}));
<Grid container alignItems="center">
<Grid>
<Typography variant="h4" component="h4">Left</Typography>
</Grid>
<Grid className={classes.right}>
<Button variant="contained" color="primary">Right</Button>
</Grid>
</Grid>
I used a different approach to list one grid item to right. Similar approach can be use to show grid items to right and one at left.
<Grid container>
<Grid item>Left</Grid>
<Grid item xs>
<Grid container direction="row-reverse">
<Grid item>Right</Grid>
</Grid>
</Grid>
</Grid>
I think the best option here is to use flex like this:
const useStyles = makeStyles(theme => ({
root: {
flexGrow: 1,
width: '100%'
},
rowLayout: {
display: 'flex',
justifyContent: 'space-between',
alignItems: 'center' // To be vertically aligned
},
}));
As a second choice (and for me the best since you are using Material UI at its fullest expression which if you are using it, it's the best thing to do. Use the library as much as you can) you could do something like this:
<Container>
<Grid container spacing={3}>
<Grid container direction="row" justify="space-between" alignItems="center">
// Goal is to align this to the LEFT
<Grid item xs={6}>
<Typography variant="h6" gutterBottom>Some Text</Typography>
</Grid>
// Goal is to align this to the RIGHT
<Grid item xs={3}>
<FormGroup>
// Simple `Switch` button goes here
</FormGroup>
</Grid>
</Grid>
</Grid>
</Container>
I have solved a similar issue using justifyContent on each of the Grid items.
<Container>
<Grid container spacing={3} alignItems="baseline">
<Grid item xs={6} sx={{
justifyContent: "flex-start"
}}>
<Typography variant="h6" gutterBottom>Some Text</Typography>
</Grid>
<Grid item xs={3} sx={{
display: "flex",
justifyContent: "flex-end"
}}>
<FormGroup>
<Typography variant="h6" gutterBottom>Some Switch</Typography>
</FormGroup>
</Grid>
</Grid>
</Container>
This page gives you a really good visually interpretation of how flex works: https://css-tricks.com/snippets/css/a-guide-to-flexbox/

Categories