2

Specifically, I want to know, in the example below, why setting a height value to the first flex-item changes (actually increases) the height of the first row.

Generally, I want to be able to determine the height of a row (I suppose when the height of the flex-container is set to auto or an explicit value).

.flex-container {
  display: flex;
  flex-wrap: wrap;
  width: 400px;
  height: 200px;
  border: 1px solid black;
  align-items: stretch;
}

.flex-container> :nth-child(1) {
  background-color: darkorchid;
  height: 60px;
}

.flex-container> :nth-child(2) {
  background-color: darkkhaki;
}

.flex-container> :nth-child(3) {
  background-color: dodgerblue;
}

.flex-container> :nth-child(4) {
  background-color: darkgoldenrod;
}

.flex-container> :nth-child(5) {
  background-color: darkcyan;
}
<div class="flex-container">
  <span>I am number 1</span>
  <div>I am number 2</div>
  <div>I am number 3</div>
  <div>I am number 4</div>
  <span>I am number 5</span>
</div>
Michael Benjamin
  • 346,931
  • 104
  • 581
  • 701
tonitone106
  • 149
  • 7
  • I know a perfect question detaling this .. need to find it now -.-. As a quick explanation you remove the 60px from 200px (to get 140px as free space (litte less because you have to consider the text of green one) then you split this in 2 (70px) which will give the first line around 60px + 70px and the second one around 70px – Temani Afif Jun 12 '20 at 21:30
  • found it, consider reading both answers to get different views and you will understand how align-content is controling all this – Temani Afif Jun 12 '20 at 21:56
  • @Temani Afif your answer doesn't seem right. First the code is giving 3 rows not 2, Second the question is really why is making the first element 60px in height making the seconfd element larger than 60px in height? – DCR Jun 12 '20 at 21:56
  • @TemaniAfif, although the duplicate does provide some guidance in understanding this question, I think a more specific answer would be useful in this case. – Michael Benjamin Jun 12 '20 at 21:59
  • @DCR in which browser you see 3 rows? there is only two and they called *flex lines* and if you check the height of the stretched element you will see that my calculation are correct. Not exactly the same because I made a fast explanation (we need to also consider the content) – Temani Afif Jun 12 '20 at 22:00
  • @MichaelBenjamin ok, feel free to reopen the question and to give an answer. I was refering to the section of your answer in the duplicate *Why is the first row taller than the second row with* where you are detailing the calculation. I was thinking it should be enough but maybe because I am already used to all this now. – Temani Afif Jun 12 '20 at 22:02
  • Yes, it's not a bad reference. Just thinking a more targeted answer in this case would be easier to understand. @TemaniAfif – Michael Benjamin Jun 12 '20 at 22:03
  • @TemaniAfif I use chrome. I see number 1 and 2 on the first line, 3 and 4 on the second line and 5 on the 3rd line. true in full page. Another way to ask this: suppose 1 and 2 have height:60px why don;t the others take up the rest of the space? – DCR Jun 12 '20 at 22:04
  • @MichaelBenjamin go ahead then ;) after all the reference is yours so you can have a tailored answer based on it. – Temani Afif Jun 12 '20 at 22:07
  • @DCR not sure how you are getting such output but even it it's the case my logic still apply. Your remove 60px from 200px to get 140px that you split into 3 (around 47px) which will give the first items at around 107px and the other around 47px (few pixel of different because I am not consider the text) – Temani Afif Jun 12 '20 at 22:09
  • Would it be possible to link the other question anyway @TemaniAfif? – tonitone106 Jun 13 '20 at 00:21
  • you can find it in the revision: https://stackoverflow.com/posts/62352474/revisions – Temani Afif Jun 13 '20 at 00:26

3 Answers3

3

An initial setting of a flex container is align-content: stretch. This means that flex lines (i.e., "rows" or "columns") will expand the cross axis of the container equally. And that's what you get when you don't set any heights on the items:

.flex-container {
  display: flex;
  flex-wrap: wrap;
  width: 400px;
  height: 200px;
  border: 1px solid black;
  align-items: stretch;
}

.flex-container> :nth-child(1) {
  background-color: darkorchid;
  /* height: 60px; */
}

.flex-container > :nth-child(2) {
  background-color: darkkhaki;
}

.flex-container > :nth-child(3) {
  background-color: dodgerblue;
}

.flex-container > :nth-child(4) {
  background-color: darkgoldenrod;
}

.flex-container > :nth-child(5) {
  background-color: darkcyan;
}
<div class="flex-container">
  <span>I am number 1</span>
  <div>I am number 2</div>
  <div>I am number 3</div>
  <div>I am number 4</div>
  <span>I am number 5</span>
</div>

In a container with height: 200px and align-items: stretch, flex items on both lines have heights of 100px.


When you set a height on a flex item you are consuming free space. Only the remaining space gets factored into align-content: stretch.

So in the question the first item is given height: 60px. That leaves 140px of free space remaining in the cross axis, right? Okay, let's go with that. That space is distributed equally among both lines.

.flex-container {
  display: flex;
  flex-wrap: wrap;
  width: 400px;
  height: 200px;
  border: 1px solid black;
  align-items: stretch;
}

.flex-container> :nth-child(1) {
  background-color: darkorchid;
  height: 60px;
}

.flex-container > :nth-child(2) {
  background-color: darkkhaki;
}

.flex-container > :nth-child(3) {
  background-color: dodgerblue;
}

.flex-container > :nth-child(4) {
  background-color: darkgoldenrod;
}

.flex-container > :nth-child(5) {
  background-color: darkcyan;
}
<div class="flex-container">
  <span>I am number 1</span>
  <div>I am number 2</div>
  <div>I am number 3</div>
  <div>I am number 4</div>
  <span>I am number 5</span>
