Why is percentage height not working on my div? [duplicate]
Asked Answered
D

2

88

I have two divs with a height of 90%, but the display is different.

I have tried to put an outer div around them, but that has not helped. Also, it's the same on Firefox, Chrome, Opera, & Safari.

Can someone explain why I am having this problem?

Below is my code:

<div style="height: 90%">
    <div ng-controller="TabsDataCtrl" style="width: 20%; float: left;">
        <tabset>
            <tab id="tab1" heading="{{tabs[0].title}}" ng-click="getContent(0)" active="tabs[0].active"
               disabled="tabs[0].disabled">
            </tab>


            <tab id="tab2" heading="{{tabs[2].title}}" ng-click="getContent(2)" active="tabs[2].active"
                 disabled="tabs[2].disabled">
            </tab>
        </tabset>
    </div>

    <div id="leaflet_map" ng-controller="iPortMapJobController">
        <leaflet center="center" markers="markers" layers="layers" width="78%"></leaflet>
    </div>
</div>
Decoration answered 30/7, 2015 at 15:30 Comment(0)
R
47

Use vh (viewport height) instead of percentage. It will get the height of the browser and size it accordingly, e.g.

height:90vh;

try this code

<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <title>JS Bin</title>
</head>
<body>
<div id ="wrapper">
    <div id="tabs" ng-controller="TabsDataCtrl">
        <tabset>
            <tab id="tab1" heading="{{tabs[0].title}}" ng-click="getContent(0)" active="tabs[0].active"
               disabled="tabs[0].disabled">
            </tab>


            <tab id="tab2" heading="{{tabs[2].title}}" ng-click="getContent(2)" active="tabs[2].active"
                 disabled="tabs[2].disabled">
            </tab>
        </tabset>
    </div>

    <div id="leaflet_map" ng-controller="iPortMapJobController">
        <leaflet center="center" markers="markers" layers="layers"></leaflet>
    </div>
    </div>
</body>
</html>

with css

<style>
    #wrapper{height:60vh;}
    #tabs {width:20% float:left; height:60vh; overflow-y:scroll; overflow-x:hidden;}
    #leaflet-map{width:78%; height:60vh; overflow-y:scroll;  overflow-x:hidden;}
</style>
Rhyner answered 30/7, 2015 at 15:37 Comment(2)
it didn't make a differenceDecoration
I changed the css a bit, its now like #wrapper { height: 90vh; } #tabs { width: 20%; float: left; height: 90vh; overflow-y: scroll; overflow-x: hidden; } #leaflet-map { width: 78%; float: right; overflow-y: scroll; overflow-x: hidden; }Decoration
V
213

Working with the CSS height property and percentage values

The CSS height property, when used with a percentage value, is calculated with respect to the element's containing block.

Let's say your body element has height: 1000px. Then a child with height: 90% would get 900px.

If you have not set an explicit height to the containing block (and the child is not absolutely positioned), then your child element with percentage height will have nothing to go on and height will be determined by content and other properties.

From the spec:

10.5 Content height: the height property

percentage
Specifies a percentage height. The percentage is calculated with respect to the height of the generated box's containing block. If the height of the containing block is not specified explicitly and this element is not absolutely positioned, the value computes to 'auto'.

auto
The height depends on the values of other properties.

Hence, if you want to use percentage heights in your divs, specify the height of all parent elements, up to and including the root element (e.g., html, body {height:100%;})

Note that min-height and max-height are not acceptable. It must be the height property.

Here's a little summary:

John: I want to set the height of my div to 100%.
Jane: 100% of what?
John: 100% of its container. So, the parent one-level up.
Jane: Okay. And what's the height of the div's parent?
John: Doesn't have one. Auto, I guess. Content-driven.
Jane: So, you want the div to have a 100% height of an unknown variable?
John: [silence]
Jane: Hey John, can I have 50% of that?
John: 50% of what?
Jane: Exactly!
Jane: Percentages are relative values. You always have to ask "percentage of what?". By declaring an explicit height for each parent all the way up to body and html you establish a frame of reference for each child with percentage height, enabling the height to work.

Examples

Let's say you want a div to have 50% height of its parent.

This won't work:

<article>
    <section>
        <div style="height:50%"></div>
    </section>
</article>

Neither will this:

<article>
    <section style="height:100%">
        <div style="height:50%"></div>
    </section>
</article>

And neither will this:

<article style="height:100%">
    <section style="height:100%">
        <div style="height:50%"></div>
    </section>
</article>

This will fail, too:

<body style="height:100%">
    <article style="height:100%">
        <section style="height:100%">
            <div style="height:50%"></div>
        </section>
    </article>
</body>

NOW, it will finally work:

<html style="height:100%">
    <body style="height:100%">
        <article style="height:100%">
            <section style="height:100%">
                <div style="height:50%"></div>
            </section>
        </article>
    </body>
 </html>

And this would work, as well:

<article>
    <section style="height: 500px">
        <div style="height:50%"></div>
    </section>
</article>

But not this:

<article>
    <section style="min-height: 500px">
        <div style="height:50%"></div>
    </section>
</article>

sample code


Use 100vh

As you can see, percentage heights are a bit tricky. You can avoid the complexity (i.e., never have to consider parent elements) by simply using viewport percentage heights. Whenever you want a box to be the height of the viewport, use height: 100vh instead of height: 100%. Nothing else is needed.

Absolute Positioning Exception

As noted in the spec, an absolutely positioned element is an exception to the rule for percentage heights. More details here: Applying 100% height to nested, non-flex elements.

