Status of this Document

This document is work in progress towards a proposal by the author
for future additions to CSS specifications. It is intended that each
rule in this specification is compatible with what at least some
existing implementations do. Since it is an attempt to define more
precisely the behavior of features that already exist, it is hoped that
it is already suitable for implementation, with the caveat that behavior
eventually specified may differ from this proposal, perhaps
significantly enough to make work spent implementing this draft a waste
of time.

Background

In [CSS2], the rules for computing the
dimensions of a table or the distribution of column widths within the
table were left undefined (for the case when table-layout is auto, the default value), although a
non-normative algorithm was presented that depended on two intrinsic
widths of a piece of content. No other reference was made to intrinsic
widths.

In [CSS21], the rules
for computing widths of absolutely positioned elements and floating
elements were modified so that they also depend on two intrinsic widths
of the content, and rules for elements with display: inline-block (a new feature) were added that
also used these two intrinsic widths (and a common set of rules, called
"shrink-to-fit", for using those widths).

Terminology

This document uses the terms intrinsic
preferred width and intrinsic minimum
width to describe the two intrinsic
widths. The following table compares this to the terminology used
elsewhere:

This proposal

CSS 2.1 visual formatting model

CSS 2 auto table layout

intrinsic preferred width

preferred width

"maximum" cell width (similar)

intrinsic minimum width

preferred minimum width

minimum content width (similar)

Conceptually, the intrinsic preferred width is intended to be the
largest width that the content can usefully fill. For example, for an
unstyled block of text, the intrinsic preferred width is the width of
the text when laid out end-to-end (one one line).

Likewise, the intrinsic minimum width is intended to be the smallest
width that the content can fit in without unintended overflow. For
example, for an unstyled block of text, the intrinsic minimum width is
the width of the longest word (unbreakable unit) in the text.

This specification also defines the outer intrinsic minimum
width and the outer intrinsic preferred width of boxes.
These are values derived from the intrinsic widths, but modified by
considering the computed values of the
width,
min-width,
max-width,
box-sizing,
padding-left,
border-left-width,
margin-left,
padding-right,
border-right-width,
margin-right, and other properties.
These outer intrinsic widths are then an important part of the
definition of the parent box's intrinsic width.

Intrinsic widths of non-table boxes

