Error404 Error404 - 1 year ago 53
HTML Question

Flex item won't consume available space in container when second flex item introduced

I have a container named

#center
in which I want to display
canvas
and a
button
inside it. I want the
canvas
object to take all the available space (respecting the button inside the container).

This is my code:



html, body {
width: 100%;
height: 100%;
}
#container {
display: flex;
height: 100%;
background-color: blue;
}
.block {
flex: 1;
}
#left {
background-color: green;
}
#center {
display: flex;
flex: 1;
flex-wrap: wrap;
align-content: flex-start;
}
#right {
background-color: orange;
}
.flexContainer {
flex: 1;
min-width: 100px;
max-width: 50%;
height: 150px;
background-color: red;
padding: 10px;
}
.flexDiv {
width: 100%;
height: 100%;
background-color: yellow;
}
#canvasObject {
display: block;
margin: 0 auto;
border: 1px solid;
background-color: yellow;
}

<div id="container">
<div id="left" class="block">Left</div>
<div id="center" class="block">
<canvas id="canvasObject">Your browser does not support Canvas.</canvas>
<button type="button">Click!</button>
</div>
<div id="right" class="block">Right</div>
</div>





If I do not have any
button
in my code,
canvas
occupy the full
div
but when I display the
button
,
canvas
does not seem to resize the desired
height
.



How can I make that the
canvas
object will resize until the available
height
(also
width
but it is already doing it)?

Thanks in advance!

Answer Source

The problem is that you have align-content: flex-start on a row-direction flex container:

#center {
    display: flex;
    flex: 1;
    flex-wrap: wrap;  
    align-content: flex-start;    /* <-- source of the problem */
}

The align-content property controls the spacing between flex items in the cross-axis when there are multiple lines in the container.

When the button element is excluded, there is only one line in the flex container. In such a case, align-content has no effect (align-items would work).

But when you add the button, there are now two lines, and align-content takes over (align-items does not work).

Since align-content is set to flex-start in your code, both lines are packed to the top of the container. (For other options, try flex-end, center, space-between, space-around and stretch).

An efficient solution would be to use flex-direction: column and apply flex: 1 to the canvas.

#center {
    display: flex;
    flex-direction: column;        /* new; stack flex items vertically */
    flex: 1;
    flex-wrap: wrap;  
    /* align-content: flex-start;  <-- remove; not necessary */
}

#canvasObject {
    flex: 1;                        /* new; consume all available free space */
    /* display: block;              <-- remove; not necessary */
    /* margin: 0 auto;              <-- remove; not necessary */
    border: 1px solid;
    background-color: yellow;
}

Revised Fiddle


W3C References: