Error404 Error404 - 6 months ago 18
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

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: