730

I have a site with the following structure:

<div id="header"></div>

<div id="main">
  <div id="navigation"></div>
  <div id="content"></div>
</div>

<div id="footer"></div>

The navigation is on the left and the content div is on the right. The information for the content div is pulled in through PHP, so it's different every time.

How can I scale the navigation vertically so that its height is the same as the content div's height, no matter which page is loaded?

TylerH
  • 20,799
  • 66
  • 75
  • 101
  • 2
    Use display table on parent and display table-cell on child. This will make child as long as the parent is. See http://stackoverflow.com/q/22712489/3429430 – user31782 Dec 07 '16 at 17:07
  • 15
    You can just set `display: flex; align-items: stretch;` for the div#main. And __don't__ use `height: 100%` for div#content – Ihor Jun 19 '19 at 11:44

31 Answers31

654

For the parent:

display: flex;

You should add some prefixes, http://css-tricks.com/using-flexbox/.

As @Adam Garner noted, align-items: stretch; is not needed. Its usage is also for parent, not children. If you want to define children stretching, you use align-self.

.parent {
  background: red;
  padding: 10px;
  display:flex;
}

.other-child {
  width: 100px;
  background: yellow;
  height: 150px;
  padding: .5rem;
}

.child {  
  width: 100px;
  background: blue;
}
<div class="parent">
  <div class="other-child">
    Only used for stretching the parent
  </div>
  <div class="child"></div>
</div>
Jonathan Hall
  • 75,165
  • 16
  • 143
  • 189
Aiphee
  • 8,904
  • 3
  • 18
  • 16
  • 5
    IE11 does not play nicely with flexbox and heights. click on "known issues" here: http://caniuse.com/#feat=flexbox – adamdport Jul 22 '16 at 18:24
  • @SuperUberDuper Well you can use it in bootstrap as this: https://jsfiddle.net/prdwaynk/ But if i were you, i would use foundation which is production ready with flexbox: http://foundation.zurb.com/sites/docs/xy-grid.html BS4 will also have Flexbox, but it is still in alpha, and i think foundation is better anyway. – Aiphee Sep 10 '17 at 06:49
  • Any info on this same problem if the child is larger than the parent and the desired result is overflow-y: scroll for the child? Again, not setting a height for the parent. The parent is getting it's height from other flex columns in the section. – Michael Oct 30 '17 at 14:31
  • 10
    If you're using `align-items: center` then the item you need to stretch needs `align-self: normal` – Dominic Aug 22 '18 at 08:50
  • 19
    This is not a right answer, cuz this needs to set parent height. Question said 'without specifying parent's height?'. – Lying_cat Mar 13 '19 at 07:28
  • 9
    @Aiphee downvoting because it appears you didn't see the part about **not having to set the parents height** right there in the original question text, yet your "solution" does exactly that. – tylerism May 07 '19 at 15:05
  • @Aiphee downvoting because it appears you didn't see the part about not having to set the parents height right there in the original question text, yet your "solution" does exactly that – user3529850 Jun 19 '19 at 07:52
  • @tylerism Well it still works when parent is stretched with inner content, edited. – Aiphee Jun 19 '19 at 08:04
  • this doesn't work when one of children, let's say other-child here (without setting height on it), has some text inside and the overal height of parent is coming from this text (`.child` doesn't take full height of parent in this case) – Erfan Azary Jan 31 '23 at 21:55
202

NOTE: This answer is applicable to legacy browsers without support for the Flexbox standard. For a modern approach, see: https://stackoverflow.com/a/23300532/1155721


I suggest you take a look at Equal Height Columns with Cross-Browser CSS and No Hacks.

Basically, doing this with CSS in a browser compatible way is not trivial (but trivial with tables) so find yourself an appropriate pre-packaged solution.

Also, the answer varies on whether you want 100% height or equal height. Usually it's equal height. If it's 100% height the answer is slightly different.

csvan
  • 8,782
  • 12
  • 48
  • 91
cletus
  • 616,129
  • 168
  • 910
  • 942
  • 8
    This looks like a nice solution until you draw a border `border:1px solid blue` e.g. on `container2` : the blue border is on the first two columns, not on the second column only as you would have expected. – Julien Kronegg Mar 07 '13 at 12:17
  • @bfritz, a better solution would be to use `display:table` – Siler Dec 17 '14 at 22:20
110

This is a frustrating issue that's dealt with designers all the time. The trick is that you need to set the height to 100% on BODY and HTML in your CSS.

html,body {
    height:100%;
}

This seemingly pointless code is to define to the browser what 100% means. Frustrating, yes, but is the simplest way.

Travis
  • 1,872
  • 1
  • 16
  • 12
  • 11
    Except it does not always work, for example if you have a relative positioned element inside an absolute positioned one, it no longer forces hasLayout. – tim May 15 '13 at 00:11
  • 1
    Also, if you want to get rid of the scrollbar on the right-hand side of the window (appears in Firefox v28), give the window some breathing room: `html { height: 100%; } body { height: 98%; }`. – Chris Middleton Apr 24 '14 at 17:39
  • 80
    This only works if all the parents have height 100%, it's not enough to set only the html and the body, all parents must have a height defined. – RaduM May 15 '14 at 18:38
  • I agree with you, but this seems to be answering a different question. Was the OP talking about the whole page? The way it reads now, it looks like it's just about being 100% the height of the parent element, which probably isn't the page or the viewport. – Michael Scheper May 27 '21 at 17:20
  • Thanks, I have used the same code for other projects without knowing what really it does. If you apply height: 100% to just body it will not work that is a bit frustrating for me. – Akash Kumar Seth Oct 12 '21 at 09:51
  • 1
    Doesn't work for ordinary divs – Lying_cat Oct 14 '21 at 06:34
98

I find that setting the two columns to display: table-cell; instead of float: left; works well.

John
  • 1
  • 13
  • 98
  • 177
Paul Harvey
  • 1,013
  • 1
  • 7
  • 2
  • 11
    MS themselves don't support it anymore, if that helps anyone convince their clients... – Heraldmonkey May 04 '14 at 11:51
  • 4
    This should be the accepted answer. Times have changed, this answer works in [all browsers](http://caniuse.com/#feat=css-table)(with on small quirk in Safari 5.1.17). Two lines of CSS and you instantly have the effect you're looking for with no draw back I can think of. – callmetwan May 29 '14 at 00:26
  • 7
    Hoist this answer. Put your backs into it lads! –  Aug 29 '14 at 04:44
  • This is the best answer. Yes we can make a table to do this, but its not tabular data, instead we treat the divs as if they were table cells... Brilliant! – Derokorian Jan 04 '15 at 18:33
  • This actually put me in the right direction for a different scenario. In case someone is struggling to work with square divs that are also flex containers in Firefox or Edge, just remember to set the :before element to display: table. Don't ask me why but it fixes it. – CGodo Jul 09 '16 at 22:38
  • While clever, solutions using i.e. `display: table-cell` to fix layout issues like the question have been rendered irrelevant by flexbox. – csvan Jul 17 '17 at 13:31
64

If you don't mind the navigation div being clipped in the event of an unexpectedly-short content div, there's at least one easy way:

#main {
position: relative;
}

#main #navigation {
position: absolute;
top: 0;
left: 0;
bottom: 0;
width: 10em; /* or whatever */
}

