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>
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.
Try to set flex: none
for blocks inside the container in the condition when you change the orientation ( @media
etc.)
I tested it in Chrome and Firefox.
As far as i understand, the following code give the result you want:
body {
display: flex;
height: 100px;
width: 100px;
}
.container {
display: flex;
flex-direction: column;
flex-wrap: wrap;
flex-grow:1;
}
.item {
flex-basis:50%;
}
.one {
background-color: red;
}
.two {
background-color: blue;
}
.three {
background-color: green;
flex-basis:100%;
}
Except from the flex-basis:50%;
this code is equal to the code you use in the plunker. For some reason the plunker does not support flex-basis
, see also:
I think you should build your layout using a Grid System in mind. On your first picture we can see 2 cols: first col is red and blue boxes, second col is the green box.
And then the structure should be like this:
<div class="flex-container">
<div class="col column">
<div class="content red"></div>
<div class="content blue"></div>
</div>
<div class="col">
<div class="content green"></div>
</div>
</div>
Using these styles:
.flex-container {
display:flex;
}
.col {
flex:1;
display:flex;
}
.column {
flex-direction:column;
}
.content {
flex:1;
}
Here is a quick code using your demo goal: https://jsfiddle.net/wyyLvymL/ Hope it helps! (if you need to understand how does it works, ping me)
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.