# Resolving percentage heights

Copyright © 1995-2008 Opera Software AS. All rights reserved. This file is part of the Opera web browser. It may not be distributed under any circumstances.

## Inspiration

How to resolve percentage-based height is well defined in CSS 2.1:

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

And:

> Note that the height of the containing block of an absolutely positioned element is independent of the size of the element itself, and thus a percentage height on such an element can always be resolved. However, it may be that the height is not known until elements that come later in the document have been processed.

How to resolve percentage based heights inside tables is also defined in css 2.1. Unfortunately not as well defined.

> Percentage heights on table cells, table rows, and table row groups compute to 'auto'.

And:

> CSS 2.1 does not define what percentage values of 'height' refer to when specified for table cells.

## Definitions

Absolute height
  Pixel height
Relative height or percentage height
  Height depending on the height of a containing element
Containing element
  The element that percentage height is resolved against
Specified height
  Height as defined in the css rules of this element
Computed height
  Height as calculated relative to a containing element. May become auto.
ORH, Old Row Heights algorithm
  Algorithm invented by Whitney Houston during her most creative period in the early 2000s
Actual height
  The height of the element as displayed on screen.
Block formatting context
  CSS 2.1 chap 9.4.1 Floats, absolutely positioned elements, inline-blocks, table-cells, table-captions, and elements with 'overflow' other than 'visible' (except when that value has been propagated to the viewport) establish new block formatting contexts. Note: IE also starts a new block formatting context with a block with specified width.

## Basic rules

A percentage height is resolved against the generated box's containing block.

