How to Use MUI Flexbox: Flex-Grow and Flex-Shrink

The flexbox module is a direction agnostic layout system made for managing the layout of a component. Flex is designed for optimizing layout when available space is unknown or dynamic.

The flexbox layout includes props set on both parent and children elements to control child size and order. Read an incredibly detailed overview of the flexbox module here.

The Material-UI Flexbox system lets you quickly apply flex properties from the flexbox module without adding CSS classes or inline styling. Instead, simply apply props such as display, justifyContent, and flexGrow.

In this article, we’ll briefly cover the properties for parent components in Material-UI’s flexbox system. I already covered them extensively in this article on aligning items in any direction in Material-UI’s Grid. Mostly we’ll focus on the child properties (flexGrow, flexShrink, alignSelf). We will create the series of layouts below and analyze them:

MUI Flexbox System
Material-UI Flexbox System

In MUI V4, Container does not have access to the flex system, but Box and Grid components do. Even the Grid component only has access to the parent flex properties. If you wanted, you could still create a flex container component by manually applying CSS flexbox styling.

Material-UI Align-Self

Each of the layouts pictured above are composed of a parent Box component and three or four child Box components.

The first layout uses flexDirection="row" (which is the default). This aligns items in a horizontal layout of one row, three columns. The second layout uses flexDirection="column". This aligns the children items in a vertical layout of one column, three rows. See the below image captured before alignSelf was used to override alignItems.

Flex-Direction

Both of these layouts utilize alignItems="flex-start" at the parent level. All children items will be aligned at the ‘start’ of the parent area: for rows this means ‘top’ and for column it means ‘left’. The ‘flexDirection row 1’ and ‘flexDirection column 1’ components are examples of this.

The alignSelf property is a child-level property that overrides the parent level alignItems value (read more about align-self here at MDN). Also, when discussing CSS, the syntax uses hyphens (align-self) but in JS the syntax is camel case (alignSelf).

Here are the alignSelf values and results in the first two layouts:

  • ‘flexDirection row 2’: alignSelf=”center” === vertical center
  • ‘flexDirection row 3’: alignSelf=”flex-end” === vertical bottom
  • ‘flexDirection column 2’: alignSelf=”center” === horizontal center
  • ‘flexDirection column 3’: alignSelf=”flex-end” === horizontal right

Here’s the code that accomplishes this:

<Box
  display="flex"
  alignItems="flex-start"
  //flexDirection="row" This is the default
  p={1}
  m={1}
  bgcolor="background.paper"
  sx={{ height: 100 }}
>
  <Box p={1} bgcolor="grey.300">
    flexDirection Row 1
  </Box>
  <Box p={1} bgcolor="grey.300" alignSelf="center">
    flexDirection Row 2
  </Box>
  <Box p={1} bgcolor="grey.300" alignSelf="flex-end">
    flexDirection Row 3
  </Box>
</Box>
<Box
  display="flex"
  alignItems="flex-start"
  flexDirection="column"
  p={1}
  m={1}
  bgcolor="background.paper"
  sx={{ height: 100 }}
>
  <Box p={1} bgcolor="grey.300">
    flexDirection Column 1
  </Box>
  <Box p={1} bgcolor="grey.300" alignSelf="center">
    flexDirection Column 2
  </Box>
  <Box p={1} bgcolor="grey.300" alignSelf="flex-end">
    flexDirection Column 3
  </Box>
</Box>

Material-UI Flex-Grow

The flexGrow property (flex-grow in CSS) is used to set the size of an element relative to it’s siblings within a flex container (a Box component in this case) and dynamically grow relative to available space. Here is a deep flex-grow tutorial with only CSS and React.

Elements with equivalent flexGrow values will get the same amount of space. An element with flexGrow={2} will have twice the size as an element with flexGrow={1}.

Interestingly, if you set flexGrow={0} it has the effect of keeping an item from growing beyond it’s original size. This is hard to notice, but is more obvious when using flexShrink={0} as I’ll show in the next section.

Flex-Grow

Above is Layout 3, which is composed of three Box components. The first and third have the same flexGrow value and evenly take up all the width except for the width taken up by ‘flexGrow 2’. This center box has the same width in this case whether flexGrow is zero or removed altogether.

<Box display="flex" p={1} bgcolor="background.paper">
  <Box p={1} flexGrow={2} bgcolor="grey.300">
    Flexgrow 1
  </Box>
  <Box p={1} flexGrow={0} bgcolor="grey.300">
    Flexgrow 2
  </Box>
  <Box p={1} flexGrow={2} bgcolor="grey.300">
    Flexgrow 3
  </Box>
</Box>

Material-UI Flex-Shrink

The flexShrink property (flex-shrink in CSS) is used to set the size of an element relative to it’s siblings within a flex container (a Box component again in this case) similar to flexGrow. However, the emphasis here is if child elements combined are larger than the parent container, flexShrink values determine how sibling elements shrink proportionately to fit the space.

I artificially constrained the width of the parent Box to 40%. The children have the following values:

  • ‘FlexShrink1’: flexShrink={1}, receives up 2X the space of FlexShrink3 component
  • ‘FlexShrink2’: flexShrink={0}, does not shrink below it’s initial value
  • ‘FlexShrink3’: flexShrink={2}, half the space of FlexShrink1
  • ‘FlexShrink4’: No flexShrink value assigned, it receives the same width as FlexShrink1
<Box display="flex" width="40%" p={1} bgcolor="background.paper">
  <Box p={1} flexShrink={1} bgcolor="grey.300">
    F l e x s h r i n k 1
  </Box>
  <Box p={1} flexShrink={0} bgcolor="grey.300">
    F l e x s h r i n k 2
  </Box>
  <Box p={1} flexShrink={2} bgcolor="grey.300">
    F l e x s h r i n k 3
  </Box>
  <Box p={1} bgcolor="grey.300">
    F l e x s h r i n k 4
  </Box>
</Box>

Resources

Read how to align buttons in a variety of layouts with the Box component here.

Code Sandbox Link

Share this post:

Leave a Comment

This site uses Akismet to reduce spam. Learn how your comment data is processed.