For inline elements, intrinsic widths are defined to be the
corresponding intrinsic width of a hypothetical anonymous block placed
around the inline element. (This definition exists so that it is
defined. However, it shouldn't be used for anything.)

The minimum intrinsic width of a block,
inline-block, or table cell, is defined to be the largest of the
following:

The handling of floats within the definition of
preferred intrinsic width of blocks is not yet written properly. I need
to write the handling of clear, and perhaps some other additions.

Note that the current behavior of Web browsers for
handling intrinsic widths of blocks containing floats is not very
interoperable.

This manner of specifying (and implementing) intrinsic
width calculations makes it impossible to specify (or implement) ideal
behavior for preferred width of blocks containing floats. The goal of
this specification is simply to define an approximation that is good
enough, and can be interoperably implemented.

Note that the properties 'width', 'min-width', and 'max-width' do not
affect the intrinsic widths of the elements on which they are specified.
However, they can affect the intrinsic widths of the parent element in
many cases, through their effect on the outer intrinsic widths. This
allows declarations like the following to be useful:

width: 5em;
min-width: min-intrinsic;

and also allows some formatting objects (such as flexible boxes) to use
formatting rules in which these properties on children do not effect the
intrinsic widths of the parent.

These rules only describe intrinsic and min-intrinsic
widths. The parallel rules for heights are quite complicated. Such
rules are necessary for mixed vertical and horizontal text, for a
flexible box model, and side table captions.

Outer intrinsic widths

This needs to account for the 'box-sizing'
property.

The following definitions are defined in terms of the values of
properties; when not otherwise specified, the values used are the
computed values. However, percentages on the following properties
are treated instead as though they were the following:

width, min-width

auto

max-width

none

margin*, padding*

0

and 'auto' values for 'width' should be treated as 0 when in max() and
infinite when in min().

Instead of treating percentage padding and margin as
zero, we should instead invert it for preferred intrinsic width (to a
limit of infinite preferred width). Perhaps it should even be inverted
for minimum intrinsic width, although with a much smaller limit. There
is little enough interoperability on this issue today to allow either
choice.

some of the "m + b + p" also need to include
scrollbars, but we don't always know when the scrollbars are present.
Figure out what needs to happen here. There may also be interesting
interactions between the 'overflow' property and percentage widths or
heights.

This specification defines the terms outer intrinsic minimum
width and outer intrinsic preferred width for the
intrinsic width values that are used as part of the computation of the
parent box's intrinsic widths.

The outer intrinsic minimum width
of blocks and inline-blocks is defined to be the following:

Intrinsic widths of inline formatting
contexts

Define minimum intrinsic width
of an inline formatting context. Break line at every point. Don't
forget all text-indent, word-spacing, letter-spacing, m/b/p on inlines,
etc. when doing this breaking. Also whitespace trimming.

Automatic Table Layout

The following rules define behavior of tables with table-layout: auto that is undefined in CSS2.1.

Note that the results produced by these rules do not
change if the order of rows in a table is changed (assuming appropriate
rearrangement of row-spanning cells). This is true of most, but not
all, current implementations of CSS2 table layout. These rules do
produce variation under reordering of columns (assuming appropriate
rearrangement of column-spanning cells) in one circumstance: when
columns have percentage widths that add to more than 100%.

The following terms are parameters of tables or table cells. These
parameters encapsulate the differences between tables with different
values of border-collapse (separate or collapse) so that the remaining subsections of
this section do not need to refer to them differently.

cell intrinsic offset

The cell intrinsic offset is a term to capture the parts of
padding and border of a table cell that are relevant to intrinsic
width calculation. It is defined as follows:

in tables with border-collapse: collapse, the padding values that
would be used to compute the outer
intrinsic preferred/minimum width, plus half the width of
the winning left border for the cell (the largest winning left
border for a row-spanning cell) plus half the width of the
winning right border for the cell (the largest winning right
border for a row-spanning cell)
Is this the correct way to account for
row-spanning cells with different borders?

The behavior of cells with percentage padding
should track the behavior of blocks with percentage padding above. If this changes, this needs to
be an algorithm rather than a term.

table intrinsic offset

The table intrinsic offset is a term to capture the parts of the
padding and border of a table that are relevant to intrinsic width
calculation. It is defined as follows:

in tables with border-collapse: collapse, half the width of the
winning left border of the top row of the table plus half the
width of the winning right border of the top row
Is this the correct way to account for
the various changes that have gone into CSS2.1 regarding which
border sticks out into the margin?

The margins are not included in the table intrinsic
offset because handling of margins depends on the 'caption-side'
property.

The behavior of tables with percentage padding
should track the behavior of blocks with percentage padding above. If this changes, this needs to
be an algorithm rather than a term.

total horizontal border spacing

The total horizontal border spacing is defined for each table:

for tables with border-collapse: separate and at least one column, the
horizontal component of the computed value of the border-spacing property times one plus
the number of columns in the table

otherwise, 0

Should the border-spacing not be added when there
are no cell boundaries at a column boundary?

The outer intrinsic minimum and preferred widths are defined for
table cells, columns, and column groups. The 'width', 'min-width', and
'max-width' values used in these definitions are those defined above:

The outer intrinsic minimum width of a table cell is
max('min-width', min('max-width', intrinsic minimum width)) plus the
cell intrinsic offset.
Should 'max-width' really be able to override the
intrinsic minimum width? An alternative expression is max('min-width',
intrinsic minimum width).

The outer intrinsic minimum width of a table column or column group
is 'min-width'.
How do values specified on columns and column groups
interact?

The outer intrinsic preferred width of a table cell with width not
'auto' is max('min-width', min('max-width', max('width', intrinsic
minimum width))) plus the cell intrinsic offset.
Should 'max-width' be able to override the intrinsic
minimum width? An alternative expression is max('min-width',
intrinsic minimum width, min('max-width', 'width')).

The outer intrinsic preferred width of a table column or
column group is max('min-width', min('max-width', 'width')).
How do values specified on columns and column groups
interact?

The percentage contribution of a table
cell, column, or column group is defined in terms of the computed values
of 'width', 'max-width', and 'min-width' that have computed values that
are percentages. It is max(percentage 'min-width', min(percentage
'width', percentage 'max-width')). If the computed values are not
percentages, then 0% is used for 'width' or 'min-width', and an infinite
percentage is used for 'max-width'.

These definitions need to account for the 'box-sizing'
property.

Intrinsic widths of columns

This subsection defines terms for various parameters associated with
each column of a table. These parameters are used in the following two
subsections as part of the rules for computing intrinsic widths of
tables and computing the column widths of a table.

The spanning and non-spanning intrinsic widths are
intermediate values that are used only within this section. The
rationale for having these separate definitions of spanning and
non-spanning widths is to make the layout of tables invariant under
reordering of the rows. This invariant is maintained by most, but not
all, current Web browser implementations.

This needs to account for character-alignment of cells
('<string>' values of the 'text-align' property). This requires
separately tracking at least intrinsic preferred widths, and perhaps
intrinsic minimum widths, for the part of the column after the alignment
point.

The handling of the 'max-width' property on cells,
columns, and column groups with this algorithm is very poor. It should
have an effect stronger than the one it has on the outer intrinsic
widths of the element on which it is specified. It probably (1) ought
to be a separate interim parameter of the column and (2) ought to have a
different effect on constrainedness.

intrinsic non-spanning minimum width

the largest of:

the outer intrinsic minimum width of the column group, if
any

the outer intrinsic minimum width of the column, if
any

the outer intrinsic minimum width of each cell in the column
whose 'column-span' property has a computed value of '1'

Is this the correct interaction of width properties
specified on columns and column groups?

intrinsic non-spanning preferred width

the largest of:

the outer intrinsic preferred width of the column group, if
any

the outer intrinsic preferred width of the column, if
any

the outer intrinsic preferred width of each cell in the column
whose 'column-span' property has a computed value of '1'

Is this the correct interaction of width properties
specified on columns and column groups?

intrinsic non-spanning percentage width

the largest of the percentage
contributions of each cell in the column whose 'column-span'
property has a computed value of '1', of the column (if any), and of the
column group (if any)

intrinsic spanning minimum width

the largest of the contributions of the cells in the column whose
'column-span' property has a computed value other than '1', where the
contribution of a cell is the result of taking the following steps:

Start with the outer intrinsic minimum width of the cell.

Subtract the intrinsic non-spanning minimum width of all columns
that the cell spans. If this gives a negative result, change it to
zero.

Multiply by the ratio of

the column's intrinsic non-spanning preferred
width to

the sum of the intrinsic non-spanning preferred
widths of all columns spanned by the cells.

However, if this ratio is undefined because
the denominator is zero, instead divide by the number of columns
spanned by the cell.

intrinsic spanning preferred width

the largest of the contributions of the cells in the column whose
'column-span' property has a computed value other than '1', where the
contribution of a cell is the result of taking the following steps:

Start with the outer intrinsic preferred width of the cell.

Subtract the intrinsic non-spanning preferred width of all columns
that the cell spans. If this gives a negative result, change it to
zero.

Multiply by the ratio of

the column's intrinsic non-spanning preferred width to

the sum of the intrinsic non-spanning preferred widths of all
columns spanned by the cells.

However, if this ratio is undefined because the denominator is zero,
instead divide by the number of columns spanned by the cell.

It is the largest of the contributions of the cells in the column whose
'column-span' property has a computed value other than '1', where the
contribution of a cell is the result of taking the following steps:

However, the intrinsic percentage width is constrained so that a
column's intrinsic percentage width and the intrinsic percentage width
of all prior columns (those to its left in a table with 'direction: ltr'
or to the right in a table with 'direction: rtl') cannot add to more
than 100%. If this constraint would be broken, it is instead the value
that makes them add to 100%.

The clamping of the total of the intrinsic percentage
widths of columns to a maximum of 100% means that the table layout
algorithm is not invariant under switching of columns.

constrainedness

A column is constrained if the column group (if any), the column
(if any), or any of the cells in the column with a 'column-span'
property whose computed value is '1' has a computed 'width' or
'max-width' that is not 'auto', is not 'none', and is not a
percentage.

Is 0% really treated like 0 rather than like a
percentage value? (e.g., if it's the only non-spanning percentage in a
column that has a spanning cell with a percentage width?)

Intrinsic widths of auto layout tables

This specification currently defines the intrinsic
widths of tables (including inline-tables) as a parameter of the table
excluding its caption, but the outer
intrinsic widths of tables
as a parameter of the table including its caption. This
distinction is needed because the intrinsic widths exclusive of the
caption are critical to the final table layout algorithm. However, it
may be better to have a separate term for these parameters rather than
overloading these existing terms by adding this strange distinction.

The intrinsic minimum width of a table or inline table is the sum of
the intrinsic minimum widths of the columns and the total horizontal border spacing of the
table.

the small percentage contribution of each of the columns, where
the small percentage contribution of a column is defined as the
ratio of

the column's intrinsic preferred width to

its intrinsic percentage width (where 100% == 1.0)

This ensures that cells, columns, or column
groups with small percentage widths have those percentage
widths satisfied when possible.

the large percentage contribution of the table, which is the
ratio of

the sum of the intrinsic preferred widths of all the
columns whose intrinsic percentage width is zero to

100% (1.0) minus the sum of the intrinsic percentage widths of
the columns,

unless the denominator of that ratio is 0, in which case it is 0 if
the numerator is also 0, and an infinitely large number if the
numerator is nonzero
This ensures that cells, columns, or column
groups with large percentage widths have those percentage
widths satisfied when possible.It would be nice to prove that there's no need
to iterate over the columns separately. I think this is true
because in such cases the small percentage effect would win.

Computing column widths

When a table is laid out at a given used width, the used width of
each column is determined as follows.

Define the assignable width as the used width of the table
minus the total horizontal border spacing.

Define the small guess as the set of column width
assignments where:

columns whose intrinsic percentage width is nonzero are assigned
the assignable width times their intrinsic percentage width, and

If the assignable width is less than or equal to the small guess,
the used width of each column is its width in the small guess minus the
product of:

the difference between the small guess and the assignable width and

the ratio of the column's intrinsic percentage width to the sum of
the intrinsic percentage widths of all columns (or zero if this ratio is
undefined).

If the assignable width is greater than the small guess and less
than to the large guess, the used width of each column is its width in
the small guess plus the product of:

the difference between its width in the large guess and its width in
the small guess

the difference between the sum of the widths assigned in the large
guess and the sum of the widths assigned in the small guess

If the assignable width is greater than or equal to the large guess,
then:

If there is at least one column (a column allowed to grow by this
rule) that is not constrained, has a zero intrinsic percentage width,
and a nonzero intrinsic preferred width, then the used width of each
column is its width in the large guess plus:

for columns not allowed to grow by this rule, zero, or

for columns allowed to grow by this rule, the product of:

the difference between the assignable width and the sum of the
widths assigned in the large guess, and

the ratio of the column's intrinsic preferred width to the sum of
the preferred widths of all columns allowed to grow by this rule.

Otherwise, if there is at least one column (a column allowed to grow
by this rule) that has a nonzero intrinsic percentage width, then the
used width of each column is its width in the large guess plus:

for columns not allowed to grow by this rule, zero, or

for columns allowed to grow by this rule, the product of:

the difference between the assignable width and the sum of the
widths assigned in the large guess, and

the ratio of the column's intrinsic percentage width to the sum of
the percentage widths of all columns allowed to grow by this rule.

Otherwise, the used width of each column is its width in the large
guess plus the ratio of:

the difference between the assignable width and the sum of the
widths assigned in the large guess, and

the number of columns in the table.

Fixed Table Layout

Intrinsic widths of fixed layout tables

The intrinsic minimum width of a fixed layout table is the total horizontal border spacing of the
table plus the specified non-percentage widths on any columns and the
specified non-percentage widths (plus the cell intrinsic offset, and
divided by the number of spanned columns) on any cells in the first row
of any columns whose width is 'auto'.

This algorithm doesn't work very well if a cell in the
first row spans some columns with specified widths and some without.

Should a percentage width cell spanning columns with
unspecified width cause the border-spacing that it spans to be
subtracted from the intrinsic minimum width?

The intrinsic preferred width of a fixed layout table is infinitely
large. This is compatible with existing
implementations but not particularly useful. If it were changed, the
rules for the computation of the width of a table would need to be
changed to ignore it for fixed layout tables.

Outer intrinsic widths of tables

Does this all make sense for table-layout:fixed?

The outer intrinsic minimum width of the non-caption part of tables
and inline tables is defined to be the sum of max('min-width', the
intrinsic minimum width of the table, min('width', 'max-width')) and the
table intrinsic offset.

The outer intrinsic minimum width of tables and inline-tables with
'caption-side: top' or 'caption-side: bottom' is
defined to be the larger of:

Define the outer intrinsic minimum width of tables and
inline-tables with 'caption-side: left' or 'caption-side: right'.

The outer intrinsic preferred width of the non-caption part of tables
and inline tables is defined to be the sum of max('min-width',
min-intrinsic, min('width', 'max-width', intrinsic)) and the table intrinsic offset.

The outer intrinsic preferred width of tables and inline-tables with
'caption-side: top' or 'caption-side: bottom' is
defined to be the larger of:

Define the outer intrinsic preferred width of tables and
inline-tables with 'caption-side: left' or 'caption-side: right'.

Computing cell widths

Define how to compute used cell widths from column
widths, column-span, border-spacing, and border and padding
properties.

Computing table widths

Define how the used width of a table is computed from
the available width, its intrinsic widths, and the computed values of
the width properties. This gets complicated with side captions, and
with the differences in offsets between border models. But ignoring
those, the basic idea is the same as the shrink-to-fit width that CSS2.1
defines for floating, non-replaced elements or for absolutely
positioned, non-replaced elements.