How to center vertically and horizontally in React with Material-UI? - reactjs

I want to center a Button inside of a Card that is in the center of the screen. So far I haven't been able to.
This is wha I have so far:
import React from 'react'
import Button from '#material-ui/core/Button'
import { makeStyles } from '#material-ui/core/styles'
import { Card } from '#material-ui/core'
import Grid from '#material-ui/core/Grid'
const useStyles = makeStyles({
root: {
background: 'linear-gradient(45deg, #9013FE 15%, #50E3C2 90%)',
minWidth: '100%',
minHeight: '100vh',
display: "flex",
flexDirection: "column",
justifyContent: "center"
},
card: {
maxWidth: '40%',
minHeight: '20vh',
},
})
export default function LoginPage () {
const classes = useStyles()
return (
<Grid className={classes.root} spacing={0} align="center" justify="center">
<Card className={classes.card} align="center" justify="center">
<Button variant="contained" color="primary">
Hello World
</Button>
</Card>
</Grid>
)
}
It's centered vertically but not horizontally, when I change other parameter I get it centered horizontally but not vertically.
Screenshot of the result
Any Ideas?
Best regards.

You can use alignItems.
Code Sandbox demo: https://codesandbox.io/s/stack-overflow-material-ui-centering-0rgqx
const useStyles = makeStyles({
root: {
background: "linear-gradient(45deg, #9013FE 15%, #50E3C2 90%)",
minWidth: "100%",
minHeight: "100vh",
display: "flex",
flexDirection: "column",
justifyContent: "center"
},
card: {
maxWidth: "40%",
minHeight: "20vh",
display: "flex",
alignItems: "center"
}
});
export default function LoginPage() {
const classes = useStyles();
return (
<Grid
className={classes.root}
spacing={0}
alignItems="center"
justify="center"
>
<Card className={classes.card}>
<Button variant="contained" color="primary">
Hello World
</Button>
</Card>
</Grid>
);
}

Related

MUI React menu never get closed

On this MUI AppBar/Drawer sample, I have added a MUI Menu to edit profile, with an anchor on a div. It's located on the top right corner. I like to be able to click on the username or the profile icon to pop the menu out. For some reason the menu never disappear. I have try to add console.log in the callbacks. It shows the open callback is called right after the close one. Can someone explain why and how to close the menu ?
Here is my code, and the full project on Codesandbox :
import React from "react";
import Box from "#mui/material/Box";
import Grid from "#mui/material/Grid";
import IconButton from "#mui/material/IconButton";
import Menu from "#mui/material/Menu";
import MenuIcon from "#mui/icons-material/Menu";
import MenuItem from "#mui/material/MenuItem";
import Toolbar from "#mui/material/Toolbar";
import AccountCircle from "#mui/icons-material/AccountCircle";
import { styled } from "#mui/material/styles";
import { useNavigate } from "react-router-dom";
export default function TopBar(props) {
const navigate = useNavigate();
const [anchorEl, setAnchorEl] = React.useState(null);
const handleMenuOpen = (event) => {
console.log("set menu open");
setAnchorEl(event.currentTarget);
};
const handleClose = () => {
console.log("set menu close");
setAnchorEl(null);
};
const UserName = styled("div")(({ theme }) => ({
fontSize: "1em",
marginRight: "0.7em",
display: "inline",
height: "100%",
textAlign: "center",
cursor: "pointer"
}));
const Logo = styled("img")(({ theme }) => ({
height: "42px",
width: "42px",
backgroundColor: "#FFF",
marginRight: "0.7em"
}));
return (
<Toolbar>
<Grid
style={{ justifyContent: "space-between", alignItems: "center" }}
container
>
<Grid item style={{ display: "inline-flex", alignItems: "center" }}>
<IconButton
color="inherit"
aria-label="open drawer"
onClick={props.handleDrawerOpen}
edge="start"
sx={{
...(props.drawerOpen && {
display: {
xs: "block",
sm: "none"
}
})
}}
>
<MenuIcon />
</IconButton>
</Grid>
<Grid item style={{ display: "inline-flex", alignItems: "center" }}>
<Logo
src=""
alt="logo"
onClick={() => {
props.handleDrawerClose();
navigate("/");
}}
/>
<Box
sx={{
whiteSpace: "nowrap",
fontSize: { xs: "1em", sm: "1.25em" },
fontWeight: { xs: 400, sm: 500 }
}}
>
Toolbar test
</Box>
</Grid>
<Grid item style={{ display: "flex", alignItems: "center" }}>
<div
style={{ display: "inline-flex", alignItems: "center" }}
onClick={handleMenuOpen}
>
<UserName sx={{ display: { xs: "none", sm: "block" } }}>
{props.userName}
</UserName>
<IconButton
color="inherit"
aria-label="user"
edge="start"
size="large"
>
<AccountCircle />
</IconButton>
<Menu
anchorEl={anchorEl}
open={Boolean(anchorEl)}
onClose={handleClose}
>
<MenuItem
onClick={() => {
props.handleDrawerClose();
navigate("/test");
}}
>
My Profile
</MenuItem>
<MenuItem
onClick={() => {
props.handleDrawerClose();
navigate("/logout");
}}
>
Logout
</MenuItem>
</Menu>
</div>
</Grid>
</Grid>
</Toolbar>
);
}
You somehow managed that when you trigger the onClose event, you are simultaneously triggering handleMenuOpen function. I would suggest you use a button base to handle opening the menu.
Something like this:
<ButtonBase onClick={handleMenuOpen}>
<UserName sx={{ display: { xs: "none", sm: "block" } }}>
{props.userName}
</UserName>
<AccountCircle />
</ButtonBase>
And dont forget to remove the onClick event from your div.
You can also take a look of the fork that i made.