#main #content {
margin: 0;
margin-left: 10em; /* or whatever width you set for #navigation */
}

Elsewise there's the faux-columns technique.

David Thomas
  • 249,100
  • 51
  • 377
  • 410
  • 2
    Thanks a ton, you saved my day. Didn't knew one could define both top and bottom and it would work this way. – rubish Mar 14 '13 at 02:37
  • This will make the content of the container stop resizing it. – DreamWave Aug 05 '13 at 07:58
  • 1
    +1 because it specifically addresses the OP's question _"How to Force Child Div to 100% of Parent's Div Without Specifying Parent's Height?"_ My problem didn't require columns (which are mentioned in the question detail but not in the main headline) but rather one div behind another. This answer works in both applications. – Luke Apr 03 '17 at 10:11
34
#main {
    overflow: hidden;
}
#navigation, #content {
    margin-bottom: -1000px;
    padding-bottom: 1000px;
}
Roman Kuntyi
  • 357
  • 3
  • 2
  • I must say I was looking for this kind of solution. Dead simple and so obvious that nobody figured it out. Congrats @Roman! – Greg0ry Aug 23 '15 at 23:29
  • Thanks a lot! I also consider this a the goto solution for many of my similar CSS problems, where elements confined to an area using overflow and percentage width/height, are often pushing the outside layout around - all apparently due to the bottom margin. – Kenneth Ellested Sep 15 '20 at 12:42
15
#main {
   display: table;
} 
#navigation, #content {
   display: table-cell;
}

Look at this example.

Aurelio
  • 24,702
  • 9
  • 60
  • 63
Sergiu
  • 1,181
  • 8
  • 9
15

using jQuery:

