Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Make child of Material UI Grid item stretch to fit the remaining height of the parent container

1. Current Appearance

I have a Material UI Grid container with 4 Grid items. Within each Grid item is a Typography component containing a title and a Card with some content, as shown below:

enter image description here

2. Desired appearance

I would like the Cards to fill the remaining height of the Grid items and not exceed it. This is my desired output:

enter image description here

3. Undesirable appearance (card height = 100%)

I have tried making the height of the Cards 100% but this means each Card takes on the height of its parent (the Grid item), and the height of the parent = Typography + Card (rather than the remaining space minus the Typography), so the result is that the Card then exceeds the height of the parent Grid item as below:

enter image description here

What is the best way to overcome this problem? I'm using Material UI's Grid to make the breakpoints easy and consistent with the rest of my project, so ideally the solution would use that approach.

Here is the code:

import React from 'react';

const useStyles = makeStyles(theme => ({
   // stretch: { height: '100%' }, // Un-commenting this results in undesirable appearance 3 (see image 3 above)
    outline: { border: '1px solid red' },
}));

const Sections= () => {
  const classes = useStyles();

  return (
    <Grid container spacing={3} justify="space-between" alignItems="stretch" className={classes.outline}>
      <Grid item xl={2} lg={2} md={6} xs={12} className={classes.outline}>
          <Typography className={classes.outline}>Big title 1</Typography>
          <Card className={classes.stretch}><CardContent>Lots and lots and lots and lots and lots and lots of content</CardContent></Card>
      </Grid>
   <Grid item xl={4} lg={4} md={6} xs={12} className={classes.outline}>
          <Typography className={classes.outline}>Big title 2</Typography>
          <Card className={classes.stretch}><CardContent>Not much content</CardContent></Card>
   </Grid>
   <Grid item xl={3} lg={3} md={6} xs={12} className={classes.outline}>
          <Typography className={classes.outline}>Big title 3</Typography>
          <Card className={classes.stretch}><CardContent>Not much content</CardContent></Card>
   </Grid>
   <Grid item xl={3} lg={3} md={6} xs={12} className={classes.outline}>
          <Typography className={classes.outline}>Big title 4</Typography>
          <Card className={classes.stretch}><CardContent>Not much content</CardContent></Card>
   </Grid>
</Grid>
  );
};


export default Sections;

Many thanks,

Katie

like image 786
Katie7 Avatar asked Jan 20 '21 18:01

Katie7


People also ask

How do you align items in grid material UI?

Material-UI Grid Center Align and Vertical Align However, if you wanted to achieve vertical alignment using CSS, you would want to use align items with one of the following values: flex-start: vertically aligns top. center: vertically aligns center. flex-end: vertically aligns bottom.

How do you set height in material UI?

To set a height of a dialog in React Material UI, we can set the classes prop of the dialog to an object that has the paper property set to a class that has the height style. We call makeStyles with a function that returns an object with the dialog property. It's set to an object with the height set to 500 pixels.

Can material UI grid be container and an item?

Material Design's grid system is implemented in MUI using the <Grid /> component. Under the hood, the <Grid /> component uses Flexbox properties for greater flexibility. There are two types of grid components: containers and items.

How do you use offset in material UI grid?

Just use a box with margin (mx) or padding px where x is horizontal. In my opinion this is better than introducing more css classes and properties that need maintenance. px gives padding in pixels, whereas offset is used in terms of grid columns.

How do I stretch a material-UI grid?

Stretch all items in a Material-UI Grid row to be the same height. Achieve a “masonry-style” layout where shorter and narrower items can wrap in a column when vertical space allows The first is simple to accomplish, requiring only a well-placed height: “100%” .

How does spacing work in the material-UI grid?

The Material-UI Grid is composed of individual children Grids with either a container or item layout prop enabled. The container and item props affect when and how spacing, padding, and margin can be used. We will explore how spacing renders in the DOM. For example, spacing= {3} only adds padding-top and padding-left. This is by design.

How to make container shrink-to-fit child elements as they wrap?

