Prince Umbrella
Prince Umbrella

Reputation: 29

Create a grid with variable card heights using material-ui react

I am trying to create a grid similar to this website by using Material-UI. However when the height of one card changes every card height changes. I tried to use direction="row" and direction="column" but it doesn't seem to work. I was wondering if there a way to change the height of the image inside depending on the size of the image while having a grid like the website above.

All I can see at the moment is this: enter image description here

Here is my code for the card:

import React from 'react';
import Card from '@material-ui/core/Card';
import CardHeader from '@material-ui/core/CardHeader';
import CardMedia from '@material-ui/core/CardMedia';
import CardContent from '@material-ui/core/CardContent';
import CardActions from '@material-ui/core/CardActions';
import Avatar from '@material-ui/core/Avatar';
import IconButton from '@material-ui/core/IconButton';
// import Typography from '@material-ui/core/Typography';
import FavoriteIcon from '@material-ui/icons/Favorite';
import ShareIcon from '@material-ui/icons/Share';
import MoreVertIcon from '@material-ui/icons/MoreVert';
import { useStyles } from '../style/card.styles';


export default function Cards({ profile, sourceImage }) {
    const classes = useStyles();

    return (
        <Card className={classes.root} style={{ height: '100%' }}>
            <CardHeader
                avatar={
                    <Avatar aria-label="recipe" src={profile} className={classes.avatar}>
                    </Avatar>
                }
                action={
                    <IconButton aria-label="settings">
                        <MoreVertIcon />
                    </IconButton>
                }
                title="Shrimp and Chorizo Paella"
                subheader="September 14, 2016"
            />

            <CardContent>
                <CardMedia
                    className={classes.media}
                    image={sourceImage}
                    title="Paella dish"
                />
                {/* <img src={sourceImage} style={{ maxHeight: '20rem' }} /> */}
            </CardContent>
            <CardActions disableSpacing>
                <IconButton aria-label="add to favorites">
                    <FavoriteIcon />
                </IconButton>
                <IconButton aria-label="share">
                    <ShareIcon />
                </IconButton>
            </CardActions>
        </Card>
    );
}

And the layout page:

import React from 'react';
import { makeStyles } from '@material-ui/core/styles';
import Grid from '@material-ui/core/Grid';
import Cards from './Card';
import vertical from '../images/v1.jfif';
import horizontal from '../images/h1.png';
import '../style/card.css';

const useStyles = makeStyles((theme) => ({
    root: {
        flexGrow: 1,
    },
    paper: {
        height: 140,
        width: 100,
    },
    control: {
        padding: theme.spacing(2),
    }
}));

export default function HomePage() {
    const imagess = [vertical, horizontal, vertical, horizontal]
    const classes = useStyles();

    return (
        <Grid container justify="center" className={classes.root} spacing={2}>
            <Grid item xs={12}>
                <Grid container alignItems="flex-start" justify="center" spacing={1}>
                    {imagess.map((image, index) => (
                        <Grid key={index} item>
                            <Cards profile={""} sourceImage={image} />
                        </Grid>
                    ))}
                </Grid>
                <Grid container alignItems="flex-start" justify="center" spacing={1}>
                    {imagess.map((image, index) => (
                        <Grid key={index} item>
                            <Cards profile={""} sourceImage={image} />
                        </Grid>
                    ))}
                </Grid>
            </Grid>
        </Grid>
    );
}

Upvotes: 0

Views: 2202

Answers (1)

Julian Kleine
Julian Kleine

Reputation: 1547

I think what you are looking for is a masonry grid. It's worth a google search. What these packages do is calculate positions within a container on page load and resize. One example for react could be react-responsive-masonry

Example usage with react-responsive-masonry

import React from "react"
import Masonry, {ResponsiveMasonry} from "react-responsive-masonry"

// The number of columns change by resizing the window
class MyWrapper extends React.Component {
    render() {
        return (
            <ResponsiveMasonry
                columnsCountBreakPoints={{350: 1, 750: 2, 900: 3}}
            >
                <Masonry>
                    <ChildA />
                    <ChildB />
                    {/* Children */}
                    <ChildY />
                    <ChildZ />
                </Masonry>
            </ResponsiveMasonry>
        )
    }
}

// The number of columns don't change by resizing the window
class MyWrapper extends Component {
    render() {
        return (
            <Masonry columnsCount={3}>
                <ChildA />
                <ChildB />
                {/* Children */}
                <ChildY />
                <ChildZ />
            </Masonry>
        )
    }
}

In case of the material ui you would basically replace the Grid and only render cards inside the Masonry.

Upvotes: 2

Related Questions