Centre the Typography

I tried to centre the typography using both textAlign and align but that did not work. Can someone help me with this ? The resulting page is below the code
import React, {useState} from 'react'
import logo from '../../images/logo.svg'
import { Typography } from '#mui/material'
import AccountCircleIcon from "#mui/icons-material/AccountCircle"
const NavBar = () => {
const StyledToolbar = styled(Toolbar)({
display: "flex",
alignItems: "center",
justifyContent: "space-between"
});
const Logo = styled("img")({
width: "12rem",
height: "auto",
});
const StyledAppBar = styled(AppBar)({
position: "sticky",
backgroundColor: "#EDEDED",
});
return (
<StyledAppBar>
<StyledToolbar>
<Logo src={logo} alt="quizy" />
<Typography variant="h5" color="black" align='center'>
Question
</Typography>
<AccountCircleIcon
style={{ color: "black" }}
/>
</StyledToolbar>
</StyledAppBar>
);
}
Page Result
It actually is centered according to its width. To center with 3 children elements you could assign Logo, Typography and Icon following CSS properties:
flex-grow: 1
flex-basis: 0
This will probably move the AccountCircleIcon a bit to the left but you can assign it margin-left: auto. You will also have to remove your assigned width of Logo. For example:
import React, {useState} from 'react'
import logo from '../../images/logo.svg'
import { Typography } from '#mui/material'
import AccountCircleIcon from "#mui/icons-material/AccountCircle"
const NavBar = () => {
const StyledToolbar = styled(Toolbar)({
display: "flex",
alignItems: "center",
justifyContent: "space-between"
});
const Logo = styled("img")({
width: "12rem",
height: "auto"
});
const StyledAppBar = styled(AppBar)({
position: "sticky",
backgroundColor: "#EDEDED",
});
return (
<StyledAppBar>
<StyledToolbar>
<div style={{ flexGrow: 1, flexBasis: 0 }}>
<Logo src={logo} alt="quizy" />
</div>
<Typography style={{ flexGrow: 1, flexBasis: 0 }} variant="h5" color="black" align='center'>
Question
</Typography>
<div style={{ flexGrow: 1, flexBasis: 0, textAlign: "right" }}>
<AccountCircleIcon
style={{ marginLeft: 'auto', color: "black" }}
/>
</div>
</StyledToolbar>
</StyledAppBar>
);
}

split material ui style to other file