$(function() {
    function unifyHeights() {
        var maxHeight = 0;
        $('#container').children('#navigation, #content').each(function() {
            var height = $(this).outerHeight();
            // alert(height);
            if ( height > maxHeight ) {
                maxHeight = height;
            }
        });
        $('#navigation, #content').css('height', maxHeight);
    }
    unifyHeights();
});
flavius
  • 215
  • 2
  • 2
  • 25
    `Math.max()` would be your friend here. – alex May 28 '12 at 06:34
  • 1
    Couldn't get the CSS to work in all cases for me an really just needed a quick fix. It may not be the most _standard_ approach, but this did the job just fine. Thanks! :-] –  Dec 20 '12 at 20:47
  • 1
    When using JQuery's `css` function, you cannot differentiate between screen and print media, as you usually do when using pure CSS solutions. Thus, you may have printing issues. – Julien Kronegg Mar 19 '13 at 07:34
14

height : <percent> will only work, if you have all parent nodes with specified percent height with a fixed height in pixels, ems, etc. on top level. That way, the height will cascade down to your element.

You can specify 100% to html and body elements as @Travis stated earlier to have the page height cascade down to your nodes.

Lajos Mészáros
  • 3,756
  • 2
  • 20
  • 26
14

Try making the bottom margin 100%.

margin-bottom: 100%;
Tony C
  • 157
  • 1
  • 2
  • 6
    or padding-bottom: 100%; it's not precise but it works well for some situations. – Jason Sep 26 '14 at 22:29
  • padding-bottom does the trick in my case. This solution is very similar to what @Roman Kuntyi posted. – Greg0ry Aug 23 '15 at 23:31
13

After long searching and try, nothing solved my problem except

style = "height:100%;"

on the children div

and for parent apply this

.parent {
    display: flex;
    flex-direction: column;
}

also, I am using bootstrap and this did not corrupt the responsive for me.

Hakan Fıstık
  • 16,800
  • 14
  • 110
  • 131
12

Add display: grid to the parent

Dziamid
  • 11,225
  • 12
  • 69
  • 104
9

For 2021 Readers:

Try this:

.parent {
  position: relative;

  display: flex;                 // And you will probably need this too.
  flex-direction: row;           // or column.
}

.child {
  position: absolute;
  top: 0;
  bottom: 0;

  align-self: center;            // And you will probably need this too.
}

Here is what I'm working on:

NeoZoom.lua
  • 2,269
  • 4
  • 30
  • 64
5

Based on the method described in this article I have created .Less dynamic solution:

Html:

<div id="container3">
    <div id="container2">
        <div id="container1">
            <div id="col1">Column 1</div>
            <div id="col2">Column 2</div>
            <div id="col3">Column 3</div>
        </div>
    </div>
</div>

Less:

/* Changes these variables to adjust your columns */
@col1Width: 60%;
@col2Width: 1%;
@padding: 0%;

/* Misc variable. Do not change */
@col3Width: 100% - @col1Width - @col2Width;

#container3 {
    float: left;
    width: 100%;
    overflow: hidden;
    background-color: red;
    position: relative;

    #container2 {
        float: left;
        width: 100%;
        position: relative;
        background-color: yellow;
        right: @col3Width;

        #container1 {
            float: left;
            width: 100%;
            position: relative;
            right: @col2Width;
            background-color: green;

            #col1 {
                float: left;
                width: @col1Width - @padding * 2;
                position: relative;
                left: 100% - @col1Width + @padding;
                overflow: hidden;
            }

            .col2 {
                float: left;
                width: @col2Width - @padding * 2;
                position: relative;
                left: 100% - @col1Width + @padding + @padding * 2;
                overflow: hidden;
            }

            #col3 {
                float: left;
                width: @col3Width - @padding * 2;
                position: relative;
                left: 100% - @col1Width + @padding + @padding * 4;
                overflow: hidden;
            }
        }
    }
}
Dmitry Efimenko
  • 10,973
  • 7
  • 62
  • 79
3

I know it's been a looong time since the question was made, but I found an easy solution and thought someone could use it (sorry about the poor english). Here it goes:

CSS

.main, .sidebar {
    float: none;
    padding: 20px;
    vertical-align: top;
}
.container {
    display: table;
}
.main {
    width: 400px;
    background-color: LightSlateGrey;
    display: table-cell;
}
.sidebar {
    width: 200px;
    display: table-cell;
    background-color: Tomato;
}

HTML

