Text not aligning properly on MUI card component - reactjs

I am new to react, I've been following a course and building a demo project. I've tried but for some reason i can't align the price text on a card that has a single line of description. In fact, I want the price to appear on the bottom left of the cards. This is what my code looks like. Any suggestion would be appreciated.
import Card from '#mui/material/Card';
import CardContent from '#mui/material/CardContent';
import CardMedia from '#mui/material/CardMedia';
import Typography from '#mui/material/Typography';
const ItemCard = (props) => {
// return <div className={classes.card}>{props.children}</div>;
return (
<div>
<Card
sx={{
maxWidth: 345,
maxHeight: '100%',
boxShadow: '0 2px 8px rgba(0, 0, 0, 0.25)',
height: '350px'
}}
>
<CardMedia component='img' height='200' image={props.img} alt='icon' />
<CardContent>
<Typography gutterBottom variant='h5' component='div'>
{props.name}
</Typography>
<Typography variant='body2' color='text.secondary'>
{props.description}
</Typography>
<Typography style={{}}>TK. {props.price}</Typography>
</CardContent>
</Card>
</div>
);
};
export default ItemCard;
Please see this image

You can add a min-height css property in your description Typography component like below (make sure the height is enough for fitting two lines. In case you have longer than two lines of description you can add the ellipsis css properties like in this solution):
<Typography variant='body2' color='text.secondary' sx={{minHeight: "30px"}}>
{props.description}
</Typography>

You can do this!
<CardActions>
<Typography style={{}}>TK. {props.price}</Typography>
</CardActions>

Related

trying to display Cards horizontally 3 items per row materia ui

I am pretty new to Material Ui and ReactJs. i am trying to display cards horizontally and each row has 3 cards. but now its currently displaying only 1 column.
this is a file that calls the cards
import * as React from 'react';
import Jobs from './Jobs'
const jobs1=[{
company:"razer",
jobtitle:"Data engineer",
},{
company:"Huawei",
jobtitle:"Data Engineer"
},{
company:"Huawei",
jobtitle:"Data Engineer"
}]
export default function Header() {
return (
jobs1.map((jobs1)=>(
<Jobs jobs1={jobs1}/>
)))
}
this is the cards file
import React from 'react';
import Card from '#mui/material/Card';
import CardContent from '#mui/material/CardContent';
import CardMedia from '#mui/material/CardMedia';
import img from './image/Razer.png'
import Typography from '#mui/material/Typography';
import {Grid,Box } from '#mui/material'
const Jobs = ({jobs1: {company, jobtitle}})=>{
return (
<Card sx={{ maxWidth: 300 }}>
<CardMedia
component="img"
height="100"
sx={{ width: 100}}
image={img}
alt="razer"
/>
<CardContent>
<Typography style={{color: '#bdbdbd'}}gutterBottom variant="h9" component="div">
{company}
</Typography>
<Typography component="div">
<Box sx={{ fontWeight: 'bold' }}>
{jobtitle}
</Box>
</Typography>
<Grid container direction="row" alignItems="center" gap={14}>
<Typography sx={{fontStyle: 'italic'}} style={{color: '#bdbdbd'}}inline variant="body1" align="left">
1 minute ago
</Typography>
<Typography inline variant="body1" >
<Box sx={{ borderRadius: '12px', p: 1,opacity:"0.5", border: '0.5px solid',color: "#64dd17",bgcolor:"#ccff90" }}>Data</Box>
</Typography>
</Grid>
<Typography style={{color: '#bdbdbd'}}>____________________________</Typography>
</CardContent>
{/* <CardActions>
<Button size="small">Share</Button>
<Button size="small">Learn More</Button>
</CardActions> */}
</Card>
);
}
export default Jobs;
i tried to do use the and flexbox instead of printing out the items everything they delete all the items in the webpage instead.
Try wrapping your parent component in Grid
import * as React from 'react';
import Jobs from './Jobs'
import { Grid } from '#mui/material';
const jobs1=[{
company:"razer",
jobtitle:"Data engineer",
},{
company:"Huawei",
jobtitle:"Data Engineer"
},{
company:"Huawei",
jobtitle:"Data Engineer"
}]
export default function Header() {
return (
<Grid container mt={2} spacing={2}>
jobs1.map((jobs1)=>(
<Jobs jobs1={jobs1}/>
))
</Grid>
)
}
Next: Wrapping you child in Grid
import React from 'react';
import Card from '#mui/material/Card';
import CardContent from '#mui/material/CardContent';
import CardMedia from '#mui/material/CardMedia';
import img from './image/Razer.png'
import Typography from '#mui/material/Typography';
import {Grid,Box } from '#mui/material'
const Jobs = ({jobs1: {company, jobtitle}})=>{
return (
<Grid item xs={4}>
<Card sx={{ maxWidth: 300 }}>
<CardMedia
component="img"
height="100"
sx={{ width: 100}}
image={img}
alt="razer"
/>
<CardContent>
<Typography style={{color: '#bdbdbd'}}gutterBottom variant="h9" component="div">
{company}
</Typography>
<Typography component="div">
<Box sx={{ fontWeight: 'bold' }}>
{jobtitle}
</Box>
</Typography>
<Grid container direction="row" alignItems="center" gap={14}>
<Typography sx={{fontStyle: 'italic'}} style={{color: '#bdbdbd'}}inline variant="body1" align="left">
1 minute ago
</Typography>
<Typography inline variant="body1" >
<Box sx={{ borderRadius: '12px', p: 1,opacity:"0.5", border: '0.5px solid',color: "#64dd17",bgcolor:"#ccff90" }}>Data</Box>
</Typography>
</Grid>
<Typography style={{color: '#bdbdbd'}}>____________________________</Typography>
</CardContent>
{/* <CardActions>
<Button size="small">Share</Button>
<Button size="small">Learn More</Button>
</CardActions> */}
</Card>
</Grid>
);
}
export default Jobs;
For more information you can check the Grid System of MUI