I wish to remove all the styles from my main component.
All the JS style of the material UI is on the same file and it is starting to get long code.
I wish to create a new file that contains all the styles on other file and on Navbar.js I will just call the components, just same as CSS file that I call to class
import styled from "#emotion/styled";
import { Notifications, Pets } from "#mui/icons-material";
import {
AppBar,
Avatar,
Badge,
Box,
InputBase,
Menu,
MenuItem,
Toolbar,
Typography,
} from "#mui/material";
import MailIcon from "#mui/icons-material/Mail";
import React, { useState } from "react";
const StyledToolbar = styled(Toolbar)({
display: "flex",
justifyContent: "space-between",
});
const Search = styled("div")(({ theme }) => ({
backgroundColor: "white",
padding: "0 10px",
borderRadius: theme.shape.borderRadius,
width: "40%",
}));
const Icons = styled(Box)(({ theme }) => ({
display: "none",
gap: "20px",
alignItems: "center",
[theme.breakpoints.up("sm")]: {
display: "flex",
},
}));
const UserBox = styled(Box)(({ theme }) => ({
display: "flex",
gap: "10px",
alignItems: "center",
[theme.breakpoints.up("sm")]: {
display: "none",
},
}));
const Navbar = () => {
const [open, setOpen] = useState(false);
return (
<AppBar position="sticky">
<StyledToolbar>
<Typography variant="h6" sx={{ display: { xs: "none", sm: "block" } }}>
PALSAM
</Typography>
<Pets sx={{ display: { xs: "block", sm: "none" } }} />
<Search>
<InputBase placeholder="search..." />
</Search>
<Icons>
<Badge badgeContent={4} color="error">
<MailIcon />
</Badge>
<Badge badgeContent={4} color="error">
<Notifications />
</Badge>
<Avatar
sx={{ width: 30, height: 30 }}
src="https://images.pexels.com/photos/846741/pexels-photo-846741.jpeg?auto=compress&cs=tinysrgb&w=1260&h=750&dpr=2"
onClick={(e) => setOpen(true)}
/>
</Icons>
<UserBox onClick={(e) => setOpen(true)}>
<Avatar
sx={{ width: 30, height: 30 }}
src="https://images.pexels.com/photos/846741/pexels-photo-846741.jpeg?auto=compress&cs=tinysrgb&w=1260&h=750&dpr=2"
/>
<Typography variant="span">Jhon</Typography>
</UserBox>
</StyledToolbar>
<Menu
id="demo-positioned-menu"
aria-labelledby="demo-positioned-button"
open={open}
onClose={(e) => setOpen(false)}
anchorOrigin={{
vertical: "top",
horizontal: "right",
}}
transformOrigin={{
vertical: "top",
horizontal: "right",
}}
>
<MenuItem>Profile</MenuItem>
<MenuItem>My account</MenuItem>
<MenuItem>Logout</MenuItem>
</Menu>
</AppBar>
);
};
export default Navbar;
You can create a new js file and add export before each const then you can import them from that file
export const StyledToolbar = styled(Toolbar)({
display: "flex",
justifyContent: "space-between",
});

How to reduce Material Toolbar height Material-UI?