<div class="container clearfix">
    <div class="sidebar">
        simple text here
    </div>
    <div class="main">
        Lorem ipsum dolor sit amet, consectetur adipiscing elit. Etiam congue, tortor in mattis mattis, arcu erat pharetra orci, at vestibulum lorem ante a felis. Integer sit amet est ac elit vulputate lobortis. Vestibulum in ipsum nulla. Aenean erat elit, lacinia sit amet adipiscing quis, aliquet at erat. Vivamus massa sem, cursus vel semper non, dictum vitae mi. Donec sed bibendum ante.
    </div>
</div>

Simple example. Note that you can turn into responsiveness.

Paula Fleck
  • 835
  • 11
  • 21
  • Oh, I forgot: if you want to align the .sidebar content in the middle, just change "vertical-align: top" to "vertical-align: middle". – Paula Fleck Oct 29 '14 at 12:09
2

My solution:

$(window).resize(function() {
   $('#div_to_occupy_the_rest').height(
        $(window).height() - $('#div_to_occupy_the_rest').offset().top
    );
});
Sunil Garg
  • 14,608
  • 25
  • 132
  • 189
Rafael Ruiz Muñoz
  • 5,333
  • 6
  • 46
  • 92
2

You use CSS Flexbox

.flex-container {
  display: flex;
  background-color: DodgerBlue;
}

.flex-container > div {
  background-color: #f1f1f1;
  margin: 10px;
  padding: 20px;
  font-size: 30px;
}
<!DOCTYPE html>
<html>
<head>
</head>
<body>

<div class="flex-container">
  <div>1</div>
  <div>2</div>
  <div>3</div>  
</div>

<p>A Flexible Layout must have a parent element with the <em>display</em> property set to <em>flex</em>.</p>

<p>Direct child elements(s) of the flexible container automatically becomes flexible items.</p>

</body>
</html>
Ini
  • 548
  • 7
  • 19
2

I might be a bit late to this but I found a work around that might be a bit of a hack. Firstly to give the parent a flex and a height of 100vh

Something like this:

.parent {
   display: flex;
   justify-content: center;
   align-items: center;
   height: 100vh;/* Can be less depends on the container, basically this forces the element to expand */
}
The Whiz of Oz
  • 6,763
  • 9
  • 48
  • 85
  • If the parent is your viewport, it would work. But usually in a more advanced layout, you will find several containers nested and if you set nested containers to have 100vh, you will eventually get problems with margins and scrollbars showing up. – A A Aug 09 '23 at 01:37
2

You can put display: flex to div#main, align-self: stretch to div#navigation.

<div id="header"></div>

<div id="main">
  <div id="navigation"></div>
  <div id="content"></div>
</div>

<div id="footer"></div>

// CSS file
#main {
  display: flex;
}

#navigation {
  align-self: stretch;
}    
ClusterH
  • 761
  • 3
  • 16
1

[Referring to Dmity's Less code in another answer] I'm guessing that this is some kind of "pseudo-code"?

From what I understand try using the faux-columns technique that should do the trick.

http://www.alistapart.com/articles/fauxcolumns/

Hope this helps :)

Jonathan Julian
  • 12,163
  • 2
  • 42
  • 48
jluna
  • 299
  • 1
  • 3
  • 9
  • 4
    Depending on sorting order of answers, it is hard to tell what "this" refers to... I am guessing it is about Dmitry's code. Thus, this remark belongs to a comment below his answer! And, for your information, it is not pseudo-code, it is code in the Less language, a way of defining CSS in a procedural way. – PhiLho Apr 29 '13 at 12:30
1

There is a bit of a contradiction in the question's title and the content. The title speaks of a parent div, but the question makes it sound like you want two sibling divs (navigation and content) to be the same height.

Do you (a) want both navigation and content to be 100% the height of main, or (b) want navigation and content to be be same height?

I'll assume (b)...if that is so, I don't think you will be able to do it given your current page structure (at least, not with pure CSS and no scripting). You would probably need to do something like:

<main div>
    <content div>
         <navigation div></div>
    </div>
</div>

and set the content div to have a left margin of whatever the width of the navigation pane is. That way, the content's content is to the right of the navigation and you can set the navigation div to be 100% of the content's height.

EDIT: I'm doing this completely in my head, but you would probably also need to set the navigation div's left margin to a negative value or set it's absolute left to 0 to shove it back to the far left. Problem is, there are many ways to pull this off but not all of them are going to be compatible with all browsers.

Paul Abbott
  • 7,065
  • 3
  • 27
  • 45
1

This answer is not ideal any more since CSS flexbox and grid where implemented to CSS. However it is still a working solution

On a smaller screen you would probably want to keep the height auto as the col1, col2 and col3 are stacked on one another.

