Make Flex-Grow Expand Items Based on Their Original Size

Make flex-grow expand items based on their original size

Short Answer

Switch from flex: 1 to flex: auto.



Explanation

The flex-grow property factors in two key pieces of data:

  1. The free space in the row / column where it is being used.
  2. The value of the flex-basis property.

Distribution of Free Space

The flex-grow property distributes free space in the container among flex items in the same line.

If there is no free space, flex-grow has no effect.

If there is negative free space (i.e., the total length of flex items is greater than the length of the container), then flex-grow has no effect and flex-shrink comes into play.


The flex-basis factor

When flex-basis is 0, flex-grow ignores the size of the content in flex items and treats all space on the line as free space.

This is absolute sizing. All space on the line is distributed.

When flex-basis is auto, the size of the content in flex items is first deducted to determine the free space in each item. flex-grow then distributes the free space among items (based on each item's flex-grow value).

This is relative sizing. Only extra space on the line is distributed.

Here's an illustration from the spec:

Sample Image


Examples:

  • flex: 1 (absolute sizing)

This shorthand rule breaks down to: flex-grow: 1 / flex-shrink: 1 / flex-basis: 0

Applied to all flex items, this will make them equal length, regardless of content. (Note that in some cases an override of default minimum sizing will be necessary for this effect to occur.)

  • flex-grow: 1 (relative sizing)

This rule by itself will factor in both content size and available space, because the default value for flex-basis is auto.

  • flex: auto (relative sizing)

This shorthand factors in both content size and available space because it breaks down to:

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

More variations here: 7.1.1. Basic Values of flex

additional keywords for search: difference between flex-basis auto 0 flex 1 auto

flex items not expanding or shrinking with flex-grow

There are two pieces missing in this puzzle.

  1. You have the column widths set to flex-grow: 1. This means that flex-basis is still at its default value, auto (content-based). So the column is sized based on the image size. You can add flex-basis: 0, or just use flex: 1.

    Full explanation: Make flex-grow expand items based on their original size




  1. Flex items, by default, cannot shrink below the size of their content. Their initial setting is min-width: auto. You need to override this default with min-width: 0.

    Full explanation: Why don't flex items shrink past content size?

.row {
display: flex;
height: 100vh;
}

.column {
min-width: 0; /* new */
flex: 1; /* adjustment */
border: 2px solid #000;
transition: all 300ms ease-in-out;
}

.column:hover {
flex-grow: 4.3;
}

body {
margin: 0;
}
<div class="row">
<div class="column">
<img src="https://images.pexels.com/photos/2194261/pexels-photo-2194261.jpeg">
</div>
<div class="column">
<img src="https://images.pexels.com/photos/1276553/pexels-photo-1276553.jpeg">
</div>
<div class="column">
<img src="https://images.pexels.com/photos/774731/pexels-photo-774731.jpeg">
</div>
</div>

Make flex item grow past (larger) than flex container

Maybe I have not understand well your problem. When I tried on JsFiddle, I have the result you seem to wish. Element hovered is bigger than the parent element "row".

.row{
position: relative;
display: flex;
background: blue;
}

.cards{
width: 50px;
height: 50px;
background: red;
margin: 10px;
}

.cards:hover{
transform: scale(1.5);
}
<div class="row">
<div class="cards">1</div>
<div class="cards">1</div>
<div class="cards">1</div>
</div>

https://jsfiddle.net/nesquimo/vbb8td62/1/

How can I allow flex-items to grow while keeping the same size?

This is something that cannot be expressed via CSS Flexbox right now. Someone asked basically this exact question on the CSS Working Group Mailing List a few days ago, and the response was: "At the moment, no, this is not possible. This is a high-priority item for Flexbox 2, though.

You may be able to hack up something like you want using max-width, though -- that'll prevent flex items (particularly those on the last line) from growing indefinitely. Here's a forked version of your plunk with a nonzero flex-grow, and with max-width: 10em.

(I chose 10em arbitrarily; you could also use e.g. max-width: calc(100%/5), if you want to make sure each flex item takes up no more than 1/5 of the line, for example.)

Make flex items have equal width in a row

Flexbox method

In order to make the text items (.section-child) equal width, you need to use flex: 1 1 0, which you have done. This is the same as saying flex: 1.

However, this by itself doesn't achieve the goal for two reasons:

  1. The parent of .section-child, a flex container, but also a flex item in a larger container, is limited to the width of its content, by default. So it won't expand and the text can overflow the container. You need to apply flex: 1 to .section, as well.

  2. A flex item cannot be smaller than the size of its content, by default. The initial setting is min-width: auto. So flex: 1 cannot work to equally distribute container space, because a flex item cannot shrink past the longest item. You need to override this behavior with min-width: 0.

.top-level {  display: flex;  flex-flow: row wrap;}
.section { display: flex; flex-flow: row nowrap; border: 1px solid; margin-right: 12px; margin-top: 12px; flex: 1; min-width: 0;}
.section-child { display: flex; flex-flow: column nowrap; align-items: center; flex: 1; min-width: 0;}
.child-title { white-space: nowrap;}
.vertical-separator { width: 1px; background-color: rgba(0, 0, 0, 0.3); margin: 8px;}
<div class="top-level">  <section class="section">    <div class="section-child">      <h4 class="child-title">Title</h4>      <!--A lot more content here-->    </div>    <div class="vertical-separator"></div>    <div class="section-child">      <h4 class="child-title">Longer title</h4>      <!--A lot more content here-->    </div>    <div class="vertical-separator"></div>    <div class="section-child">      <h4 class="child-title">Much much longer title</h4>      <!--A lot more content here-->    </div>  </section>  <section class="section">    <div class="section-child">      <h4 class="child-title">Title</h4>      <!--A lot more content here-->    </div>    <div class="vertical-separator"></div>    <div class="section-child">      <h4 class="child-title">Longer title</h4>      <!--A lot more content here-->    </div>    <div class="vertical-separator"></div>    <div class="section-child">      <h4 class="child-title">Much much longer title</h4>      <!--A lot more content here-->    </div>  </section>  <section class="section">    <div class="section-child">      <h4 class="child-title">Title</h4>      <!--A lot more content here-->    </div>    <div class="vertical-separator"></div>    <div class="section-child">      <h4 class="child-title">Longer title</h4>      <!--A lot more content here-->    </div>    <div class="vertical-separator"></div>    <div class="section-child">      <h4 class="child-title">Much much longer title</h4>      <!--A lot more content here-->    </div>  </section></div>

Fill the remaining height or width in a flex container

Use the flex-grow property to make a flex item consume free space on the main axis.

This property will expand the item as much as possible, adjusting the length to dynamic environments, such as screen re-sizing or the addition / removal of other items.

A common example is flex-grow: 1 or, using the shorthand property, flex: 1.

Hence, instead of width: 96% on your div, use flex: 1.


You wrote:

So at the moment, it's set to 96% which looks OK until you really squash the screen - then the right hand div gets a bit starved of the space it needs.

The squashing of the fixed-width div is related to another flex property: flex-shrink

By default, flex items are set to flex-shrink: 1 which enables them to shrink in order to prevent overflow of the container.

To disable this feature use flex-shrink: 0.

For more details see The flex-shrink factor section in the answer here:

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

Learn more about flex alignment along the main axis here:

  • In CSS Flexbox, why are there no "justify-items" and "justify-self" properties?

Learn more about flex alignment along the cross axis here:

  • How does flex-wrap work with align-self, align-items and align-content?

How to create a flex item that shrinks before it wraps?

The problem is not flex-shrink. The problem is flex-basis. You have it set to 50%.

This means that flex-grow will add free space to the flex-basis, and each item will wrap quickly, before it has an opportunity to shrink.

Switch from flex-basis: 50% to flex-basis: 0.

More specifically, instead of flex: 1 1 50% use flex: 1, which breaks down to this:

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

Now flex-grow distributes free space equally – not proportionally – to both items, and they can shrink before they wrap.

(Here's a more in-depth explanation: Make flex-grow expand items based on their original size)

.m {  display: flex;  flex-wrap: wrap;}
.l_1 { background-color: red; flex: 1;}
.r_1 { background-color: yellow; flex: 1;}
<div class=m>  <div class=l_1>left_______________________________________________X</div>  <div class=r_1>right</div></div>

How to make flexbox items the same size?

Set them so that their flex-basis is 0 (so all elements have the same starting point), and allow them to grow:

flex: 1 1 0px

Your IDE or linter might mention that the unit of measure 'px' is redundant. If you leave it out (like: flex: 1 1 0), IE will not render this correctly. So the px is required to support Internet Explorer, as mentioned in the comments by @fabb;

Make one item of a flexbox half or a quarter size of other items

Trying flex: .5 1 0 should work. That should size it the way you want.



Related Topics



Leave a reply



Submit