Understanding the Difference Between the Flex and Flex-Grow Properties

Understanding the difference between the flex and flex-grow properties

flex is a shorthand property of flex-grow, flex-shrink and flex-basis.

In this case, flex: 1 sets

  • flex-grow: 1
  • flex-shrink: 1
  • flex-basis: 0 (in old spec drafts it was flex-basis: 0%)

If you only use flex-grow: 1, you will have

  • flex-grow: 1
  • flex-shrink: 1
  • flex-basis: auto

Then, the difference is that the flex base size will be 0 in the first case, so the flex items will have the same size after distributing free space.

In the second case each flex item will start with the size given by its content, and then will grow or shrink according to free space. Most probably the sizes will end up being different.

The difference between flex:1 and flex-grow:1

flex

The flex property is a shorthand for setting:

  • flex-grow
  • flex-shrink
  • flex-basis

The flex: 1 rule is supposed to compute to this:

  • flex-grow: 1
  • flex-shrink: 1
  • flex-basis: 0

These values are defined in the spec. See section 7.1.1. Basic Values of flex

I say "supposed to compute" because, in IE11 and possibly other browsers, a unit of measure, such as px or %, is appended to the 0 value in flex-basis. This can make a difference (example).


flex-grow

The flex-grow property (which distributes free space in the container among flex items), when declared by itself, leaves flex-shrink and flex-basis at their initial values.

So when you set flex-grow: 1, the browser renders this:

  • flex-grow: 1 (overrides the default value, which is 0)
  • flex-shrink: 1 (this is the default value)
  • flex-basis: auto (this is the default value)

The difference between flex: 1 and flex-grow: 1

Ultimately, the difference between flex: 1 and flex-grow: 1 is that the former sets flex-basis: 0, and the latter keeps the default flex-basis: auto.

For a complete explanation of the difference between flex-basis: 0 and flex-basis: auto see this post:

  • Make flex-grow expand items based on their original size

Your code example

The reason you're seeing a difference in your code is that flex-basis controls height in a column-direction container.

In Chrome, with flex-basis: auto, the height of the element is 450px (500px parent - 50px header). In other words, flex-grow is free to distribute the free space.

With flex-basis: 0, the height of the element is 0, and flex-grow has no free space to distribute.

The height: 100% on the child of the flex item is simply ignored because it isn't being applied properly, as explained in these posts:

  • Working with the CSS height property and percentage values
  • Chrome / Safari not filling 100% height of flex parent

In reading the posts above you'll also understand why your code renders differently in Firefox, Safari, Edge and IE.

flex vs flex-grow producing different results

When you set only flex-grow, the flex-basis property remains unaffected. It still defaults to flex-basis: auto.

When you use the flex property, flex-basis gets reset to 0.

So flex: 0 is shorthand for flex-grow: 0 and flex-basis: 0. This means 0 width.

With flex-grow: 0 you still have flex-basis: auto.

To understand the difference between flex-basis: 0 and flex-basis: auto, see this post:

  • Make flex-grow expand items based on their original size

What are the differences between flex-grow and width?

width and flex-grow are two entirely different CSS properties.

The width property is used for defining the width of elements.

The flex-grow property is used for distributing free space in a flex container. This property doesn't apply a specific length to an element, like the width property. It simply allows a flex item to consume whatever space may be available.

Sometimes if I want one element to grow the rest of the space, I can either do width: 100% or flex-grow: 1. How do I choose?

Yes, if there is one element in the row, width: 100% and flex-grow: 1 may have the same effect (depending on padding, border and box-sizing settings).

But what if there are two elements, and you want the second one to take the remaining space? With a sibling in the container, width: 100% causes an overflow. I guess you can do something like this:

width: calc(100% - width of sibling);

But what if the sibling's width is dynamic or unknown? calc is no longer an option.

The quick and easy solution is flex-grow: 1.


While width and flex-grow are apples-to-oranges, width and flex-basis are apples-to-apples.

The flex-basis property sets the initial main size of a flex item and is similar to width.

  • What are the differences between flex-basis and width?

For the differences between flex-basis and flex-grow see:

  • flex-grow not sizing flex items as expected

What is the difference between the flex and height properties?

When you set an element to flex: 1, that breaks down to:

  • flex-grow: 1
  • flex-shrink: 1
  • flex-basis: 0

In a column-direction container (like you have), the flex properties above apply vertically. This means that flex-basis and height are equivalent properties.

flex-basis = height (in a column-direction container)

There is an obvious difference between flex-basis: 0 and height: 100%. It's the same difference as height: 0 and height: 100%.

In your situation, where there is a .header and a .footer consuming 140px of vertical space, setting the middle item (.body) to height: 100% would normally cause an overflow.

But since an initial value of a flex container is flex-shrink: 1, flex items are permitted to shrink, and this wouldn't happen. However, it's still sloppy and imprecise coding, in my view.

By setting .body to flex: 1, you're setting the height to 0, but also allowing it to consume free height with flex-grow: 1. I would say, in this case, that this solution is more efficient.


More details:

  • What are the differences between flex-basis and width?
  • § 7.1.1. Basic Values of flex

Do I not understand the flex-grow property?

You have to specify a value for flex-basis as well (not specifying this property causes behaviour similar to using the initial value, auto).

Add flex-basis: 0; to both children or just set it with the shorthand:

.flex-item {
flex: 1; /* flex-basis is 0 if omitted */
}
.big {
flex-grow: 3;
}

http://codepen.io/anon/pen/JEcBa

Understanding flex-grow and flex-shrink when using flex-basis

Percentage lengths are relative to their containing blocks.

Therefore, if the flex container has a width of 200px, and the flex items are set to flex-basis: 50%, then each item will resolve to 100px.

Of course, in flex layout, flex-basis represents the initial main size or, the size before flex-grow and flex-shrink are applied.

You have flex-grow disabled, so nothing happens there.

But you have flex-shrink enabled, so the items will shrink below 100px when necessary to prevent an overflow of the container.

In this case, because all items are set to flex-shrink: 1, they will shrink in equal proportion.

article {  display: flex;  width: 200px;  border: 1px solid black;}
[one] > section { flex: 0 1 50px;}
[two] > section { flex: 0 1 50%;}
[three] > section { flex: 0 0 50%;}

/* non-essential demo styles */section { height: 50px; background-color: lightgreen; border: 1px solid #ccc; display: flex; justify-content: center; align-items: center; box-sizing: border-box;}
<p>container width 200px in all cases</p><article one>  <section><span>50px</span></section>  <section><span>50px</span></section>  <section><span>50px</span></section>  <section><span>50px</span></section></article>
<hr>
<p><code>flex-shrink</code> enabled</p>
<article two> <section><span>50%</span></section> <section><span>50%</span></section> <section><span>50%</span></section> <section><span>50%</span></section></article>
<hr>
<p><code>flex-shrink</code> disabled</p>
<article three> <section><span>50%</span></section> <section><span>50%</span></section> <section><span>50%</span></section> <section><span>50%</span></section></article>


Related Topics



Leave a reply



Submit