However after a media query breakpoint you would like cols to appear next to each other with an equal height for all columns.

1125 px is only an example of window width breakpoint after which you would want to make all columns set to the same height.

<div class="wraper">
    <div class="col1">Lorem ipsum dolor sit amet.</div>
    <div class="col2">Lorem ipsum dolor sit amet, consectetur adipisicing elit. Eos laudantium, possimus sed, debitis amet in, explicabo dolor similique eligendi officia numquam eaque quae illo magnam distinctio odio, esse vero aspernatur.</div>
    <div class="col3">Lorem ipsum dolor sit amet, consectetur adipisicing elit. Dolorem, odio qui praesentium.</div>
</div>

You could, of course, set more breakpoints if you need to.

<script>
    $(document).ready(function(){
        $(window).on('load resize', function() {
            let vraperH = $('.wraper').height();
            if (window.innerWidth>= 1125) {
              $('.col1').height(vraperH);
              $('.col2').height(vraperH);
              $('.col3').height(vraperH);
            }
            if (window.innerWidth < 1125) {
              $('.col1').height('auto');
              $('.col2').height('auto');
              $('.col3').height('auto');
            }
        });
    });
</script>
DevWL
  • 17,345
  • 6
  • 90
  • 86
1

giving position: absolute; to the child worked in my case

neoDev
  • 2,879
  • 3
  • 33
  • 66
1

I had the same issue, it worked based on Hakam Fostok's answer, I've created a small example, in some cases it might work without having to add display: flex; and flex-direction: column; on the parent container

.row {
    margin-top: 20px;
}

.col {
    box-sizing: border-box;
    border: solid 1px #6c757d;
    padding: 10px;
}

.card {
    background-color: #a0a0a0;
    height: 100%;
}

JSFiddle

Builo
  • 31
  • 4
0

As shown earlier, flexbox is the easiest. eg.

#main{ display: flex; align-items:center;}

this will align all child elements to the center within the parent element.

Chandan Purohit
  • 2,283
  • 1
  • 17
  • 16
0
.row-eq-height {
display: -webkit-box;
display: -webkit-flex;
display: -ms-flexbox;
display:         flex;
 }

From:

http://getbootstrap.com.vn/examples/equal-height-columns/equal-height-columns.css

states bootstrap but you do not need bootstrap to use this. Answering this old question, as this worked for me, and seems pretty easy to implement.

This was the same answer I provided to this Question

eaglei22
  • 2,589
  • 1
  • 38
  • 53
0

This trick does work: Adding a final element in your section of HTML with a style of clear:both;

    <div style="clear:both;"></div>

Everything before that will be included in the height.

Paul V
  • 351
  • 3
  • 9
0

What worked for me was adding style={{ display: 'flex', overflowY: "auto" }} to all parents of the child and then style={{ overflowY: "auto" }} to the child itself.

Akaisteph7
  • 5,034
  • 2
  • 20
  • 43
0

The following code give an ability of setting minimum height to the scroll div and also make it having 100% height of its parent by just using flex.

CSS:

.main {
  display: flex;
  flex-direction: column;
}

.scroll {
  overflow: auto;
  flex: 1 0 50px;
}

HTML:

<div class="main">
  <div class="scroll">
    Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum.
    Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum.
    Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum.
  </div>
</div>
Him Hah
  • 1,385
  • 14
  • 9
-2

This code works perfectly for me

<html>
    <body style="display: flex;">
        <div style="position: absolute; width: 100%; height: 100%; background-color: aliceblue">
            <table style="width: 100%; height: 100%;">
               <tr>
                   <td style="width: 70%; background-color: green"></td>
                   <td style="background-color: red"></td>
               </tr>
            </table>
       </div>
   </body>
-3

The easiest way to do this is to just fake it. A List Apart has covered this extensively over the years, like in this article from Dan Cederholm from 2004.

Here's how I usually do it:

<div id="container" class="clearfix" style="margin:0 auto;width:950px;background:white url(SOME_REPEATING_PATTERN.png) scroll repeat-y center top;">
    <div id="navigation" style="float:left;width:190px;padding-right:10px;">
        <!-- Navigation -->
    </div>
    <div id="content" style="float:left;width:750px;">
        <!-- Content -->
    </div>
</div>

You can easily add a header onto this design by wrapping #container in another div, embedding the header div as #container's sibling, and moving the margin and width styles to the parent container. Also, the CSS should be moved into a separate file and not kept inline, etc. etc. Finally, the clearfix class can be found on positioniseverything.

Aaron Brethorst
  • 763
  • 1
  • 6
  • 17