Ashwin
Ashwin

Reputation: 12411

CSS solution to stretch div vertically

I have 3 child div inside one parent div. first and third div are of fixed height. How do I get second div to occupy all the remaining space. Looking for only CSS solution.

HTML:

<div id="parent">
    <div id="first">1</div>
    <div id="second">2</div>
    <div id="third">3</div>
</div>

CSS:

div{border:1px solid #000}
#parent{width:200px;height:300px}
#first{width:100%;height:50px;background-color:red}
#second{width:100%;height:auto;background-color:yellow}
#third{width:100%;height:50px;background-color:blue}

JSFIDDLE: https://jsfiddle.net/n4ncb57w/

Upvotes: 1

Views: 1678

Answers (5)

Lux Logica
Lux Logica

Reputation: 1439

I'm assuming that:

  1. we don't know the height of the parent div
  2. the height of first and third divs (let's call them 'top' and 'bottom') are known in advance
  3. the height of the second div (let's call it 'middle') is not known: it should take up all the space between the 'top' and 'bottom' divs (and only that space), regardless of how much or how little content it may have.

Solution 1: Use 'absolute' positioning with both 'top' and 'bottom'

If the 'middle' div uses absolute positioning, and you don't set its height, but do set both its 'top' and 'bottom', then it will automatically stretch to fill. I have not tested it, but the markup will look something like this:

<div id="parent">
    <div id="top">
        Heading at the TOP!
    </div>

    <div id="middle">
        Lorem ipsum dolor sit amet, consectetuer...
    </div>

    <div id="bottom>
        ...and here is the BOTTOM.
    </div>
</div>

...and the stylesheet will look something like this:

#parent { 
    width: 100%; 
    height: 100vh; 
    position: relative; 
}

#top, #middle, #bottom { 
    box-sizing: border-box;
    margin: 0px;
    position: absolute;
}

#top {
    top: 0px;
    height: 63px; // <- the set height of the top
}

#bottom {
    bottom: 0px;
    height: 96px; // <- the set height of the bottom
}

#middle { 
    // no 'height' - use both 'top' and 'bottom' instead
    top: 63px; // <- the set height of the top
    bottom: 96px // <- the set height of the bottom
    overflow: auto;
}

This is probably the most straight-forward way, which is likely to have the best cross-browser support.

Solution 2: Use calc()

If you're not concerned about supporting older browsers - such as Internet Explorer 9 or earlier - then you can use calc() to get the browser to automatically calculate the height of the 'middle' div for you. The calc() built-in CSS function allows you to mix different units of measurement - like '%' and 'px' in your calculations. Using calc(), your stylesheet would look something like this:

#parent { 
    width: 100%; 
    height: 100vh; // this is the parentHeight
    position: relative; 
}

#top, #middle, #bottom { 
    box-sizing: border-box;
    margin: 0px;
}

#top {
    height: 63px; // <- the topHeight
}

#bottom {
    position: absolute;
    bottom: 0px;
    height: 96px; // <- the bottomHeight
}

#middle { 
    // Automatically calculate the height using 'calc'.
    // The formula for the calculated height should be:
    // (parentHeight - (topHeight + bottomHeight)):
    height: calc(100vh - 159px);
    overflow: auto;
}

Solution 3: Use a Flexbox Layout

There are several tutorials online that cover how to achieve what you want - and much more - using the new 'flexbox' layout mode, so I won't cover it here. Flexbox is a relatively new addition to CSS, and although current versions of Firefox, Chrome and Safari support it extremely well, Internet Explorer 10 and 11 don't (it's quite buggy). Considering that there are easier, alternative solutions - like the ones above - at this point I'd probably go with one of these. Nevertheless, Flexbox is the future, and if you want to learn how to use it, this would be a good exercise: go and learn it! ;-)

There are probably other solutions which I haven't though of, so it'll be interesting to see how many suggestions are going to turn up here...

I hope this helps!

Upvotes: 1

krishna
krishna

Reputation: 518

Use calc() method. JSFiddle

div {
  border: 1px solid #000
}
#parent {
  width: 200px;
  height: 300px
}
#first {
  width: 100%;
  height: 50px;
  background-color: red
}
#second {
  width: 100%;
  height: calc(100% - 106px);
  background-color: yellow
}
#third {
  width: 100%;
  height: 50px;
  background-color: blue
}
<div id="parent">
  <div id="first">1</div>
  <div id="second">2</div>
  <div id="third">3</div>
</div>

Upvotes: 0

Lawlez
Lawlez

Reputation: 11

I would do it with the calc() function CSS provides.

second{height: calc(100% - 106px);}

So what is done here is we subtract the combined height of #first and #third from 100%. So in this case its 2x 52px(border included), now because #second also has a 1px border we subtract another 2 px.

Fiddle

Upvotes: 0

Try using flex.

#parent{width:200px;height:300px; display: flex; flex-direction:column}
#second{width:100%;height:auto;background-color:yellow; flex-grow: 100;}

Fiddle https://jsfiddle.net/n4ncb57w/4/

Watch out for IE compatibility http://caniuse.com/#search=flex

Upvotes: 3

ketan
ketan

Reputation: 19341

One solution is use calc.

#second{
  width:100%;
  height:auto;
  background-color:yellow; 
  height: calc(100% - 100px);
}

And

#parent > div {
    box-sizing: border-box;
}

Working Fiddle

Upvotes: 0

Related Questions