My goal is to create a two-column layout with flexbox wherein the first column has two rows and the second column has one, like this:
Setting flex-basis: 100%
on the third item gives the desired effect, but only when the container's flex-direction
is row
:
Changing flex-direction
to column
results in the following, unless the height
is set explicitly, which is infeasible in my project:
How can I get the first image without explicitly setting the height
of the container?
Here's a Plunker illustrating the problem.
body {
display: flex;
height: 100px;
width: 100px;
}
.container {
display: flex;
flex-direction: column; /* Setting this to `row` gives the expected effect,but rotated */
flex-grow: 1;
flex-wrap: wrap;
/* height: 100%; */ /* Setting this fixes the problem, but is infeasible for my project*/
}
.item {
flex-grow: 1;
}
.one {
background-color: red;
}
.two {
background-color: blue;
}
.three {
background-color: green;
flex-basis: 100%;
}
<div class="container">
<div class="item one"> </div>
<div class="item two"> </div>
<div class="item three"> </div>
</div>
display. This defines a flex container; inline or block depending on the given value. It enables a flex context for all its direct children. Note that CSS columns have no effect on a flex container.
flex-basis: auto looks up the main size of the element and defines the size. For example, on a horizontal flex container, auto will look for width and height if the container axis is vertical. If no size is specified, auto will fall back to content .
Changing flex-direction Setting flex-direction: row-reverse will keep the items displaying along the row, however the start and end lines are switched. If we change flex-direction to column the main axis switches and our items now display in a column. Set column-reverse and the start and end lines are again switched.
on Feb 5, 2019. Flex-basis overrules any specified CSS width value, so if you set flex-basis to 0, it doesn't fall back to the CSS "width" value. However, the only way it'll actually be 0px wide is if there's absolutely no content or padding inside it (which would be uncommon in real-world use).
Why it doesn't work:
Flex wrap only happens when the initial main size of the flex items overflows the flex container. In the case of flex-direction: row
, this is when they flex items are wider than the container. With flex-direction: column
, they must overflow the height of the container.
But in CSS, height behaves fundamentally differently than width. The height of a container in CSS is determined by the height of its children. Thus, without something constraining the container’s height, they flex items will never overflow; they just make their container taller. If they don’t overflow, they won’t wrap.
Possible solutions:
You have to constrain the height of the container. The obvious way (which you said is off the table), is setting an explicit height
or max-height
.
Ask yourself why you need to constrain the height. Is it to stay within the viewport? You could use viewport-relative units and set something like max-height: 100vh
. Is it to equal the height of another column outside this flex container? You might be able to constrain it with another flexbox. Make this flex container a flex item in an outer flexbox. Something else in that outer flexbox would have to establish its height, though.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With