- GeeksforGeeks How to make container shrink-to-fit child elements as they wrap? A Flexible Layout must have a parent element having display property set to flex. Direct child elements of the flexible container automatically become flexible items. The element below represents a flex container with four flex items.

How to stretch a Div inside a container using CSS?

A child div inside a container can be made to take the complete width and height of the parent div. There are two methods to stretch the div to fit the container using CSS tat are discussed below: Method 1: First method is to simply assign 100% width and 100% height to the child div so that it will take all available space of the parent div.


2 Answers

To solve this, you need to set a height for each individual Grid Item. Then you can display the Grid Item flexed with the flex-direction of "column". Next, you can set the height of the card to 100% as you had before. The default display mechanism in the Material-UI grid is not set to flex so the card will extend outside of the border since they use things like negative margins.

The code is below:

// imports omitted

const useStyles = makeStyles(theme => ({
  stretch: { height: "100%" },
  item: { display: "flex", flexDirection: "column" } // KEY CHANGES
}));

export const Sections = () => {
  return (
    <Grid container spacing={2} justify="space-between" alignItems="stretch">
      <Item xl={2} lg={2} md={6} xs={12} title="Big Title 1" content="Lots and lots and lots and lots and lots and lots of content!" />
      <Item xl={4} lg={4} md={6} xs={12} title="Big Title 2" content="Not much content" />
      <Item xl={3} lg={3} md={6} xs={12} title="Big Title 3" content="Not much content" />
      <Item xl={3} lg={3} md={6} xs={12} title="Big Title 4" content="Not much content" />
    </Grid>
  );
}

const Item = ({ title, content, ...rest }) => {
  const classes = useStyles();

  return (
    <Grid className={classes.item} item {...rest}>
      <Typography>{title}</Typography>
      <Card className={classes.stretch}>
        <CardContent>{content}</CardContent>
      </Card>
    </Grid>
  );
};

Checkout stackblitz for a live example.

like image 90
Charles Kornoelje Avatar answered Oct 24 '22 05:10

Charles Kornoelje


to make the Card remaining height always, give a height to Typography. let's say the height of Typography is 20px and then set the height of the CardItem as 100% - (height of the typography_ i.e; `height:'calc(100% - 20px)'. It'll take the remaining height.

const useStyles = makeStyles((theme) => ({
    stretch: {
        height: 'calc(100% - 20px)'
    }, // Un-commenting this results in undesirable appearance 3 (see image 3 above)
    outline: { border: "1px solid red" }
}));
<Grid
  container
  spacing={3}
  justify="space-between"
  alignItems="stretch"
  className={classes.outline}>
  <Grid item xl={2} lg={2} md={6} xs={12} className={classes.outline}>
    <Typography style={{height:'20px'}} className={classes.outline}>Big title 1</Typography>
    <Card className={classes.stretch}>
      <CardContent>
        Lots and lots and lots and lots and lots and lots of content
      </CardContent>
    </Card>
  </Grid>
  <Grid item xl={4} lg={4} md={6} xs={12} className={classes.outline}>
    <Typography style={{height:'20px'}} className={classes.outline}>Big title 2</Typography>
    <Card className={classes.stretch}>
      <CardContent>Not much content</CardContent>
    </Card>
  </Grid>
  <Grid item xl={3} lg={3} md={6} xs={12} className={classes.outline}>
    <Typography style={{height:'20px'}} className={classes.outline}>Big title 3</Typography>
    <Card className={classes.stretch}>
      <CardContent>Not much content</CardContent>
    </Card>
  </Grid>
  <Grid item xl={3} lg={3} md={6} xs={12} className={classes.outline}>
    <Typography style={{height:'20px'}} className={classes.outline}>Big title 4</Typography>
    <Card className={classes.stretch}>
      <CardContent>Not much content</CardContent>
    </Card>
  </Grid>
</Grid>

Edit gallant-violet-k9tqs

like image 42
Rajiv Avatar answered Oct 15 '22 09:10

Rajiv