848

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;
}
<div class="container">
  <div class="flex-1"></div>
  <div class="flex-2">
    <div class="flex-2-child"></div>
  </div>
</div>

And here's the JSFiddle

flex-2-child doesn't fill the required height except in the two cases where:

  1. flex-2 has a height of 100% (which is weird because a flex item has a 100% by default + it is buggy in Chrome)
  2. flex-2-child has a position absolute which is also inconvenient

This doesn't work in Chrome or Firefox currently.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Raz
  • 8,981
  • 4
  • 19
  • 18
  • what is the problem with using height:100%; for .flex-2 ? – rmagnum2002 Mar 13 '13 at 09:31
  • 1
    It defies the purpose of the flex item which is to fill the content by itself and it's giving me the weirdest bug in chrome where the height goes back to zero whenever I resize the window – Raz Mar 13 '13 at 09:46
  • Firefox versions that still follow the spec from 2009 (display: box) behave very differently from versions that follow the modern spec. If FF is misbehaving, I'd recommend dropping support for it. – cimmanon Mar 13 '13 at 12:30
  • 4
    Actually, the latest version of Firefox is the only one working properly – Raz Mar 13 '13 at 13:36
  • 2
    Currently, there are significant differences in behavior among browsers when it comes to rendering percentage heights in flexbox: http://stackoverflow.com/a/35537510/3597276 – Michael Benjamin Mar 17 '16 at 12:07
  • 4
    Yep, Chrome has some issues, especially with nested flexboxes. For example I've got a nested flex box with children that have `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. – trusktr Sep 25 '18 at 18:05
  • 1
    It doesn't work at all... – Federico Schiocchet Jun 09 '21 at 10:57
  • Looks like in 2022 height 100% works on flex children now. – user31782 Oct 07 '22 at 06:02

14 Answers14

823

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.

B T
  • 57,525
  • 34
  • 189
  • 207
  • 25
    `stretch`: this should be the chosen answer. – Dave Everitt Jul 16 '19 at 12:02
  • 6
    How would you align the text inside a div that has been stretched to vertically align in the middle tho? – astigmatik Oct 22 '20 at 09:43
  • 21
    Yes you should add removing `height: 100%` – Elpis Jan 22 '21 at 10:23
  • 1
    This saved my day. I got a flex row which has some items. I want these items to take height from its parent. I demonstrated my issue here https://codepen.io/dshung1997/pen/LYxvXNy – hungdoansy Apr 28 '21 at 12:24
  • Will this work if we have no control over "container" in this example? In other words, I can't make "container" use flex layout – void.pointer Jun 05 '21 at 15:41
  • @void.pointer Probably not. align-items only works in flex boxes as far as I know. – B T Jun 10 '21 at 22:55
  • @astigmatik set "align-self: stretch" only for a child item you want to take 100% height and for parent "align-item: center" – MAZ Jan 18 '22 at 07:49
  • This is not a workaround, this is exactly how it should be done, the parent container should be flex and set to stretch its childrens. Thats the whole philosophy of flexbox, it aligns and sizes its children. – Mladen Oršolić Dec 13 '22 at 16:42
  • It just seems silly that height: 100% doesn't work. I regard that as a failing of css - whether its a bug or a design flaw. – B T Dec 13 '22 at 21:00
  • for me, align-self:stretch worked but align-items:stretch didn't – Akin Hwan Apr 20 '23 at 22:22
  • 1
    "Note that height: 100% should be removed from the child component" this line was time savior for me, thanks – Tarun Jain Aug 08 '23 at 05:35
289

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.

  1. 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).
  1. 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.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Brett Postin
  • 11,215
  • 10
  • 60
  • 95
  • 10
    Point 1) works perfectly in Chrome, Firefox doesn't need the position absolute. – yuri Nov 06 '13 at 20:08
  • 3
    This is not an acceptable solution. In all my years of programming I've learned you only use position absolute very carefully for some things, as elements may not render correctly in other browsers. Plus the answer isn't addressed, as he mentioned Flexbox right there in the Title, so this answer is wrong. – Manny Alvarado Apr 20 '22 at 02:51
  • @MannyAlvarado this question and answer were posted at a time when flexbox was still in working draft and browser implementations all over the place. Historical context is important here. Thankfully we're in a better place now which is why better answers have surpassed this one. – Brett Postin Apr 26 '22 at 13:40
  • 1
    @MannyAlvarado I've been doing this for a while too, but I have not experienced weird browser quirks with `position: absolute` ever (but I have seen them with `flex`...). Paired with `position: relative`, it can be "fluid" a bit like flex, can be useful in some situations. – surj Jun 27 '23 at 17:55