Vasodilator answered 30/7, 2015 at 16:5 Comment(18)
<html><body style="height:100%">**Will this work?**</body></html> - Isn't the default of a tag always 100% (it fills as much as possible), so if the parents height wasn't declared the body in my example above would simply fill out the whole html. In other words it is going to work. Am I wrong?Crust
@Bjango, yes, that is incorrect. HTML elements generally default to height: auto (the height of the content), not height: 100%. Width, on the other hand, defaults to width: 100% (the width of the parent) on block-level elements.Vasodilator
Here's a more detailed explanation: https://mcmap.net/q/37036/-how-to-make-a-div-100-height-of-the-browser-windowVasodilator
Here's a rare exception, where elements default to height: 100%: https://mcmap.net/q/37037/-why-does-height-100-work-when-doctype-is-removed/3597276Vasodilator
What about a fixed height header and you want to fill the remaining height under itTripe
Haha I feel like I just read a Head First CSS book after reading this answers' summary section. Nice job!Sauncho
@Michael_B hello! I have this jsfiddle jsfiddle.net/hasugamer/bjq8rn0s/147 where I encounter a weird situation: So what I want to achieve is have a grid (consisting of thirds) laid out over some content (whatever that is, text, picture, etc) pretty much like in this scenario: codepen.io/rm/pen/nemsu. But in the codepen example I feel like it was done pretty much hardcoded and I want it to be responsive (resize height etc). But before I get there I need to lay out the table over the content and it won't work. It's height won't stretch even with absolute pos, but a div will.Shortstop
@Michael_B also please note that I've left some comments in the fiddle to explain better what's going on. The gist of it is that I have a container which has an auto height. I'd like to have a table which I could put on top of that container and match its height without knowing explicitly what its height is. In my mind this can be determined at rendering time? I don't necessarily need a table, I've noticed that a div would work however I'd like to understand why a table won't or if you could please point me in the right direction with the documentation. Thank you!Shortstop
I'm not sure there is any official documentation outlining this behavior. It looks more like differences in browser implementation. Note that your code works in Firefox. @GeorgeVasodilator
You're combining percentage heights (which has well-documented rendering variations among browsers), HTML table elements (which have its own complex rendering algorithm, and which the W3C even admits is "not fully defined", and which leads to additional rendering variations among browsers), and CSS absolute positioning (which removes the table from the document flow, again complicating matters).Vasodilator
My suggestion would be to use the simplest combination of elements and styles possible. Using a div, instead of a table, would be a good start in my opinion. You can emulate a table layout using CSS flex and grid layouts. Also, consider posting a formal question. This issue is interesting and may be useful to others (plus I may have missed something). @GeorgeVasodilator
@Michael_B phew, I really didn't think you'd answer after a few days haha. Thank you so much for the reply. Okay, I will post a formal question about this issue, as I've done some research and it's not a duplicate of anything (as you might have noticed). See you on that thread, I'll ping you here with the linkShortstop
@Michael_B as promised: #54368842Shortstop
@MichaelBenjamin But let's think we have displa-inline block containe and don't have explicit width but have 2 inner element (display inline-block) one of them have explicit width and container width will width of child and if i give other inner element width with percentage child width will relative implicit width of container but this is not work for height why?Jauregui
Thank you so much for this answer! My issue was there was a min-height in the chain and I had no idea it was causing the children height: 100%s to failDitto
Will a percentage work if the parent div has height specified using vh? e.g. parent div height = 90vh, child div height=100%. This is not working for me currently.Hyacinthie
Thank you @MichaelBenjamin. I liked the conversation part. It solved my issues in under 30 seconds. Awesome.Badderlocks
It is incorrect to say that the height is inherited directly from the parent element. After all, the height can be flexible, regardless of whether the height is specified directly in the parent element. Also the statement about min-height is incorrect. Here is a simple example of when it will work: <section style="min-height: 500px; display: grid;"><div style="height: 50%;"></div></section> exampleJada
R
47

Use vh (viewport height) instead of percentage. It will get the height of the browser and size it accordingly, e.g.

height:90vh;

try this code

<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <title>JS Bin</title>
</head>
<body>
<div id ="wrapper">
    <div id="tabs" ng-controller="TabsDataCtrl">
        <tabset>
            <tab id="tab1" heading="{{tabs[0].title}}" ng-click="getContent(0)" active="tabs[0].active"
               disabled="tabs[0].disabled">
            </tab>


            <tab id="tab2" heading="{{tabs[2].title}}" ng-click="getContent(2)" active="tabs[2].active"
                 disabled="tabs[2].disabled">
            </tab>
        </tabset>
    </div>

    <div id="leaflet_map" ng-controller="iPortMapJobController">
        <leaflet center="center" markers="markers" layers="layers"></leaflet>
    </div>
    </div>
</body>
</html>

with css

<style>
    #wrapper{height:60vh;}
    #tabs {width:20% float:left; height:60vh; overflow-y:scroll; overflow-x:hidden;}
    #leaflet-map{width:78%; height:60vh; overflow-y:scroll;  overflow-x:hidden;}
</style>
Rhyner answered 30/7, 2015 at 15:37 Comment(2)
it didn't make a differenceDecoration
I changed the css a bit, its now like #wrapper { height: 90vh; } #tabs { width: 20%; float: left; height: 90vh; overflow-y: scroll; overflow-x: hidden; } #leaflet-map { width: 78%; float: right; overflow-y: scroll; overflow-x: hidden; }Decoration

© 2022 - 2024 — McMap. All rights reserved.