Button on card prevent new tab link from launching

I have a card component that has a green button on the top right, an image and text below it, I want to be able to click on anywhere on the card and for it to redirect to the url in the code; however if the green button is clicked, it should do nothing and not open the url. In the code below it doesn't do that, instead it always opens the url. I used href as it allows the left click on mouse to open in the same page, but the middle click to open a new tab while remaining in the same page which is very important.
Here is a link to a codeSandBox having the code: https://codesandbox.io/s/material-demo-forked-chy0d?file=/demo.js
Code:
export default function MediaCard() {
const classes = useStyles();
return (
<Card className={classes.root}>
<a href="sdfs">
<CardActionArea style={{ paddingTop: 50 }}>
<div
style={{
position: "absolute",
color: "white",
top: 8,
right: 8
}}
>
<Button
style={{ background: "green", color: "white" }}
onMouseDown={(e) => e.stopPropagation()}
size="small"
color="primary"
>
BUTTON
</Button>
</div>
<CardMedia
className={classes.media}
image="https://media.tarkett-image.com/large/TH_25121916_25131916_25126916_25136916_001.jpg"
title="Contemplative Reptile"
/>
<CardContent>
<Typography gutterBottom variant="h5" component="h2">
jnikn
</Typography>
<Typography variant="body2" color="textSecondary" component="p">
ijneodsk ipknv onfp o nf onopndsfc on pnojnc olpnoinoi hbib iubn
iujno nouno oijipj onoin ioio
</Typography>
</CardContent>
</CardActionArea>
</a>
</Card>
);
try this
import React from "react";
import { makeStyles } 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";
const useStyles = makeStyles({
root: {
maxWidth: 345,
position: "relative"
},
media: {
height: 140
// marginTop: 50
}
});
export default function MediaCard() {
const classes = useStyles();
return (
<Card className={classes.root}>
<Button
style={{ zIndex:'1000',
position: "absolute",
top: 8,
right: 8,background: "green", color: "white",width:'70px',height:'30px' }}
onMouseDown={(e) => e.stopPropagation()}
size="small"
color="primary"
>
BUTTON
</Button>
<a href="sdfs">
<CardActionArea style={{ paddingTop: 50 }}>
<CardMedia
className={classes.media}
image="https://media.tarkett-image.com/large/TH_25121916_25131916_25126916_25136916_001.jpg"
title="Contemplative Reptile"
/>
<CardContent>
<Typography gutterBottom variant="h5" component="h2">
jnikn
</Typography>
<Typography variant="body2" color="textSecondary" component="p">
ijneodsk ipknv onfp o nf onopndsfc on pnojnc olpnoinoi hbib iubn
iujno nouno oijipj onoin ioio
</Typography>
</CardContent>
</CardActionArea>
</a>
</Card>
);
}

Target nested material component in JSS style definition

I have this JSX layout currently
<div className={classes.bottomArea}>
<Box display="flex" flexDirection="column">
<Typography variant="h1" component="span">1982</Typography>
<Typography variant="h5" component="span">Bed Count</Typography>
</Box>
</div>
And in my styles I'm trying to change the color of the h5 Typography element
bottomArea: {
$h5: {
color: "red"
}
}
I think I understand why this isn't working but is there an easy way to target that h5 variant?
Here is a codesandbox to show
https://codesandbox.io/s/material-demo-wb7ts
Assuming that you want to retain <span> as your component, you can target the h5 variant by targeting the CSS class added by Typography which is MuiTypography-h5.
In the syntax shown below, the & refers to the class generated for bottomArea and then the space indicates targeting .MuiTypography-h5 as a descendant.
import React from "react";
import Typography from "#material-ui/core/Typography";
import Box from "#material-ui/core/Box";
import { makeStyles } from "#material-ui/core/styles";
const useStyles = makeStyles({
bottomArea: {
"& .MuiTypography-h5": {
color: "red"
}
}
});
export default function Types() {
const classes = useStyles();
return (
<div className={classes.bottomArea}>
<Box display="flex" flexDirection="column">
<Typography variant="h1" component="span">
1982
</Typography>
<Typography variant="h5" component="span">
Bed Count
</Typography>
</Box>
</div>
);
}
JSS Documentation: https://cssinjs.org/jss-plugin-nested/?v=v10.3.0#use--to-reference-selector-of-the-parent-rule
Related answer: How do you change a style of a child when hovering over a parent using material-ui jss styles
You are using the Typography props the wrong way. The variant props only defines the style applied to the component whereas the component props defines which tag will be used to render this component.
If you want your Typography component to be a h5:
<Typography variant="h5" component="h5">Bed Count</Typography>
And then for the styling:
bottomArea: {
'& h5': {
color: "red"
}
}
CodeSanbox: https://codesandbox.io/s/material-demo-6i1lq?file=/demo.js
Great day !
you can use withStyle to update the specific component classes
check this Typography API
const Typography = withStyles(() => ({
h5: {
color: "red",
},
}))(MuiTypography);
export default function Types() {
return (
<div>
<Box display="flex" flexDirection="column">
<Typography variant="h1" component="span">
1982
</Typography>
<Typography variant="h5" component="span">
Bed Count
</Typography>
</Box>
</div>
);
}

Material-UI for react, how layout Card component to align texts

So essentially I want to accomplish this block I designed in Adobe XD.
Adobe XD card design
Here is my code to implement the following:
const useStyles = makeStyles({
root: {
minWidth: 275,
maxWidth: 300
},
title: {
fontSize: 14
},
pos: {
marginBottom: 5
}
});
export default function SimpleCard() {
const classes = useStyles();
const bull = <span className={classes.bullet}>•</span>;
return (
<Card className={classes.root}>
<CardContent>
<Typography
className={classes.title}
color="textSecondary"
display="inline"
>
Physics
</Typography>
<Typography display="inline" align="right" style={{ marginLeft: 110 }}>
benevolent
</Typography>
<Typography variant="body2" component="p" align="left">
10/25/2001
</Typography>
</CardContent>
</Card>
);
}
Here is the codepen link:
https://codesandbox.io/embed/material-demo-bi3sm?fontsize=14&hidenavigation=1&theme=dark
The problem with this is that in the first line I have to manually set the distance between the two typography tags. So basically the distance between Physics and Benevolence is set manually. How can I automatically determine that distance? Also How can I get closer to my design?
Flex box can accomplish what you want easily, with the following class:
const useStyles = makeStyles({
header: {
display: "flex",
justifyContent: "space-between"
}
});
And if you use a div to wrap the typography:
<div className={classes.header}>
<Typography
className={classes.title}
color="textSecondary"
display="inline"
>
Physics
</Typography>
<Typography display="inline" align="right">
benevolent
</Typography>
</div>
...
Then it accomplishes what you want.
Have you tried using flexbox? You could put each line in a div and use justify-content with the different "between" options. This would put a set distance between each depending on which option you choose.
These might be the best two options:
justify-content: space-between;
justify-content: space-around;
Also using align-items: center might be good for centering them vertically.
If this doesn't work directly, you might wanna try adding !important to the new CSS code because I know Material-UI is fussy about styling.

How to put different content for each cards

I am using material ui album template for my react app
I want to put different image and different text for each cards for this when I remove this array it create the problems in responsiveness of the cards
I tried to put separte grid for each cards but thats some how solve the issue but that responsiveness of the template does not remain same
here is my demo code
https://codesandbox.io/s/material-demo-pz8df
Make sure you're updating the right cards array. Use an array of objects as well, where each object has a key for an image-link and one for the description. In the .map() we'll use these values to render the content. Here's a working sandbox: https://codesandbox.io/s/material-demo-3v44c
The responsiveness will work like expected.
Working code:
import React from "react";
import AppBar from "#material-ui/core/AppBar";
import Button from "#material-ui/core/Button";
import CameraIcon from "#material-ui/icons/PhotoCamera";
import Card from "#material-ui/core/Card";
import CardActions from "#material-ui/core/CardActions";
import CardContent from "#material-ui/core/CardContent";
import CardMedia from "#material-ui/core/CardMedia";
import CssBaseline from "#material-ui/core/CssBaseline";
import Grid from "#material-ui/core/Grid";
import Toolbar from "#material-ui/core/Toolbar";
import Typography from "#material-ui/core/Typography";
import { makeStyles } from "#material-ui/core/styles";
import Container from "#material-ui/core/Container";
import Link from "#material-ui/core/Link";
function MadeWithLove() {
return (
<Typography variant="body2" color="textSecondary" align="center">
{"Built with love by the "}
<Link color="inherit" href="https://material-ui.com/">
Material-UI
</Link>
{" team."}
</Typography>
);
}
const useStyles = makeStyles(theme => ({
icon: {
marginRight: theme.spacing(2)
},
heroContent: {
backgroundColor: theme.palette.background.paper,
padding: theme.spacing(8, 0, 6)
},
heroButtons: {
marginTop: theme.spacing(4)
},
cardGrid: {
paddingTop: theme.spacing(8),
paddingBottom: theme.spacing(8)
},
card: {
height: "100%",
display: "flex",
flexDirection: "column"
},
cardMedia: {
paddingTop: "56.25%" // 16:9
},
cardContent: {
flexGrow: 1
},
footer: {
backgroundColor: theme.palette.background.paper,
padding: theme.spacing(6)
}
}));
const cards = [
{
img:
"https://images.unsplash.com/photo-1564135624576-c5c88640f235?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=3300&q=80",
desc: "Campsite"
},
{
img:
"https://images.unsplash.com/photo-1564198879220-63f2734f7cec?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=2072&q=80",
desc: "Space"
}
];
export default function Album() {
const classes = useStyles();
return (
<React.Fragment>
<CssBaseline />
<AppBar position="relative">
<Toolbar>
<CameraIcon className={classes.icon} />
<Typography variant="h6" color="inherit" noWrap>
Album layout
</Typography>
</Toolbar>
</AppBar>
<main>
{/* Hero unit */}
<div className={classes.heroContent}>
<Container maxWidth="sm">
<Typography
component="h1"
variant="h2"
align="center"
color="textPrimary"
gutterBottom
>
Album layout
</Typography>
<Typography
variant="h5"
align="center"
color="textSecondary"
paragraph
>
Something short and leading about the collection below—its
contents, the creator, etc. Make it short and sweet, but not too
short so folks don&apos;t simply skip over it entirely.
</Typography>
<div className={classes.heroButtons}>
<Grid container spacing={2} justify="center">
<Grid item>
<Button variant="contained" color="primary">
Main call to action
</Button>
</Grid>
<Grid item>
<Button variant="outlined" color="primary">
Secondary action
</Button>
</Grid>
</Grid>
</div>
</Container>
</div>
<Container className={classes.cardGrid} maxWidth="md">
{/* End hero unit */}
<Grid container spacing={4}>
{cards.map(card => (
<Grid item key={card} xs={12} sm={6} md={4}>
<Card className={classes.card}>
<CardMedia
className={classes.cardMedia}
image={card.img}
title="Image title"
/>
<CardContent className={classes.cardContent}>
<Typography gutterBottom variant="h5" component="h2">
Heading
</Typography>
<Typography>{card.desc}</Typography>
</CardContent>
<CardActions>
<Button size="small" color="primary">
View
</Button>
<Button size="small" color="primary">
Edit
</Button>
</CardActions>
</Card>
</Grid>
))}
</Grid>
</Container>
</main>
{/* Footer */}
<footer className={classes.footer}>
<Typography variant="h6" align="center" gutterBottom>
Footer
</Typography>
<Typography
variant="subtitle1"
align="center"
color="textSecondary"
component="p"
>
Something here to give the footer a purpose!
</Typography>
<MadeWithLove />
</footer>
{/* End footer */}
</React.Fragment>
);
}

Resources