Why Does 100% Not Mean 100% Height

Why does 100% not mean 100% height?

The issue is covered in the CSS 2.1 spec:

<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 (i.e., it depends on content height), and this
element is not absolutely positioned, the value computes to 'auto'. A
percentage height on the root element is relative to the initial
containing block. Note: For absolutely positioned elements whose
containing block is based on a block-level element, the percentage is
calculated with respect to the height of the padding box of that
element. This is a change from CSS1, where the percentage was always
calculated with respect to the content box of the parent element.

So, to clarify, a percentage height will reference the height of its containing block (unless it is position: absolute or position: fixed). If that containing block does not have a specified height, then the percentage will refer to auto, and it won't really do much.

position: absolute changes the referenced containing block to the nearest positioned (absolute, relative, or fixed) element.

position: fixed changes the referenced containing block to the viewport.

So, if you specify a height on your containing block, specify a position other than static on your containing block, or don't mind using the viewport as your containing block, then you can use percentage heights effectively.

Please see my demonstration at jsFiddle

Why is 100% height not 100% of the browser height?

The short answer: It's complicated. To really understand all the factors that affect CSS 100% heights (and widths) you'll need to know about terms such as: the view port, initial containing block, flow, overflow, inline formatting contexts, block formatting contexts, the W3C box model, the IE box model and Quirks Mode.

If you're really interested on getting on top of it there is no better place to start than the spec: The Visual Formatting Model

But here's an overview.

Heights on inline elements are calculated differently than block elements -- so from here on this only refers to block elements or elements which have been given new block formatting contexts.

To start with when you give an element 100% height, it will take it's height from it's containing block eg. it's parent and it's parent takes it's height from it's parent and so-forth back to the initial containing block.

The initial containing block is different in HTML (body) and XML/XHTML (html) and it's default height isn't 100% of the viewport so normally you would cover your butt and define it this way:

html, body {
margin:0;
padding:0;
height:100%;
}

We had to zero the margin and padding because in CSS the Height property refers to the height of the Content Box and if there was any margin or padding (or border) we'd get a scrollbar. The height would be 100% + padding + border + margin... W3C Box Model

The exception to this is if IE is in Quirks Mode... IE box model

...so unless you maintain this "100% height" through all descendant elements then you are redefining the meaning of "100% height" to each new descendant. This can also be affected by the creation of a new Block Formatting Context. You create new bock formatting contexts when you Float or Absolutely Position an element (as well as some other things)

About the height of Table cells...

People often ask "Why won't my Div with 100% height work in a table cell?".

This has to do with how a Table cell's height is calculated. When a cell is rendered the height of it's content box isn't stretched to match the height of the parent Row. The renderer instead adds extra padding as required so that the overall height matches the height of the Row. So in this example...

<tr>
<td>
line one<br>
line two<br>
line three
</td>
<td>
<div style="height:100%">
Hello world!
</div>
</td>
</tr>

...the height of the Div is 100% -- 100% of the cell's Content Box. The cell's content box was given extra padding so that it matched the overall height of the row. The Div's height is 100% of it's parents content box (not the overall height).

See Table height algorithms.

As this question seems to be asked almost daily I've check the Wiki check box -- I'm a newbie but presumable this will make it easier for others to make corrections and additions as needed.

difference between css height : 100% vs height : auto

height: 100% gives the element 100% height of its parent container.

height: auto means the element height will depend upon the height of its children.

Consider these examples:

height: 100%

<div style="height: 50px">
<div id="innerDiv" style="height: 100%">
</div>
</div>

#innerDiv is going to have height: 50px

height: auto

<div style="height: 50px">
<div id="innerDiv" style="height: auto">
<div id="evenInner" style="height: 10px">
</div>
</div>
</div>

#innerDiv is going to have height: 10px

Why does 100% height = 0px in this context?

As as stated in my comment, it's because none of that element's parents have a declared height. Why does that matter? Becuase that's just how it works.

MDN:

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 (i.e., it depends on content
height), and this element is not absolutely positioned, the value
computes to auto
. A percentage height on the root element is relative
to the initial containing block.

Why doesn't height: 100% work to expand divs to the screen height?

In order for a percentage value to work for height, the parent's height must be determined. The only exception is the root element <html>, which can be a percentage height. .

So, you've given all of your elements height, except for the <html>, so what you should do is add this:

html {
height: 100%;
}

And your code should work fine.

* { padding: 0; margin: 0; }html, body, #fullheight {    min-height: 100% !important;    height: 100%;}#fullheight {    width: 250px;    background: blue;}
<div id=fullheight>  Lorem Ipsum        </div>

why doesn't height: 100% and width: 100% work?

To get vertical alignment you have to have a second div inside the first 100% sized one.

Approx centering (fine for small amounts of text) is easy: http://jsfiddle.net/ngVSd/4

If you want proper centering you have to set the height and width of the central div explicitly then give it negative margins of 1/2 the width and height. You also have to remove the padding and margin from body.

Note that to vertically center the text in the inner div you also need to set its line-height to be the same as its height: http://jsfiddle.net/ngVSd/6/

html, body {     height: 100%;    margin: 0;    padding: 0;}
#outerDiv { height: 100%; width: 100%; background-color: red; text-align: center; }
#wordDiv { position: absolute; background-color: lightblue; top: 50%; left: 50%; width: 100px; height: 100px; line-height: 100px; margin: -50px -50px;}
<div id="outerDiv">    <div id="wordDiv">Word</div></div>

Why does height 100% work when DOCTYPE is removed?