I want to change(reduce) the default height of the toolbar from Material-UI
I already referred How do I change the Material UI Toolbar height? still I'm facing the problem
The thing is when I am increasing beyond like 50 , I can see changes. But when I want to decrease the height I am unable to.
How can I achieve this?
My Code :
const useStyles = makeStyles((theme) => ({
root: {
position: "relative",
display: "flex",
alignItems: "center",
justifyContent: "flex-end",
},
minHeight: {
minHeight: "20px !important",
},
}));
const AppHeader = () => {
const toolbarSt = useStyles();
return (
<>
<AppBar position="static">
<Toolbar
className={toolbarSt.minHeight}
classes={{ regular: toolbarSt.regular, root: toolbarSt.root }}
>
<Typography> Home </Typography>
<Typography> About </Typography>
</Toolbar>
</AppBar>
</>
);
};
This is due to the font size of <Typography> Home </Typography> and
<Typography> About </Typography> for exemple if you add style class to both Typography like this:
const useStyles = makeStyles((theme) => ({
root: {
position: "relative",
display: "flex",
alignItems: "center",
justifyContent: "flex-end",
},
minHeight: {
minHeight: "5px !important",
},
smallTypo:{
fontSize:"5px"
}
}));
const AppHeader = () => {
const toolbarSt = useStyles();
return (
<>
<AppBar position="static">
<Toolbar
className={toolbarSt.minHeight}
classes={{ regular: toolbarSt.regular, root: toolbarSt.root }}
>
<Typography className={toolbarSt.smallTypo}> Home </Typography>
<Typography className={toolbarSt.smallTypo}> About </Typography>
</Toolbar>
</AppBar>
</>
);
};
you can make a really small AppBar.
here a codeSandeBox
You should set the minHeight property to the root element
const useStyles = makeStyles((theme) => ({
root: {
position: "relative",
display: "flex",
alignItems: "center",
justifyContent: "flex-end",
minHeight: "20px"
}
}));
const AppHeader = () => {
const toolbarSt = useStyles();
return (
<>
<AppBar position="static">
<Toolbar classes={{ root: toolbarSt.root }}>
<Typography> Home </Typography>
<Typography> About </Typography>
</Toolbar>
</AppBar>
</>
);
};
Please refer to the docs for more information https://material-ui.com/api/toolbar/#toolbar-api
just put sx={{ height : '70px }} in appbar for some reason it is not working in toolbar but works on appbar
return (
<AppBar position="static" sx={{ height: '70px' }} >
<Container >
<Toolbar disableGutters >
</Toolbar>
</Container>
</AppBar>
);
};

Material UI card will not center. React JS

Trying to use a card for the main part of my home page. However, nothing I will do will center the card, and I have tried putting justify, alignItems, alignContent, however, none of them seem to resolve the issue. I honestly have no idea what else to do to align this to the center. I don't see how it's even possible. Here is the code:
import React from 'react';
import PropTypes from 'prop-types';
import { withStyles } from '#material-ui/core/styles';
import Card from '#material-ui/core/Card';
import CardActionArea from '#material-ui/core/CardActionArea';
import CardActions from '#material-ui/core/CardActions';
import CardContent from '#material-ui/core/CardContent';
import CardMedia from '#material-ui/core/CardMedia';
import Button from '#material-ui/core/Button';
import Typography from '#material-ui/core/Typography';
import reactImage from '../images/djangoreact.png'
const styles = {
card: {
width: "100%",
backgroundColor: 'black',
textAlign: 'center',
justifyContent: 'center',
alignContent: 'center',
padding: '30px'
},
media: {
height: 325,
// textAlign: 'center',
// justifyContent: 'center',
// alignContent: 'center',
},
font: {
color: 'white',
// textAlign: 'center',
// justifyContent: 'center',
// alignContent: 'center',
},
header:{
textAlign: 'center',
justify: 'center',
alignContent: 'center',
width: '100%'
}
};
function MediaCard(props) {
const { classes } = props;
return (
<div className={classes.header} style={{
justify: 'center',
alignContent: 'center',
alignItems: 'center'
}}>
<Card className={classes.card} style={{
justify: 'center',
alignContent: 'center',
alignItems: 'center'
}}>
<CardActionArea>
<CardMedia
className={classes.media}
image={reactImage}
title="Contemplative Reptile"
/>
<CardContent>
<Typography gutterBottom variant="h5" component="h2" className={classes.font}>
Welcome to the KB
</Typography>
<Typography component="p" className={classes.font}>
Check out the tutorial for the Djanog/React boilerplate used to make this site!
</Typography>
</CardContent>
</CardActionArea>
<CardActions>
<Button size="small" color="primary">
Learn More
</Button>
</CardActions>
</Card>
</div>
);
}
MediaCard.propTypes = {
classes: PropTypes.object.isRequired,
};
export default withStyles(styles)(MediaCard);
Use the Grid provided by material-UI
import Grid from '#material-ui/core/Grid';
// import like this
function MediaCard(props) {
const { classes } = props;
<Grid
container
spacing={0}
direction="column"
alignItems="center"
justify="center"
style={{ minHeight: '100vh' }}
>
<Grid item xs={3}>
<Card>
// card content
</Card>
</Grid>
</Grid>
}
hope this will help you.
Use this: https://material-ui.com/layout/grid/ for more info
Alternatively to switching to <Grid>, I put a <div> wrapper around the <CardMedia> element and used
style={{ display:'flex', justifyContent:'center' }}
on the outer <div> tag to achieve the same result.
I do not know what is your problem while you are setting the width of cards 100%.
I cannot see the rendered view, however, I want to recommend one of minimal solution without <Grid>.
If I were you, I would simply try:
card: {
'margin-left': '5%',
width: "90%",
...
use this style
const useStyles = makeStyles((theme) => ({
cardstyle:{
marginTop: theme.spacing(20),
margin:'auto',
flexDirection: 'column',
},
}));
<Card className={clasess.cardstyle}>
// card content
</Card>

Resources