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.
Comments on this draft should be sent to the public mailing list www-style@w3.org (Archive) or to the author.
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).
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 (on 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.
A cell is said to originate in a column if, when the 'direction' of the table is 'ltr' ('rtl'), the column is the leftmost (rightmost) column that the cell spans. (Cells with a 'column-span' of '1' are considered to originate in their only column.)
The function min() is defined as the function that returns the smallest of its arguments, and the function max() is defined as the function that returns the largest of its arguments. When one of those arguments is an 'auto' value for 'width', it should be treated as 0 when in max() and (positively) infinite when in min(). Likewise, a 'none' value for 'max-width' should be treated as (positively) infinite.
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 preferred 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.
Absolutely positioned elements never contribute to containing block's intrinsic widths.
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.
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:
Adjusting an intrinsic width for the content edge, padding edge, or border edge of a box to add horizontal padding (if content edge), border (if content edge or padding edge), and margin involves the following steps:
Note that the handling of percentage padding and margin is not very interoperable in today's browsers.
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:
The outer intrinsic preferred width of blocks and inline-blocks is defined to be the following:
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.
Define preferred intrinsic width of an inline formatting context. Ditto.
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.
The cell intrinsic offsets is a term to capture the parts of padding and border of a table cell that are relevant to intrinsic width calculation. It is a set of computed values for border-left, padding-left, padding-right, and border-right defined as follows:
border-collapse
: separate
, the horizontal padding and
borderborder-collapse
: collapse
, the computed padding values
of the cell, and for border values, half the width of
the winning left border for the cell (the largest winning left
border for a row-spanning cell) and 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.
The table intrinsic offsets is a term to capture the parts of the padding and border of a table that are relevant to intrinsic width calculation. It is a set of computed values for border-left, padding-left, padding-right, and border-right defined as follows:
border-collapse
: separate
, the computed padding and
border valuesborder-collapse
: collapse
, padding values of zero, and
border values that are 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 offsets because handling of margins depends on the 'caption-side' property. But doesn't that break handling of percentage padding?
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 in which cells originateThe 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 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.
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. Rewrite!
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 ought to be a separate parameter of the column (though how it interacts with the intrinsic minimum width would need to be defined).
the largest of:
the largest of:
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)
the largest of the intermediate intrinsic minimum width for span N-1 and the contributions of the cells in the column whose 'column-span' property has computed value N, where the contribution of a cell is the result of taking the following steps:
the largest of the intermediate intrinsic preferred width for span N-1 and the contributions of the cells in the column whose 'column-span' property has computed value N, where the contribution of a cell is the result of taking the following steps:
If the intermediate intrinsic percentage width for span N-1 is greater than 0%, then the intermediate intrinsic percentage width for span N is the same as the intermediate intrinsic percentage width for span N-1.
Otherwise, it is the largest of the contributions of the cells in the column whose 'column-span' property has computed value N, where the contribution of a cell is the result of taking the following steps:
the intermediate intrinsic minimum width for span N, where N is the number of columns in the table
the intermediate intrinsic preferred width for span N, where N is the number of columns in the table
the smaller of:
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.
A column is constrained if the column group (if any), the column (if any), or any of the cells in the column has a computed 'width' that is not 'auto', and is not a percentage. Do we need intermediate constrainedness? It's easier to implement that way, but does it actually make any difference?
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?)
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 intrinsic preferred width of a table or inline table is the sum of the total horizontal border spacing of the table and the largest of:
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 minimum guess as the set of column width assignments where each column is assigned its minimum width.
Define the minimum-percentage guess as the set of column width assignments where:
Define the minimum-specified guess as the set of column width assignments where:
Define the preferred guess as the set of column width assignments where:
Note that the assignable width is greater than or equal to the table width using the minimum guess, and that the widths for each column in the four guesses (minimum guess, minimum-percentage guess, minimum-specified guess, and preferred guess) are in nondecreasing order.
If the assignable width is less than or equal to the preferred guess, the used widths of the columns are the linear combination (with weights adding to 1) of the two guesses whose width sums bound the available width.
Otherwise, if there are unconstrained columns with intrinsic percentage width of 0% and with nonzero intrinsic preferred width (columns allowed to grow by this rule), the used widths of the columns are the widths given in the preferred guess plus, for columns allowed to grow by this rule, the extra space in the assignable width distributed in proportion to preferred width.
Otherwise, if there are (constrained) columns with intrinsic percentage width of 0% and with nonzero intrinsic preferred width (columns allowed to grow by this rule), the used widths of the columns are the widths given in the preferred guess plus, for columns allowed to grow by this rule, the extra space in the assignable width distributed in proportion to preferred width.
Otherwise, if there are columns with intrinsic percentage width greater than 0% (columns allowed to grow by this rule), the used widths of the columns are the widths given in the preferred guess plus, for columns allowed to grow by this rule, the extra space in the assignable width distributed in proportion to intrinsic percentage width.
Otherwise, the used widths of the columns are the widths given in the preferred guess plus the extra space in the assignable width distributed equally to all columns.
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 (adjusted by the cell intrinsic offsets, 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.
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 max('min-width', the intrinsic minimum width of the table, min('width', 'max-width')) adjusted by 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 max('min-width', min-intrinsic, min('width', 'max-width', intrinsic)) adjusted by 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'.
Define how to compute used cell widths from column widths, column-span, border-spacing, and border and padding properties.
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, except that a specified width is just a lower bound.
This section proposes adding four new values to the 'width', 'max-width', and 'min-width' properties:
I'm not a big fan of the 'intrinsic' and 'min-intrinsic' names. Improvements welcome.
As for 'width: auto' and 'max-width: none', changing the value of 'box-sizing' should not change the behavior of these values.
Note that 'width: shrink-wrap' is the same as 'width: auto' for floats and tables, and 'width: fill' is the same as 'width: auto' for blocks in the normal flow.
When computing outer intrinsic widths, the 'fill' value on all properties and the 'shrink-wrap' value on the 'width' property behave exactly like the default value for the property ('width: auto', 'max-width: none', 'min-width: 0').
On table columns and table column groups, all values behave like the default value of the property ('width: auto', 'max-width: none', 'min-width: 0').
These values were implemented in Mozilla, with -moz- prefixes, in bug 311415.
Some testcases are available at http://dbaron.org/css/test/intrinsic/, but more need to be developed. The examples at http://dbaron.org/css/test/2004/intrinsic/ and http://dbaron.org/css/test/2006/intrinsic-examples/ were also useful in developing this specification.
Tests for the new values for 'width',
'max-width', and 'min-width' are available in the Mozilla source
tree in the filenames width-special-values-*
and
box-sizing-*
in the directory layout/reftests/box-properties.
The file reftest.list
in that directory gives the pass
conditions.