CSS height property, percentage values & DOCTYPE

The first part of your question asking how to apply a 100% height to your div has been answered several times by others. Essentially, declare a height on the root element:

html { height: 100%; }

A complete explanation can be found here:

  • Working with the CSS height property and percentage values.

The second part of your question has received much less attention. I'll try to answer that.

Why does removing the doctype make [the green background] work?

When you remove the DOCTYPE (document type declaration) the browser switches from standards mode to quirks mode.

In quirks mode, also known as compatibility mode, the browser simulates an old browser so it can parse old web pages – pages authored before the advent of web standards. A browser in quirks mode pretends to be IE4, IE5 and Navigator 4 so it can render old code as the author intended.

Here's how Wikipedia defines quirks mode:

In computing, quirks mode refers to a technique used by some web
browsers for the sake of maintaining backward compatibility with web
pages designed for older browsers, instead of strictly complying with
W3C and IETF standards in standards mode.

Here's MDN's take:

In the old days of the web, pages were typically written in two
versions: One for Netscape Navigator, and one for Microsoft Internet
Explorer. When the web standards were made at W3C, browsers could not
just start using them, as doing so would break most existing sites on
the web. Browsers therefore introduced two modes to treat new
standards compliant sites differently from old legacy sites.

Now, here's the specific reason why the height: 100% in your code works in quirks mode but not in standards mode:

In standards mode, if the parent element has a height: auto (no height defined), then the percentage heights of child elements will also be treated as height: auto (as per the spec).

This is why the answer to your first question is html { height: 100%; }.

For height: 100% to work in your div, you must set a height on parent elements (more details).

In quirks mode, however, if the parent element has a height: auto, then the percentage heights of child elements are measured relative to the viewport.

Here are three references covering this behavior:

  • https://www.cs.tut.fi/~jkorpela/quirks-mode.html
  • https://stackoverflow.com/a/1966377/3597276
  • https://developer.mozilla.org/en-US/docs/Mozilla_Quirks_Mode_Behavior

TL;DR

Here's what developers need to know in a nutshell:

A browser in quirks mode will render web pages in a way that is
unpredictable, unreliable and often undesirable. So always include a
DOCTYPE
for the document to render in standards mode.

Selecting the right DOCTYPE used to be an ambiguous and somewhat
confusing process with many DOCTYPE versions to choose from. But
today the process is as simple as ever. Just use:

<!DOCTYPE html>

Why height=100% doesn't work?

In general, for an element using percent on height to pick up its parent's height, the parent need a height other than auto or being positioned absolute, or the height will be computed as auto.

Based on those 2 options, and as you mentioned in a comment, your own header is dynamic in height, you are left with absolute positioning.

The problem with adding absolute to the content, it will be taken out of flow and stop behaving as a normal flowed flex item, the good news, one can add a wrapper set to absolute.

Stack snippet

.container {  display: flex;  flex-direction: column;  width: 200px;  height: 100px;}
.header { display: flex; background-color: rgba(255, 0, 0, 0.5);}
.content { position: relative; /* added */ flex-grow: 1; background-color: rgba(0, 255, 0, 0.5);}
.wrapper { position: absolute; /* added */ left: 0; /* added */ top: 0; /* added */ right: 0; /* added */ bottom: 0; /* added */}
.third-party-component { height: 100%; width: 100%; background-color: rgba(0, 0, 255, 0.5);}
<div class="container">  <div class="header">Header</div>  <div class="content">    <div class="wrapper">      <div class="third-party-component">       Third party component      </div>    </div>  </div></div>

What does it mean to give a div a style='height:100%'?

100% of the parent container's height.

See here: http://jsfiddle.net/6VRn6/

If you want to use this method to make the div 100% of the page's height, you have to specify the height as 100% of the body and html as well.

body, html {
height: 100%;
}

When you don't specify a html or body height, their heights are the sum of the heights of the elements in it.

Updated demo showing this. We have a 200px div with 2px borders totaling 204px and then a 40px status div. The body height should be 244px. Now, if you add the CSS above to the page, the height will be the height of the bottom right quadrant of the jsfiddle. Try adding it and running the code again. Then resize the result pane and run it again to see the height change accordingly.

CSS height 100% makes element height more than 100%

The reason you're getting the vertical scrollbar is because you're telling the div parent of col1 and col2 to be height: 100%. This by itself gives it the full height of the viewport.

From your code:

<div id='newdiv' style="display:flex; flex-direction:row; height:100%">
<div style="background:#ffd0d0"> Col 1 </div>
<div> Col 2 </div>
</div>

Except this div has a sibling: the header div, which is also taking up space.

So when the browser does it's height calculation, here is the result:

100% + (computed height of header div) > viewport height = vertical scrollbar

Instead of using defined heights, consider letting flexbox do the work. By default, flex items expand the full length of the container along the cross-axis.

So by simply declaring display: flex, child elements will expand to fill all available space (with no vertical scroll). But since a height rule will override this flex setting, we need to remove height: 100% from any flex items.

html, body { height: 100%; }
<body style="margin:0">    <div style="height:100%;display:flex;flex-direction:column">        <div style="background:#d0d0ff">            This is a header        </div>        <div style="background:#d0ffd0;flex-grow:1; display: flex;"><!--adjustment here-->            <div id='newdiv' style="display:flex;"><!--adjustment here-->                <div style="background:#ffd0d0; display: flex;"> Col 1 </div>                <div> Col 2 </div>            </div>        </div>    </div></body>


Related Topics



Leave a reply



Submit