If the containing block is computed to auto, the percentage height resolves to auto, with the exception of boxes that are handled by the keep old row heights (ORH) algorithm (ref ###).

Absolute positioned elements with percentage height is resolved with the actual height of the element, not the computed height.

Otherwise percentage height is resolved as a percentage of the containing elements computed height.

### Containing element

The definition of containing block varies wildly in this context. See height resolving tables.

### Use old row heights (ORH) algorithm

The use old row heights algorithm works in two passes. The first pass is a measuring pass, where all percentage content is set to 0 (firefox intrinsic) height. The table row height is then calculated based on the non percentage content and available space in the table.

In the second pass any unresolved percentage height content is resolved against the previously calculated table row height. The actual row height will remain unchanged however.

This algorithm will very often lead to content overflowing their table cells, especially if there is mixed static and percentage height elements in the table.

(FIXME how does this apply really)In firefox and webkit (at least) any excess table row height is spread _after_ applying the use old row height algorithm. Unfortunately, interpretation of the ORH algorithm seem to differ a lot between browsers.

FIXME anything special to say about nested percentage height tables?

FIXME how are relative height tables that are over-constrained (i.e. not affected by percentage height) taken into account in ORH?

### Detailed table row height algorithm

The height of a table row is at least the height of the tallest content in any cell. But content heights calculated by the ORH algorithm does not affect table row heights.

Excess table height is distributed using the following (FIXME) algorithm.

If IE has two table cells with 100% on top of each other, the table gets twice as high. In opera not.

### Unsorted notes

Overflow on tables differ. Other browsers seem to have td { overflow:hidden; } by default. Overflow visible does not seem to work in all cases in those browers however...

IE seems to have a min-height on block boxes (and more) of one line-height.

## Height resolving table in strict mode

Strict mode | Opera (9.61) | IE 7 | Firefox (3.0.3) | WebKit (525.19) | General Comments
--- | --- | --- | --- | --- | ---
Block | Containing element | Parent block or table cell | Parent table cell, table row or nearest ancestor block with specified height or establishing a block formatting context or has specified width. | parent block, table cell or ORH. | parent block, table cell or row. |
Calculation | If the parent is a table cell, the height of the block is resolved against the computed table cell height. The computed table cell height in turn is resolved against the computed height of the table. If the parent is a table cell height is declared auto, the block is resolved against the computed height of the table row.

If both table cell and row are auto, the height computes to auto.

If parent is block, height is resolved against this parent block.

If the parent is a table cell and the table cell specified percentage height, the height of the block is resolved against the computed table cell height. The table cell height is resolved against the table height.

If the parent is a table cell and the table cell specified absolute height, the height of the block is resolved against the table cell height.

If the table cell height is declared auto, the block is resolved against the computed height of the table row.

If both table cell and row are auto, the height computes to auto.

Otherwise the nearest block with specified height or that creates a new block formatting context (or block with specified width) is used as containing block.

If parent is table cell and any of the table cells in the table row or the table row has declared percentage height, all percentage heights in the table are resolved against the actual(!) table row height, using ORH algorithm.

Otherwise percentage heights are resolved against the specified height on the table cell (which subsequently is auto or absolute).

If parent is a block, percentage heigth is resolved against this parent block.

If parent is table cell and the table has height resolved to non-auto, and the containing table cell is not the cell that contributes to the row height, the height is resolved against the actual(!) table row height.

Following behaviour has changed since WebKit 525.19

If parent is table cell and the cell content contributes to the row height, percentage height is resolved to auto.

Content is centered vertically.

Table | Containing element | Nearest ancestor that establishes a block formatting context according to the CSS2.1 chap 9.4.1 criteria or nearest ancestor that has a specified (FIXME computed?) width; | Nearest ancestor that establishes a block formatting context according to the CSS2.1 chap 9.4.1 criteria or nearest ancestor that has a specified (FIXME computed?) width; | parent block, table cell or ORH | parent block, table cell or row | FIXME more detail about when table is contained in a table.
Calculation |  |  |  |  | Any specified height on a table is treated as min-height. Apart from min-height,content of the table will affect table height except for content heights calculated with the ORH algorithm, which specifically does not affect table height.
Table Row | Containing element | containing table | containing table | containing table | containing table |
Calculation | Any computed or specified height on a table row is treated as min-height. Apart from min-height, table cell heights or content of the table row will affect height except for content heights calculated with the ORH algorithm, which specifically does not affect table row height. | Any computed or specified height on a table row is treated as min-height. Apart from min-height, table cell heights or content of the table row will affect height except for content heights calculated with the ORH algorithm, which specifically does not affect table row height. | Any computed or specified height on a table row is treated as min-height. Apart from min-height, table cell heights or content of the table row will affect height except for content heights calculated with the ORH algorithm, which specifically does not affect table row height. | If any table cell has specified height, a specified height for table row is ignored. Otherwise a computed height for table row is treated as min-height. | See also (ref ###)
Table Cell | Containing element | containing table | containing table | containing table | containing table |
Calculation | Table cell height is not resolved individually but as a part of the table row height algorithm. Any height or content of a table cell contributes to the table row height if it is greater than either the specified table row height or greater than any other table cell height, or if the content of the table cell is taller than any other table cell content in this row.

ORH content of a table cell does not contribute to table row height.

However computed height of table cells may affect children percentage heights.

Table cell height is not resolved individually but as a part of the table row height algorithm. Any height or content of a table cell contributes to the table row height if it is greater than either the specified table row height or greater than any other table cell height, or if the content of the table cell is taller than any other table cell content in this row.

ORH content of a table cell does not contribute to table row height.

However computed height of table cells may affect children percentage heights.

Table cell height is not resolved individually but as a part of the table row height algorithm. Any height or content of a table cell contributes to the table row height if it is greater than either the specified table row height or greater than any other table cell height, or if the content of the table cell is taller than any other table cell content in this row.

ORH content of a table cell contributes to table row height with intrinsic height

Table cell height is not resolved individually but as a part of the table row height algorithm. Any height or content of a table cell contributes to the table row height if it is greater than any other table cell height, or if the content of the table cell is taller than any other table cell content in this row.

If this is the cell that contributes to the table height, any percentage content height is resolved to auto. Otherwise percentage content is resolved agains the table row height.

Replaced | Containing element | Nearest ancestor with a height that is not resolved to auto or the nearest ancestor that establishes a block formatting context or has a specified width. | Nearest ancestor with a height that is not resolved to auto or the nearest ancestor that establishes a block formatting context or has a specified width. | Nearest ancestor. | Nearest ancestor with a height that is not resolved to auto.
Calculation | If the parent is a table cell, the height of the element is resolved against the computed table cell height. The computed table cell height in turn is resolved against the computed height of the table (and specifically not any specified, computed or actual table row height, nor the actual height of the table).

If parent is block, height is resolved against the nearest block with non-auto height or nearest block establishing a new block formatting context, or nearest block with non-auto width.

If parent is table cell ####

If parent is block, height is resolved against the nearest block with non-auto height or nearest block establishing a new block formatting context, or nearest block with non-auto width.

If parent is table cell and any of the table cells in the table row (entire table?) or the table row has specified percentage height, all percentage heights in the table row are resolved against the actual (sic!) table row height, using the ORH algorithm.

Otherwise percentage heights are resolved against the specified height on the table cell (auto or absolute).

If parent is block, percentage heigth is resolved against this parent block.

If parent is table cell and the table has height resolved to non-auto, the height is resolved against the actual (sic!) table row height, using the ORH algorithm.

If any table cell has absolute height, the height is resolved against the cell specified height.

Content is centered vertically.

There is something more strange going on probably (?) regarding squeezing content into the last row.

If parent is block, percentage height is resolved against the nearest ancestor with non-auto height, disregarding new block formatting contexts. If a table is encoutered futher down the tree, however, height is resolved against the table cell height. But only if it has non-relative height specified, otherwise it is resolved to auto (sic!)

Replaced inline and replaced block elements are handled (essentially) the same way.

Relative positioned | Containing element |  |  |  |  | Works the same way as statically positioned block, tables or replaced elements respectively
Calculation |  |  |  |  | Works the same way as statically positioned block, tables or replaced elements respectively
Absolute positioned | Containing element | nearest positioned ancestor that is not table, tablerow, tablecell. | table cell, table row or nearest ancestor block with specified height or establishing a block formatting context or has specified width. | nearest positioned ancestor that is not table, tablerow, tablecell | nearest positioned ancestor that is not table, tablerow, tablecell |
Calculation | Opera calculation | IE calculation | Firefox calcualtion | WebKit calculation |

## Height resolving table in quirks mode

Strict mode | Opera | IE 7 | Firefox | WebKit | General Comments
--- | --- | --- | --- | --- | ---
Block | Containing element |  | . |  |  |
Calculation |  |  |  |  |
Table | Containing element |  |  |  |  |
Calculation |  |  |  |  |
Table Row | Containing element | containing table | containing table | containing table | containing table |
Calculation |  |  |  |  |
Table Cell | Containing element | containing table | containing table | containing table | containing table |
Calculation |  |  |  |  |
Replaced | Containing element |  |  |  |
Calculation |  |  |  |  |
Relative positioned | Containing element |  |  |  |  |
Calculation |  |  |  |  |
Absolute positioned | Containing element |  |  |  |  |
Calculation |  |  |  |  |