273

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.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
David Storey
  • 29,166
  • 6
  • 50
  • 60
  • How can I do the same, just with a height of 100% and every child is 50/50 ? – Ricky Levi Oct 16 '14 at 20:46
  • 9
    Be aware that if you use "align-items: center" you won't be able to use this fix since your items will now become equal-height. – Neil Monroe Jun 03 '15 at 16:56
  • 18
    @NeilMonroe You can still use `align-items: center` if you use `align-self: stretch` on just the one child. – B T Sep 08 '15 at 20:04
  • 2
    Hi @David, i tried your solution, it works fine for the flex-direction: row layout, it seems not working with flex-direction: column layout, or i have any places wrong in the code. Could you help to check why in this fiddle http://jsfiddle.net/78o54Lmv/, the inner box won't occupy the full height of its parent? – huan feng Dec 07 '18 at 06:50
  • I have to add `min-height: 100vh;` to `.flex-2` element to make it works. Thanks for the help! – Tenaciousd93 May 15 '19 at 07:05
  • @NeilMonroe Thanks! I always forget this until I come across your comment. – Matt. Jul 07 '19 at 22:16
32

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;
}
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
user3896501
  • 2,987
  • 1
  • 22
  • 25
  • A nice hack, but the problem is: if child is a sidebar and it have a background color, the margin space is still white. – Boris Burkov Jul 07 '19 at 12:18
  • What's great about this solution is that the height of the parent can be dynamic! The previous solutions require the parent to have a set height. Thanks for this. – Bribbons Mar 17 '20 at 05:41
  • problem is i need a border to go all tlhe way down to the bottom – chovy Feb 24 '23 at 21:58
27

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.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Ilya Streltsyn
  • 13,076
  • 2
  • 37
  • 57
  • 2
    Exactly! To put this into practice, just add `height:100%` to `.flex-2`. Here's the [jsfiddle](http://jsfiddle.net/2ZDuE/114/). – CourtDemone Jan 06 '14 at 20:43
  • 7
    Chrome's behavior is more consistent with *Chrome Team's interpretation of* the CSS spec. While it could be interpreted that way, there are far better ways of interpreting it, any of which wouldn't have trapped us into this bazaar, annoying, and irksome behavior. They should have thought it through more. – WraithKenny May 03 '16 at 18:05
  • 1
    @RickDoesburg, this was more than a year ago, but I believe that I had to resort to fixed height elements. I wish these browsers would get their act together. I'm really starting to dislike the mobile space. – Jordan Oct 10 '16 at 12:03
  • 2
    Setting a child of a vertical flexbox container to `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. – Jules Jul 23 '17 at 03:24
10

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;
}
<div class="container">
  <div class="flex-1"></div>
  <div class="flex-2">
    <div class="flex-2-child"></div>
  </div>
</div>
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
GiorgosK
  • 7,647
  • 2
  • 29
  • 26
8

Another approach (other option wouldn't fit my case because I needed a more generic solution, I really want to avoid using position: absolute when possible, and just display: flex with align-items: stretch wouldn't work in my case because of other syling):

  1. Have a parent with display: flex
  2. Give your element display flex as well, align-self: stretch and margin-top: 0 + margin-bottom: 0

Minimal reproducible example:

.parrent {
  display: flex;
}
.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;
}
<div>
  <div class="parrent">
    <div class="full-height-just-with-bg-collor"></div> 
    textForHeight
  </div>
</div>
Berci
  • 2,876
  • 1
  • 18
  • 28
6
.parent {
    display: flex;
}

.child {
    min-height: 100%;
}
Zach White
  • 161
  • 1
  • 7
5

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/

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
rmagnum2002
  • 11,341
  • 8
  • 49
  • 86
5

.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;
}
<div class="container">
    <div class="flex-1"></div>
    <div class="flex-2">
        <div class="flex-2-child"></div>
    </div>
</div>

http://jsfiddle.net/2ZDuE/750/

corn on the cob
  • 2,093
  • 3
  • 18
  • 29
Carol McKay
  • 2,438
  • 1
  • 15
  • 15
4

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 ...

Archy Will He 何魏奇
  • 9,589
  • 4
  • 34
  • 50
0
.parent {
    display: flex;
    align-items: center;
}

.child {
    align-self: stretch;
}

Based on previous answers got this solution to work for full height flex elements.

TiagoLr
  • 2,782
  • 22
  • 16
-8

.container { . . . . align-items: stretch; . . . . }

HRK
  • 17
  • 1
  • 8
    Welcome to stackoverflow. You need to fully explain your answer, and what it contributes that is different from the existing answers. See https://stackoverflow.com/help/how-to-answer – Simon.S.A. Mar 13 '19 at 03:29
  • 2
    Your answer seems to be the same as B T's (written over three years early) but expressed far more poorly. – Quentin Nov 13 '19 at 08:36
-14

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.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Marco Allori
  • 3,198
  • 33
  • 25