I'm trying to fill the vertical space of a flex item inside a Flexbox.
.container { height: 200px; width: 500px; display: flex; flex-direction: row; } .flex-1 { width: 100px; background-color: blue; } .flex-2 { position: relative; flex: 1; background-color: red; } .flex-2-child { height: 100%; width: 100%; background-color: green; }
And here's the JSFiddle
flex-2-child
doesn't fill the required height except in the two cases where:
flex-2 has a height of 100% (which is weird because a flex item has a 100% by default + it is buggy in Chrome) flex-2-child has a position absolute which is also inconvenient
This doesn't work in Chrome or Firefox currently.
height:100%
but they are rendering with natural height instead. And the weird thing is if I change their height to auto
, then they render as height:100%
like I was trying to do. It is definitely not intuitive if that's how it should work.
Use align-items: stretch
Similar to David Storey's answer, my workaround is:
.flex-2 {
display: flex;
align-items: stretch;
}
Note that height: 100%
should be removed from the child component (see comments).
Alternatively to align-items
, you can use align-self
just on the .flex-2-child
item you want stretched.
I have answered a similar question here.
I know you have already said position: absolute;
is inconvenient, but it works. See below for further information on fixing the resize issue.
Also see this jsFiddle for a demo, although I have only added WebKit prefixes so open in Chrome.
You basically have two issues which I will deal with separately.
Getting the child of a flex-item to fill height 100%
Set position: relative; on the parent of the child.
Set position: absolute; on the child.
You can then set width/height as required (100% in my sample).
Fixing the resize scrolling "quirk" in Chrome
Put overflow-y: auto; on the scrollable div.
The scrollable div must have an explicit height specified. My sample already has height 100%, but if none is already applied you can specify height: 0;
See this answer for more information on the scrolling issue.
If I understand correctly, you want flex-2-child to fill the height and width of its parent, so that the red area is fully covered by the green?
If so, you just need to set flex-2 to use Flexbox:
.flex-2 {
display: flex;
}
Then tell flex-2-child to become flexible:
.flex-2-child {
flex: 1;
}
See http://jsfiddle.net/2ZDuE/10/
The reason is that flex-2-child is not a Flexbox item, but its parent is.
align-items: center
if you use align-self: stretch
on just the one child.
min-height: 100vh;
to .flex-2
element to make it works. Thanks for the help!
I suppose that Chrome's behavior is more consistent with the CSS specification (though it's less intuitive). According to Flexbox specification, the default stretch
value of align-self
property changes only the used value of the element's "cross size property" (height
, in this case). And, as I understand the CSS 2.1 specification, the percentage heights are calculated from the specified value of the parent's height
, not its used value. The specified value of the parent's height
isn't affected by any flex properties and is still auto
.
Setting an explicit height: 100%
makes it formally possible to calculate the percentage height of the child, just like setting height: 100%
to html
makes it possible to calculate the percentage height of body
in CSS 2.1.
height: 100%
is giving very odd results for me in Chrome. It seems that this causes the "specified height" to be set to the total height of the container, rather than the height of the element itself, so causes unwanted scrolling when other elements have sizes calculated relative to it.
I found the solution by myself. Suppose you have the CSS below:
.parent {
align-items: center;
display: flex;
justify-content: center;
}
.child {
height: 100%; <- didn't work
}
In this case, setting the height 100% will not work, so I set the margin-bottom
rule to auto
, like:
.child {
margin-bottom: auto;
}
And the child will be aligned to the topmost of the parent.
You can also use the align-self
rule anyway if you prefer:
.child {
align-self: flex-start;
}
This can also be solved with align-self: stretch;
on the element we want to be stretched.
Sometimes it is desirable to only stretch one item in a Flexbox setup.
.container { height: 200px; width: 500px; display: flex; flex-direction: row; } .flex-1 { width: 100px; background-color: blue; } .flex-2 { position: relative; flex: 1; align-self: stretch; background-color: red; } .flex-2-child { background-color: green; }
.container { height: 200px; width: 500px; display: -moz-box; display: -webkit-flexbox; display: -ms-flexbox; display: -webkit-flex; display: -moz-flex; display: flex; -webkit-flex-direction: row; -moz-flex-direction: row; -ms-flex-direction: row; flex-direction: row; } .flex-1 { flex:1 0 100px; background-color: blue; } .flex-2 { -moz-box-flex: 1; -webkit-flex: 1; -moz-flex: 1; -ms-flex: 1; flex: 1 0 100%; background-color: red; } .flex-2-child { flex: 1 0 100%; height: 100%; background-color: green; }
http://jsfiddle.net/2ZDuE/750/
An idea would be that display:flex;
with flex-direction: row;
is filling the container
div with .flex-1
and .flex-2
, but that does not mean that .flex-2
has a default height:100%;
, even if it is extended to full height.
And to have a child element (.flex-2-child
) with height:100%;
, you'll need to set the parent to height:100%;
or use display:flex;
with flex-direction: row;
on the .flex-2
div too.
From what I know, display:flex
will not extend all your child elements height to 100%.
A small demo, removed the height from .flex-2-child
and used display:flex;
on .flex-2
: http://jsfiddle.net/2ZDuE/3/
fun fact: height-100% works in the latest chrome; but not in safari;
so solution in tailwind would be
"flex items-stretch"
https://tailwindcss.com/docs/align-items
and be applied recursively to the child's child's child ...
.parent {
display: flex;
}
.child {
min-height: 100%;
}
Another approach I used (other option wouldn't fit my case because I needed a more generic solution and I really want to avoid using position: absolute
when possible):
Have a parent with display: flex Give your element display flex as well, align-self: stretch and margin-top: 0 + margin-bottom: 0
Minimal reproducible example:
.parrent { display:flex; // the width can be anything. width: 150px; } .full-height-just-with-bg-collor { width: 100%; display: flex; align-self: stretch; // this can be just 0 or you can set just the top and bottom values margin: 0 2px; background-color: green; }
.container { . . . . align-items: stretch; . . . . }
This is my solution using css+.
First of all, if the first child (flex-1) should be 100px, it shouldn't be flex.
In css+ in fact you can set flexible and/or static elements (columns or rows) and your example become as easy as this:
<div class="container">
<div class="EXTENDER">
<div class="COLS">
<div class="CELL _100px" style="background-color:blue">100px</div>
<div class="CELL _FLEX" style="background-color:red">flex</div>
</div>
</div>
</div>
Container CSS:
.container {
height: 200px;
width: 500px;
position: relative;
}
And obviously include css+ 0.2 core.
Here is the fiddle.
Success story sharing
stretch
: this should be the chosen answer.height: 100%