Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Image behavior within flexbox (rows embedded in columns)

Tags:

html

css

flexbox

The below fiddle has three blocks.

block 1 contains three columns. The middle column has two rows within it, each set to flex:1.

block 2 contains three columns. The middle column has two rows within it, each set to flex:1. The second row contains an image of a dog. The image will not shrink to the height of the row within which it is contained.

block 3 contains only the middle column which has two rows within it, each set to flex:1. The second row contains an image of a dog. The image DOES shrink to the height of the row within which it is contained.

The question is why does the image in the second row of the middle column of block 2 not shrink to the height of the row within which it is contained? What CSS rules can I add to make this happen?

.block{
    height:100px;
}

.wrapper{
    border:5px solid purple;
    display:flex;
    flex-direction:row;
}

.column{
    flex:1;
    border:3px solid yellow;
}

.middle{
    display:flex;
    flex-direction:column;
}

.first{
    background:red;
}

.second{
    background:orange;
}

.third{
    background:purple;
}

.row{
    flex:1;
    border:1px solid black;
    display:flex;
    align-items:stretch;
}

img{
    flex:1;
}
<div class="wrapper block">
<div class="left column"></div>
<div class="middle column">
  <div class="row first"></div>
  <div class="row second"></div>
      	
</div>
<div class="right column"></div>
</div>

<div class="wrapper block">
<div class="left column"></div>
<div class="middle column">
  <div class="row first"></div>
  <div class="row second">
            	<img src="https://upload.wikimedia.org/wikipedia/commons/8/89/Dog.svg" />
  </div>

</div>
<div class="right column"></div>
</div>

<div class="middle block">
  <div class="row first"></div>
  <div class="row second">
            	<img src="https://upload.wikimedia.org/wikipedia/commons/8/89/Dog.svg" />
  </div>

</div>
like image 248
mags Avatar asked Nov 28 '15 19:11

mags


People also ask

Does CSS columns have effect on a Flex container?

the column-* properties in the Multi-column Layout module [CSS3COL] have no effect on a flex container. float and clear have no effect on a flex item, and do not take it out-of-flow. However, the float property can still affect box generation by influencing the display property's computed value.

Does flexbox allows you to arrange your HTML elements into rows and columns?

Flexbox is a one-dimensional layout method for arranging items in rows or columns. Items flex (expand) to fill additional space or shrink to fit into smaller spaces.

How do you show 3 items per row in flexbox?

For 3 items per row, add on the flex items: flex-basis: 33.333333% You can also use the flex 's shorthand like the following: flex: 0 0 33.333333% => which also means flex-basis: 33.333333% .


1 Answers

Solution

replace:

.row {
    flex: 1;
    border: 1px solid black;
    display: flex;
    align-items: stretch;
}

with:

.row {
    flex: 1 1 0px;             /* adjustment on this line */
    border: 1px solid black;   /* no change */
    display: flex;             /* no change */
    align-items: stretch;      /* no change */
}

DEMO 1


Explanation

You wrote:

The question is why does the image in the second row of the middle column of block 2 not shrink to the height of the row within which it is contained?

It appears that you tested your code in Chrome only, because the premise of your question is false when it comes to Firefox and IE11.

In those browsers the image of the dog in block two is contained nicely within the flex item. The image is a bit stretched in IE, but it's contained nonetheless.

Your question appears to be Chrome-specific. (I didn't test in Safari, but that's a WebKit browser like Chrome, so the solution may be similar.)

Here's a demo of your original code in case you want to test across browsers:

DEMO 2

The solution to this problem is interesting because a small and seemingly insignificant difference in a property value makes a big difference in Chrome rendering.


Your image is a child element (more specifically: a flex item) of div.row, a flex container with row-direction.

div.row is also a flex item of a larger container (in column-direction) and has flex: 1 applied. The problem in Chrome is rooted in that flex: 1 declaration.

What does flex: 1 mean?

The flex property is shorthand for flex-grow, flex-shrink and flex-basis.

flex: 1 is the equivalent of flex-grow: 1, flex-shrink: 1 and flex-basis: 0%.

Notice that percentage sign (%) after the 0. It's defined in the flexbox spec's Common Values of flex and it actually makes a difference.

Try this in Chrome:

Replace flex: 1 in div.row with its equivalent flex: 1 1 0%. You'll notice that nothing changes when rendered.

Now remove the percentage sign and run it again. The image snaps into place.

Making it flex: 1 1 0px, like stated in CSS-Tricks, also works.

DEMO 3

So, using px or no unit – and not a percentage – on the 0 fixes the problem in Chrome... and it doesn't break anything in Firefox.

In IE11, however, px works but unitless does not. In fact, unitless obliterates the layout.

But IE11 is another story...

On the browser support data website caniuse.com, IE11 was showing full support for flexbox until recently, when it was downgraded to partial support due to the "large amount of bugs present". In testing the above demos, IE11 regularly rendered the same code differently on refresh. See the Known Issues tab on caniuse.com for a list of problems.


Note that flexbox is supported by all major browsers, except IE 8 & 9. Some recent browser versions, such as Safari 8 and IE10, require vendor prefixes. IE11, as mentioned above, offers partial support due to several known bugs. For a quick way to add all the prefixes you need, use Autoprefixer. More browser compatibility details in this answer.

like image 101
Michael Benjamin Avatar answered Sep 19 '22 15:09

Michael Benjamin