10 Visual formatting model details

This is derived from the September 2003 CSS2.1 Last Call Working Draft. Only modified sections are presented here.

10.2 Content width: the 'width' property

...

Values have the following meanings:

<length>
Specifies the width of the content area using a length unit.
<percentage>
Specifies a percentage width. The percentage is calculated with respect to the width of the generated box's containing block. If the containing block's width depends on this element's width, then the resulting layout is undefined in CSS 2.1. Note: For absolutely positioned elements whose containing block is based on a block-level element, the percentage is calculated with respect to the width of the padding box of that element. This is a change from CSS1, where the percentage width was always calculated with respect to the content box of the parent element.
auto
The width depends on the values of other properties. See the sections below.

In some cases, a "shrink-to-fit" width is used. This is similar to calculating the width of a table cell using the automatic table layout algorithm, but CSS 2.1 does not define the exact algorithm. Roughly: calculate the preferred width by formatting the content without breaking lines other than where explicit line breaks occur, and also calculate the preferred minimum width, e.g., by trying all possible line breaks. Thirdly, calculate the available width by applying the given horizontal constraints. The shrink-to-fit width is: min(max(preferred minimum width, available width), preferred width).

Negative values for 'width' are illegal.

Example(s):

For example, the following rule fixes the content width of paragraphs at 100 pixels:

p { width: 100px }

10.3 Calculating widths and margins

...

10.3.3 Block-level, non-replaced elements in normal flow

The following constraints must hold between the used values of the other properties:

'margin-left' + 'border-left-width' + 'padding-left' + 'width' + 'padding-right' + 'border-right-width' + 'margin-right' = width of containing block

If all of the above have a computed value other than 'auto', the values are said to be "over-constrained" and one of the used values will have to be different from its computed value. If the 'direction' property has the value 'ltr', the specified value of 'margin-right' is ignored and the value is calculated so as to make the equality true. If the value of 'direction' is 'rtl', this happens to 'margin-left' instead.

If there is exactly one value specified as 'auto', its used value follows from the equality.

If 'width' is set to 'auto', any other 'auto' values become '0' and 'width' follows from the resulting equality.

If both 'margin-left' and 'margin-right' are 'auto', their used values are equal. This horizontally centers the element with respect to the edges of the containing block.

...

10.3.5 Floating, non-replaced elements

If 'margin-left', or 'margin-right' are computed as 'auto', their used value is '0'.

If 'width' is computed as 'auto', the used value is the "shrink-to-fit" width the shrink-to-fit width using the block-level non-replaced rules to calculate the available width.

...

10.3.7 Absolutely positioned, non-replaced elements

For the purposes of this section and the next, the term "static position" (of an element) refers, roughly, to the position an element would have had in the normal flow. More precisely:

But rather than actually calculating the dimensions of that hypothetical box, user agents are free to make a guess at its probable position.

For the purposes of calculating the static position, the containing block of fixed positioned elements is the initial containing block instead of the viewport.

The constraint that determines the used values for absolutely-positioned these elements is:

'left' + 'margin-left' + 'border-left-width' + 'padding-left' + 'width' + 'padding-right' + 'border-right-width' + 'margin-right' + 'right' = width of containing block

The solution to this constraint is reached through a number of substitutions in the following order.

  1. If 'left' and 'right' are 'auto' while 'direction' is 'ltr', set 'left' to the static position.
  2. If 'left' and 'right' are 'auto' while 'direction' is 'rtl', set 'right' to the static position.
  3. If any of 'width', 'left', or 'right' is 'auto', set any 'auto' values for 'margin-left' and 'margin-right' to 0.
  4. If 'width' and either 'left' or 'right' are 'auto', the width is shrink-to-fit, with the available width calculated by substituting 0 for the remaining 'auto' position and solving the constraint equation above.
  5. If at this point the values are overconstrained, set either 'left' (in case 'direction' is 'rtl') or 'right' (in case 'direction' is 'ltr') to 'auto'.
  6. If both 'margin-left' and 'margin-right' are still 'auto', solve the equation under the extra constraint that the two margins must get equal values.
  7. If there is an 'auto' value left, solve the equation for that value.

If all three of 'left', 'width', and 'right' are 'auto': First set any 'auto' values for 'margin-left' and 'margin-right' to 0. Then, if 'direction' is 'ltr' set 'left' to the static position and apply rule number three below; otherwise, set 'right' to the static position and apply rule number one below.

If none of the three is 'auto': If both 'margin-left' and 'margin-right' are 'auto', solve the equation under the extra constraint that the two margins get equal values. If one of 'margin-left' or 'margin-right' is 'auto', solve the equation for that value. If the values are over-constrained, ignore the value for 'left' (in case 'direction' is 'rtl') or 'right' (in case 'direction' is 'ltr') and solve for that value.

Otherwise, set 'auto' values for 'margin-left' and 'margin-right' to 0, and pick the one of the following six rules that applies.

  1. 'left' and 'width' are 'auto' and 'right' is not 'auto', then the width is shrink-to-fit. Then solve for 'left'
  2. 'left' and 'right' are 'auto' and 'width' is not 'auto', then if 'direction' is 'ltr' set 'left' to the static position, otherwise set 'right' to the static position. Then solve for 'left' (if 'direction is 'rtl') or 'right' (if 'direction' is 'ltr').
  3. 'width' and 'right' are 'auto' and 'left' is not 'auto', then the width is shrink-to-fit . Then solve for 'right'
  4. 'left' is 'auto', 'width' and 'right' are not 'auto', then solve for 'left'
  5. 'width' is 'auto', 'left' and 'right' are not 'auto', then solve for 'width'
  6. 'right' is 'auto', 'left' and 'width' are not 'auto', then solve for 'right'

Calculation of the shrink-to-fit width is similar to calculating the width of a table cell using the automatic table layout algorithm. Roughly: calculate the preferred width by formatting the content without breaking lines other than where explicit line breaks occur, and also calculate the preferred minimum width, e.g., by trying all possible line breaks. CSS 2.1 does not define the exact algorithm. Thirdly, calculate the available width: this is found by solving for 'width' after setting 'left' (in case 1) or 'right' (in case 3) to 0.

Then the shrink-to-fit width is: min(max(preferred minimum width, available width), preferred width).

...