</div>

At this point we should see items 2, 3 and 4 with heights of 130px, and item 5 with a height of 70px. (Item 1 doesn't participate because align-items: stretch no longer applies. It's been overridden with a height declaration (full explanation).)

But that's not what happens. Participating items on the first row have a height of 121px, and on the second row 79px.

enter image description here

enter image description here

Why? Because there was less free space than originally thought. The content itself (the text) has height and consumes space. Once you factor in the height of the text (whatever it may be, I don't know), those numbers add up.

In fact, the only reason flex lines were equal height in the first example (the one with no height defined on the first item) was that all text had the same font size. If you were to change the font size of, let's say, item #5, flex lines would again have unequal heights.

.flex-container {
  display: flex;
  flex-wrap: wrap;
  width: 400px;
  height: 200px;
  border: 1px solid black;
  align-items: stretch;
}

.flex-container> :nth-child(1) {
  background-color: darkorchid;
  /* height: 60px; */
}

.flex-container > :nth-child(2) {
  background-color: darkkhaki;
}

.flex-container > :nth-child(3) {
  background-color: dodgerblue;
}

.flex-container > :nth-child(4) {
  background-color: darkgoldenrod;
}

.flex-container > :nth-child(5) {
  background-color: darkcyan;
  font-size: 2em; /* demo */
}
<div class="flex-container">
  <span>I am number 1</span>
  <div>I am number 2</div>
  <div>I am number 3</div>
  <div>I am number 4</div>
  <span>I am number 5</span>
</div>

More details:

Michael Benjamin
  • 346,931
  • 104
  • 581
  • 701
  • So as I understand, `align-content: stretch` will (try to) have each row take up the same space (as it takes up the height of the container). By specifying height (60px) in one item this subtracts from the cross-size that align-content has to play with (giving it 140px which splits into 70px each row). The height of the first row (or flex-line?) will be 70px plus the additional height of its tallest grid-item - 60px, giving 130px. I don’t understand this bit about having to also add the (line-?) height of the text because surely the text is within the height of the content (60px)? – tonitone106 Jun 13 '20 at 00:44
  • Yes, but item #1 isn't participating (see paragraph 5 in my answer). The height of the text only applies to the other items. – Michael Benjamin Jun 13 '20 at 00:50
  • When we're 'factoring in the height of the text' into the equation 1. What constitutes height of the text? Line-height? 2. Would you be able to show me in an (my) example how the height of the text is factored even if it’s just hypothetical figures? – tonitone106 Jun 13 '20 at 19:45
  • It could be line height or font size or something else. I would guess the first option. In terms of the hypothetical, assume the content (line-) height is 15px. Then factor that number into the `align-content` calculation just like `height: 60px` was in my answer. – Michael Benjamin Jun 13 '20 at 19:50
  • 15px isn't taller than 60px so I'm struggling to understand how it'd make a dent in the 130px space that `align-content: stretch` has to play with and tries to split evenly. Would you mind doing it for me and then maybe I can deduce the rule? This is a tricky part for me and I'm unsure my concept of what's going on's correct. (Thanks for help btw). – tonitone106 Jun 13 '20 at 19:55
  • Consider posting a new question. You're now delving deeper into the flex algorithm. – Michael Benjamin Jun 13 '20 at 20:00
  • Okay :) https://stackoverflow.com/questions/62365120/flexbox-how-to-determine-the-height-of-flex-lines-when-align-content-stretch – tonitone106 Jun 13 '20 at 20:24
  • 1
    @tonitone106 your new asked question isn't different from this one and it's actually exactly the same. You should not ask new question if you need a little more details, you should edit this one so we can keep answering here and have all the details in one place. Now we have 2 same question dealing with the same thing having answers in different places (+ the question I initially used as duplicate). Also the answer you accepted there isn't accurate because it's not about the font-size but the line-height. Font-size play no role (add line-height:0 and see what happen) – Temani Afif Jun 15 '20 at 08:15
  • 1
    @tonitone106 here is the part you are missing to get the exact calculation: https://stackoverflow.com/a/61835863/8620333 there you will find how to identify the height of block elements when height is set to auto. – Temani Afif Jun 15 '20 at 08:28
-2

.flex-container {
        
        display: flex;
        flex-wrap: wrap;
        width: 400px;
        height: 200px;
        border: 1px solid black;
        align-items: stretch;
}

.flex-container > :nth-child(1) {
        background-color: darkorchid;
        height: 100%;   
}

.flex-container > :nth-child(2) {
        background-color: darkkhaki;
}

.flex-container > :nth-child(3) {
        background-color: dodgerblue;
}

.flex-container > :nth-child(4) {
        background-color: darkgoldenrod;
}

.flex-container > :nth-child(5) {
        background-color: darkcyan;
        height: 100%;
}
 <div class="flex-container">
      <span>I am number 1</span>
      <div>I am number 2</div>
      <div>I am number 3</div>
      <div>I am number 4</div>
      <span>I am number 5</span>
</div>
belhadj abdou
  • 178
  • 4
  • 16
-3

As you are setting flex-wrap: wrap. It might cause quite unexpected behavior of the flex-container when you add elements with various widths and heights in it. So, it gets harder to get the height of the first row as you add new items to flex-container.

In your code flex-container has a specific height of 200px and a width of 400px. That means, no matter how many elements the flex-container includes it will never overflow the given width and height. Every item in the flex-container will try to cover the available space.

Each row will have the height of it the element with the maximum height because of align-items: stretch. That's why setting the height of one item might not always effect to the height of the row.