CSS3 module: the box model

W3C Working Draft, 26 July 2001

This version:
http://www.w3.org/TR/2001/WD-css3-box-20010726
Latest version:
http://www.w3.org/TR/css3-box
Previous version:
-
Editors:
Bert Bos (W3C), <Bert@w3.org>

Abstract

CSS (Cascading Style Sheets) describe the rendering of documents on various media. When textual documents (e.g., HTML, WML) are laid out on visual media (e.g., screen, paper), CSS represents the elements of the document by rectangular boxes that are laid out one after the other or nested inside each other in an ordering that is called a flow. This module describes the characteristics of the flow and of the various kinds of boxes.

The flow described here includes "floating" boxes, but the layout inside tables [[CSS3-tables]] and inside boxes that result from "absolute" or "fixed" positioning[link] is described in other modules. Also, the rules for partitioning a flow into pages (for paged media) is described elsewhere[link], as are the special for Ruby annotations [[CSS3-ruby]] and the boxes for multicolumn layouts [reference].

The box model builds on the inline text model (see the CSS3 Text module [CSS3-text]), that describes how text is laid out on a line, including treatment of superscripts and bidirectional ("bidi") text.

The flow can be horizontal (typical for most languages), but in level 3 of CSS, flows can also be vertical (typical for the Uighur script and often used for ideographic scripts).

Status of this document

This is a draft of a module of CSS level 3. It should eventually become a CSS3 Recommendation, most likely as a chapter in a larger set of modules.

Some of the sections, such as the sections on recognition and behavior of hyperlinks and the 'content' property, are likely to be moved to other CSS3 modules, or become modules on their own.

All the properties and features described here that also exist in CSS level 2 are intended to be backwards compatible, except in very rare cases that are explicitly marked. There is a small number of new properties, mostly to deal with vertical writing, and some properties from CSS2 have become shorthand properties for more detailed new ones in CSS3.

This draft should not be cited except as "work in progress." It is a work item of the CSS working group which is part of the Style activity. It may be modified or dropped altogether at any point in time. Implementations for the purpose of experimenting with the specification are welcomed, as long as they are clearly marked as experimental.

Feedback on this draft is invited. The preferred place for discussion of this draft is the public, archived mailing list www-style@w3.org.

To find the latest version of this working draft, please follow the "Latest version" link above, or visit the list of W3C Technical Reports.

Table of contents


1. Dependencies on other modules

This CSS3 module depends on the following other CSS3 modules:

[I think syntax/grammar, values/units?]

It has non-normative (informative) references to the following other CSS3 modules:

2. Notations used in this specification

Each property is introduced by a table summarizing its usage. See [where? Introduction?] for an explanation. The values 'inherit' and initial, that occur in each table, are explained in [where? Cascading module?]

Note that non-normative notes generally start with the word "note" and are rendered like this paragraph.

Examples look like this.

3. Introduction and glossary

The formatting model of CSS for visual media is based on a "flow" of rectangular "boxes," that are either juxtaposed or nested, according to certain rules. There are several kinds of boxes (block boxes, inline boxes, table boxes, floating boxes,...). Properties such as 'margin' and 'float' can modify the position of a box within its parent to a certain extent.

Typically, an element in the source document corresponds to a box on the display, but sometimes an element has more than one box (e.g., a list item and its bullet, or a box that is broken over two lines), and sometimes there is no box at all (if the rendering has been suppressed with the property 'display: none'). Conversely, every box either belongs to a single element in the source, or it is an "anonymous" box that belongs to no element but is created by the rules in the style sheet (but then it indirectly belongs to the element that its parent box belongs to). This relation is important for interactive presentations, including WYSIWYG editors, because every event on a box, such as a mouse click, can unambiguously be linked to a specific element in the document source.

Schematic representation of rel

Relation between 4 displayed boxes in the rendered document (on the right) and the 3 corresponding elements in the source document on the (left).

CSS level 3 supports three orientations of flows: horizontal, vertical and vertical-lr. Horizontal flow has horizontal text and the flow grows downwards. This is the typical flow for most languages, e.g., English, Greek or Arabic. Vertical flow has vertical text and the flow grows to the left. This orientation is often used in Japanese and Chinese. Vertical-lr flow also has vertical text, but the flow grows to the right ("lr" = "left to right"). This is the typical orientation for the Uighur script, one of the scripts used for Mongolian. Horizontal flow that grows upwards is not supported, and neither are diagonal flows or complex shapes (spirals, zigzag,...). Such texts can usually be achieved with a combination of [SVG1.0] and CSS. The orientation of a flow is set (indirectly) with the 'writing-mode' shorthand property.

CSS (levels 2 and 3) also supports bidirectionality: text that is partly written from left to right and partly from right to left. Arabic and Hebrew are examples of languages that need bidirectionality. In level 3, bidirectionality also works in vertical flows: most text would be written top to bottom, but Arabic and Hebrew would mostly be bottom to top. The 'direction' property sets the direction, or it can be set with the 'writing-mode' shorthand property. Bidirectionality is not described in this module, but in the Text module [CSS3-text].

Boxes have a content with a certain width and height (which can often be set explicitly with the 'width' and 'height' properties). Around that can be an optional area called the padding (the thickness of which is controlled with the 'padding' property; '0' means no padding). Around the padding can be a border (controlled by the 'border' property). Finally, boxes also have a margin around the border (specified with the 'margin' property). The outside edges of these areas are called content edge, padding edge, border edge and margin edge respectively. When we talk about the width/height of a box, we mean the width/height of the content area, unless otherwise specified.

Diagram of a typical box, showing the content, padding, border
and margin areas

The various areas and edges of a typical box

Here are some definitions (the values of the properties refer to the computed values [reference]):

root box, root element
The box resp. element that has no parent box resp. element. The root element of the source document generates the root box.
positioned box, positioned element
A box resp. element whose 'display-role' property is not 'none' and whose 'position' property is either 'absolute' or 'fixed'. A positioned element generates a positioned box. Note that 'position' does not apply to the root element.
floating box, floating element
A box resp. element whose 'display-role' property is not 'none', whose 'position' property is either 'static' or 'relative' and whose 'float' property is not 'none'. A floating element generates a floating box. Note that 'position' and 'float' do not apply to the root element.
normal-flow box, normal-flow element
A box resp. element whose 'display-role' property is not 'none', whose 'position' property is 'static' or 'relative', whose 'float' property is 'none' and whose orientation is the same as its parent's. The root box resp. element is also a normal-flow box resp. element.
block-level box, block-level element
Informally: an element that creates a block whose width is determined by its parent, not by its content. Formally: a normal-flow box resp. element whose 'display-role' property is 'block', 'list-item', 'run-in' (under certain conditions) or 'compact' (under certain conditions). See the 'display-role' property for when 'run-in' and 'compact' are rendered as block-level boxes.
inline-level box, inline-level element
Informally: an element that is rendered inside a line box. Formally: a normal-flow box resp. element whose 'display-role' property is 'inline', 'marker', 'run-in' (under certain conditions) or 'compact' (under certain conditions). See the 'display' property for when 'run-in' and 'compact' are rendered as inline-level boxes.
flow root
A box (or element) that is either the root box, a positioned box, a floating box, a block-level box that has a different orientation than its parent, or else an inline-level box with 'display-model' set to 'flow' or a box with 'display-role' set to 'table-cell' or 'table-caption'. It is called a "flow root," because it is the root of a flow.
flow, normal flow
A flow consists of a flow root box with all its children that are normal-flow boxes, plus all their children that are normal-flow boxes, etc., recursively. The word "normal flow" is sometimes used as a synonym for flow.
horizontal flow
A flow with horizontal text, i.e., whose flow-root has a horizontal orientation (see 'writing-mode').
vertical flow
A flow with vertical text, i.e., whose flow-root has vertical or vertical-lr orientation (see 'writing-mode').
orientation
The orientation of an element. An element can have one of three orientations:
containing block (of an element)
The containing block of a normal-flow element or of a floating element is the content area of the nearest ancestor that is either a flow root or a block-level element.
The containing block of a positioned element is the padding area of the nearest ancestor that is a flow root. [Check this with Position module.]

Note that if this nearest ancestor has columns, the containing block is a column. See the multicolumn module[ref].

intrinsic size, intrinsic width, intrinsic height
[Probably need to define a "minimum intrinsic width" as well as an "(optimum) intrinsic width", like in the algorithm for automatic table size.]
The width & height that an element has "naturally," i.e., without outside constraints. We don't define where the intrinsic size of replaced elements comes from, but we assume there is one. (For raster images, it is typically the size in pixels; for vector graphics, the design size.)
The intrinsic width of a non-replaced element in a horizontal flow is found as follows: set 'display' to 'block' and find the minimum width such that increasing the width (1) does not lead to a different number of line breaks and (2) does not decrease the number of child elements that overflow (see 'overflow'). The intrinsic height is the box's height at that width. Vertical flow is analogous, but find the minimum height and the corresponding width. The intrinsic size of elements with a 'display' value that is not defined by this specification should be defined in the specification that defined that value.
The intrinsic size of non-replaced elements is used, e.g., to determine when a 'compact' element is rendered as a block, or what the optimal size of a table is.
link element
An element that is the source anchor of a link. See the '@link' rule and the 'collapse' property.
replaced element
A link element whose 'content' property is 'link'. (Informally: an element whose content is not rendered by the box model of this chapter. The prime example is an image, i.e., a link in the source document that is replaced by the image that it points to; hence the name.)
line box
Sequences of inline-level elements are laid out one after the other, aligned on their baselines and broken over several lines according to the rules for line breaking and text alignment. Each resulting line is wrapped in a box that is called the line box and whose height is determined from the various 'line-height' and 'line-box-contain' properties of each of the boxes on the line. Line boxes are then stacked together with no intervening margins to form the content of a block-level box. See the Line box model [CSS3-linebox].
nominal font (of an element)
The first font in the list of fonts of the 'font' property for which the UA can determine the position of the element's dominant baseline (see 'dominant-baseline') in the font's em-box.

Note that this usually means that the UA actually has that font. Note also that the nominal font need never actually appear, e.g., if the element has no textual content.

anonymous inline element
If an element with a 'display-model' of 'flow' contains text (that is not inside a child element and that is not white space that can be collapsed), all uninterrupted sequences of such text are anonymous inline elements. "Anonymous" means more than "no name": it means the elements cannot be selected, not even with the universal selector (*), and thus all their properties are either inherited or set to their initial values. In particular 'display' is set to 'inline'.
anonymous block element
If an element has child elements with a 'display-role' of 'inline' as well as child elements with other 'display-role' values (except 'none'), then every sequence of elements with 'inline' (including anonymous inline elements) is considered to be contained inside an anonymous block element. Such elements do not affect the matching of selectors and they themselves cannot be selected, but they help to explain the box model. [Actually, it doesn't, since this gloss is not referenced anywhere. Check whether it can be removed.]

Here is an example of anonymous inline elements.

<P>This is a <EM>short</EM> paragraph</P>

Assume that P has 'display: block' (which implies 'display-model: flow') and that EM has 'display: inline' (implying 'display-model: inline'), then the two texts "This is a" and "paragraph" are anonymous inline elements. The text "short" is not an anonymous inline element, because the EM itself is already inline.

4. The 'display', 'display-model' and 'display-role' properties

Name: display-model
Value: inline-inside | block-inside | table | ruby | inherit | initial
Initial: text
Applies to: all elements
Inherited: no
Percentages: N/A
Media: visual
Computed value specified value (except for 'inherit' and 'initial')
Name: display-role
Value: none | block | inline | list-item | marker | run-in | compact | table-row | table-cell | table-row-group | table-header-group | table-footer-group | table-column | table-column-group | table-caption | ruby-text | ruby-base | ruby-base-group | ruby-text-group | inherit | initial
Initial: inline
Applies to: all elements
Inherited: no
Percentages: N/A
Media: visual
Computed value specified value (except for 'inherit' and 'initial')
Name: display
Value: inline | block | inline-block | list-item | run-in | compact | marker | table | inline-table | table-row-group | table-header-group | table-footer-group | table-row | table-column-group | table-column | table-cell | table-caption | ruby | ruby-base | ruby-text | ruby-base-group | ruby-text-group | none | inherit | initial
Initial: inline
Applies to: all elements
Inherited: no
Percentages: N/A
Media: visual ('none' applies to all)
Computed value see individual properties

The 'display-model' property determines the algorithm with which an element lays out its children, 'display-role' specifies what role an element has in its parent's algorithm, and 'display' is a shorthand for the most common combinations of the two.

The equivalence between 'display', 'display-model' and 'display-role' is as follows:

inline-inside block-inside table ruby
none** none none none none
inline inline inline-block inline-table ruby
block *** block table ??
list-item *** list-item * ??
marker marker * * *
run-in run-in * * *
compact compact * * *
table-cell *** table-cell * ??
table-caption *** table-caption * ??
table-row-group** table-row-group
table-header-group** table-header-group
table-footer-group** table-footer-group
table-column** table-column
table-column-group** table-column-group
table-row** table-row
ruby-base** ruby-base
ruby-text** ruby-text
ruby-base-group** ruby-base-group
ruby-text-group** ruby-text-group

*) this combination can be made only by setting 'display-role' and 'display-model'; there is no shorthand for 'display'

**) 'display-model' is ignored for this value of 'display-role'

***) this combination cannot be made with 'display', but note that the effect is the same as with 'display-model' set to 'block-inside', which can be made with 'display'

The values of 'display-model' have the following meaning. (For ease of reading, we describe only horizontal flow.)

math
The content of the element is rendered according to the rules of the Math module [link].
table
See the Tables module [[CSS3-tables]].
ruby
See the Ruby module [[CSS3-ruby]].
inline-inside
If this is not an inline-level element, the effect is the same as for 'block-inside'. Otherwise the element's inline-level children and text sequences that come before the first block-level child are rendered as additional inline boxes for the line boxes of the containing block. Ditto for the text sequences and inline-level children after the last block-level child. The other children and text sequences are rendered as for 'block-inside'.
block-inside
Child elements are rendered as described for their 'display-role'. Sequences of inline-level elements and anonymous inline elements (ignoring elements with a display-role of 'none') are rendered as one or more line boxes. (How many line boxes depends on the line-breaking rules, see the Text module [[CSS3-text].)

Note that an element with 'display-model' of 'flow' may contain anonymous inline elements. For example, the texts "Your" and "or your" are anonymous inline elements of this paragraph:

<p>
Your <em>money</em> or your <em>life!</em>
</p>

The difference between 'inline-inside' and 'block-inside' is subtle. It is best illustrated with the difference between inline elements and inline-block elements. Assume the following document:

<p>The two words <span>two words</span> appear twice in this para.</p>

Further assume the following style sheet:

p    { display-model: block-inside }
span { display-role: inline; display-model: inline-inside }

The second line is equivalent to (and would usually be written as) 'span {display: inline}'. The rendering might look like this:

Element rendered inline

The 'display-model' of the span is 'inline-inside' and the contents thus appear as part of the line.

If the 'display-model' of the span is changed to 'block-inside' (i.e., equivalent to 'span {display: inline-block}'), and we further set the 'width' to an appropriate value, e.g.:

p    { display-model: block-inside }
span { display-role: inline; display-model: block-inside;
       width: 2.5em}

then the rendering will become like this:

Element rendered as inline block

The 'display-model' of the span is 'block-inside' and the contents thus appear as a block.

The values of 'display-role' have the following meaning. (Where we talk about "next element," we ignore any intervening elements with 'display-role: none'.) The descriptions assume horizontal flow for easier reading, but vertical flow is analogous.

none
The element is not rendered. The rendering is the same as if the element had been removed from the document tree, except for possible effects on counters (see [generated] or [paged]).

Note that :before and :after pseudo elements of this element are also not rendered, see [generated].)

run-in
The effect depends on what comes after the element. If the next element (in the depth-first, left to right tree traversal, so not necessarily a sibling) has a 'display-model' of 'flow', the current element will be rendered as if it had display-role 'inline' and was the first child of that block element. Otherwise this element will be rendered as if it had display-role 'block'.
compact
The effect depends on the intrinsic size of this element and on what comes after it. If the next element has a 'display-role' of 'block', and the intrinsic width of the compact element is less than or equal to the left margin of that block (resp. the right margin, if the block's 'direction' is 'rtl'), then the compact element is rendered in the left (right) margin of the block at its intrinsic size and baseline aligned with the first line box of the block. [Do we need a different alignment depending on script?] In all other cases the compact element is rendered as if its display-role was 'block'.
marker
If the parent element does not have a display-role of 'list-item' or 'block' (including 'run-in' and 'compact' that are rendered as 'block'), the marker element is rendered as if its display-role was 'inline'. Otherwise, the element is rendered at its intrinsic size and in its parent's left margin (right margin, if the parent has 'direction' 'rtl'), at a distance 'marker-offset' from the content edge, and baseline aligned with the parent's first line box. [Should we change this to border edge? That avoids markers overlapping with borders or with floats, but it is different from what CSS2 says.]
list-item
The element is rendered the same as if it had display-role 'block', but in addition a marker is generated (see 'list-style'). The marker is not generated if the element has a child with display-role 'marker'.

Note that this requires the renderer to look ahead in the source document to find a possible child with a 'display-role' of 'marker'. However, since the marker doesn't change the position of the list item, the renderer can still continue rendering progressively. It might also generate a marker tentatively and overwrite it later, if needed, or postpone drawing the marker until the end of the element.

block
The element is rendered as a rectangular block. See Collapsing margins for its position relative to earlier boxes in the same flow. In paged media [ref] or inside another element that has two or more columns, the box may be split into several smaller boxes.
inline
The element is rendered inside a line box. It may be split into several boxes because of line breaking and bidi processing (see the Text module).
table-...
See the Tables module [[CSS3-tables]].

Note that in CSS2, 'marker' could only occur as the display-role of a ':before' pseudo-element; in CSS3, real elements can be 'marker', too. [Is this true?]

The computed value of 'display-role' is influenced by the 'float' property (and, in case the Positioning module [CSS3-positioning] is in use, also by 'position'):

(As usual, the above holds after processing 'inherit' and 'initial'.)

[Add an elaborate illustration showing line boxes, block elements, margins between them, a marker, etc.]

Here is an HTML example with various types of boxes:

<style type="text/css">
  h3 { display: run-in; margin: 1em 0 }
  h3:after { content: ". " }
  p { display: block; margin: 1em 0 }
  img { display: block; margin: 0.5em }
  span { display: inline-block; padding: 0.6em;
    font-size: 70%; vertical-align: middle }
</style>
<h3>First heading</h3>
<h3>Second heading</h3>
<p>This paragraph has an image that is displayed as a block:
  <img src="w3c_home" ALT="W3C">
  and also an inline-block:
  <span>
    This element<br>
    has two lines
  </span>

A possible rendering is as follows:

Possible rendering

Possible rendering of the example HTML document

Possible rendering with explanations

Rendering with explanations

The first H3 was not rendered inline, because it was not followed by a block. The top and bottom margin that was set on H3 only apply when the element is rendered as a block.

4.1. Mixing flow layout with other layouts

In documents formats that combine different layout models (e.g., a format that combines SVG with HTML in a single document), it may be necessary to introduce additional values for 'display-model', for the layout models that are not defined by CSS3. It is up to the specification of such formats to define appropriate keywords.

[Do we recommend a naming scheme?]

5. The 'padding' properties

Name: padding
Value: [ <length> | <percentage> ]{1,4} | inherit | initial
Initial: (see individual properties)
Applies to: all elements
Inherited: no
Percentages: width* of containing block
Media: visual
Computed value see individual properties
*) if the containing block is 'horizontal', otherwise the height
Name: padding-top , padding-right, padding-bottom, padding-left
Value: [ <length> | <percentage> ] | inherit | initial
Initial: 0
Applies to: all elements
Inherited: no
Percentages: width* of containing block
Media: visual
Computed value <length>
*) if the containing block is 'horizontal', otherwise the height

Sets the thickness of the padding around a box. The value may not be negative. The color/pattern of the element's background extends into the padding. See the 'background' property.

'Padding' is a shorthand that sets the four other properties at the same time. If 'padding' has 4 values, they are for top, right, bottom and left in that order. If left is omitted, it is the same as right. If bottom is omitted it is the same as top, if right is omitted it is the same as top.

When the padding is 0, we say that the padding is absent.

Note that percentages on 'padding-top' and 'padding-bottom' are relative to the width of the containing block, not the height (at least in a horizontal flow; in a vertical flow they are relative to the height).

6. The 'border' properties

Name: border-top-color , border-right-color, border-bottom-color, border-left-color
Value: <color> | transparent | inherit | initial
Initial: the value of the 'color' property
Applies to: all elements
Inherited: no
Percentages: N/A
Media: visual
Computed value <color> or 'transparent'
Name: border-top-style , border-right-style', border-bottom-style, border-left-style
Value: <border-style> | inherit | initial
Initial: none
Applies to: all elements
Inherited: no
Percentages: N/A
Media: visual
Computed value specified value, except for 'inherit' and 'initial'
Name: border-top-width , border-right-width, border-bottom-width, border-left-width
Value: <length> | thin | medium | thick | inherit | initial
Initial: medium
Applies to: all elements
Inherited: no
Percentages: N/A
Media: visual
Computed value specified value, except for 'inherit' and 'initial'
Name: border-style
Value: <border-style>{1,4} | inherit | initial
Initial: (see individual properties)
Applies to: all elements
Inherited: no
Percentages: N/A
Media: visual
Computed value see individual properties
Name: border-width
Value: <border-width>{1,4} | inherit | initial
Initial: (see individual properties)
Applies to: all elements
Inherited: no
Percentages: N/A
Media: visual
Computed value see individual properties
Name: border-color
Value: <border-color>{1,4} | inherit | initial
Initial: (see individual properties)
Applies to: all elements
Inherited: no
Percentages: N/A
Media: visual
Computed value see individual properties
Name: border , border-top, border-right, border-bottom, border-left
Value: [ <border-width> || <border-style> || <border-color> ] | inherit | initial
Initial: none
Applies to: all elements
Inherited: no
Percentages: N/A
Media: visual
Computed value see individual properties
Name: border-radius-topright, border-radius-bottomright, border-radius-bottomleft, border-radius-topleft, border-radius

Value:

<length> <length>? | inherit | initial
Initial: 0
Applies to: all elements
Inherited: no
Percentages: N/A
Media: visual
Computed value specified values, except for 'inherit' and 'initial'

These properties set the color, thickness and style of the border.

<border-style> is 'none | hidden | dotted | dashed | solid | double | dot-dash | dot-dot-dash | wave | groove | ridge | inset | outset', with the following meanings:

none
No border. Color and width are ignored (i.e., the border has width 0).
hidden
Same as 'none', but has different behavior in the conflict resolution rules for tables[ref].
dotted
A series of dots.
dashed
A series of dashes.
solid
A single line segment.
double
Two parallel solid lines with some space between them. (The thickness of the lines is not specified, but the sum of the lines and the space must equal 'border-width'.)
dot-dash
Alternating dots and dashes.
dot-dot-dash
Two dots and a dash.
wave
A wavy line.
groove
Looks as if it were carved in the canvas. (This is typically achieved by creating a "shadow" from two colors that are slightly lighter and darker than the 'border-color'.)
ridge
Looks as if it were coming out of the canvas.
inset
Looks as if the content on inside of the border is sunken into the canvas. Different meaning on table[ref] elements.
outset
Looks as if the content on the inside of the border is coming out of the canvas. Different meaning for table[ref] elements.

Examples of border styles

Examples of border styles. (This picture is not normative.) [add wave, dot-dash...]

The two length values of the 'border-radius' properties define the radii of a quarter ellipse that defines the shape of the corner (see the diagram below). The first value is the horizontal radius (or vertical if the orientation is vertical). If the second length is omitted it is equal to the first (and the corner is thus a quarter circle). If either length is zero, the corner is square, not rounded. The border radius also causes the element's background to be rounded (even if the border is 'none'). Negative values are not allowed.

Diagram of the inscribed ellips

Diagram showing the effect of 'border-radius: 55pt 25pt' and 'border: 5pt solid black'

Note: There is no control over the spacing of the dots and dashes, nor over the length of the dashes. Implementations are encouraged to choose a spacing that makes the corners symmetrical. Also, it is recommended that the dots are round, not square.

Note: This specification does not define how borders of different styles should be joined in the corner. Also note that rounded corners may cause the corners and the contents to overlap, if the padding is less than the radius of the corner.

The background of the element extends into the border area. See the 'background' property.

The <border-width> can be '<length> | thin | medium | thick'. The <length> may not be negative. The lengths corresponding to 'thin', 'medium' and 'thick' are not specified, but the values are constant throughout a document and thin <= medium <= thick. A UA could, e.g., make the thickness depend on the 'medium' font size: one choice might be 1, 3 & 5px when the 'medium' font size is 17px or less.

The <border-color> can be '<color> | transparent'. When the border is transparent, only the background is visible.

'Border-width' is a shorthand that sets the four 'border-*-width' properties. If it has four values, they set top, right, bottom and left in that order. If left is missing, it is the same as right; if bottom is missing, it is the same as top; if right is missing, it is the same as top.

'Border-style' is a shorthand that sets the four 'border-*-style' properties. 'Border-color' is a shorthand for the four 'border-*-color' properties.

'Border-top' is a shorthand for 'border-top-style', 'border-top-width' and 'border-top-color'. 'Border-right', 'border-bottom' and 'border-left' are analogous.

'Border' is a shorthand for all of the other border properties, except that it can only set all four sides to the same style, color and width.

Note that the initial width is 'medium', but the initial style is 'none' and therefor the computed width is 0.

When the computed width of the border is 0, we say that the border is absent.

7. The 'border-break' property

Name: border-break
Value: open | close | inherit | initial
Initial: open
Applies to: elements with a border
Inherited: yes
Percentages: N/A
Media: visual
Computed value: specified value, except for 'inherit' and 'initial'

When a box that has a border is broken at a page break, column break, or, for inline elements, at a line break, a border can be inserted at the break, or the border can be left open. The value 'closed' will add padding and a border at the break, as if it was the normal end of the box. The value 'open' will not add padding or border at the break. The property has no effect if the border is absent.

Illustration of open and closed

Examples of open (on the left) and closed (on the right) borders.

8. The 'margin' properties

Name: margin-top , margin-right, margin-bottom, margin-left, margin-inside, margin-outside
Value: <length> | <percentage> | auto | inherit | initial
Initial: 0
Applies to: all elements
Inherited: no
Percentages: width* of containing block
Media: visual
Computed value <length>
*) if the containing block is 'horizontal', otherwise height
Name: margin
Value: [ <length> | <percentage> | auto ]{1,4} | inherit | initial
Initial: (see individual properties)
Applies to: all elements
Inherited: no
Percentages: width* of containing block
Media: visual
Computed value see individual properties
*) if the containing block is 'horizontal', otherwise height

These properties set the thickness of the margin. The value may be negative, but the UA may impose a lower bound.

'Margin' is a shorthand to set top, right, bottom and left together. If four values are given, they set top, right, bottom and left in that order. If left is omitted, it is the same as right. If bottom is omitted, it is the same as top. If right is omitted it is the same as top.

'Margin-inside' and 'margin-outside' are aliases for 'margin-left' or 'margin-right', depending on the current medium:

Note: "inside" refers to the side of a page close to the binding, "outside" to the side where the book opens.

[Do we really need margin-inside & margin-outside, or is 'page:left' enough?]

The meaning of 'auto' is as follows:

Margins must satisfy certain constraints, which means that the computed value may be different from the specified value. See equation (1) below.

Note that in a horizontal flow, percentages on 'margin-top' and 'margin-bottom' are relative to the width of the containing block, not the height (and in vertical flow, 'margin-left' and 'margin-right' are relative to the height, not the width).

9. The 'width' and 'height' properties

Name: width, height
Value: <length> | <percentage> | auto | inherit | initial
Initial: auto
Applies to: all elements, except inline-level elements with 'display-model' of 'text'
Inherited: no
Percentages: width, resp. height of containing block, but see prose
Media: visual
Computed value <length> or 'auto' (see text)

[Idea by David Baron: add keyword values 'intrinsic' and 'min-intrinsic' to force an element to have its intrinsic or minimum width.]

This property sets the width resp, height of the content area. The value may not be negative and in addition the UA may impose a certain lower bound.

Width and height are symmetric: the role of width and height are exactly interchanged in horizontal and in vertical text. Below we explain only width; height can be derived from that by interchanging "horizontal" and "vertical."

The computed value is normally a <length>, but in the following cases it can also be 'auto':

In these two cases, a specified value of 'auto' cannot be replaced by a <length> on the basis of information that is available at the start of the element, i.e., based solely on the width and height of preceding elements and ancestors.

9.1. The <length> and <percentage> values

A <percentage> is relative to the computed value of the width or height of the containing block, but if that value is 'auto' the computed value for the percentage is also 'auto'.

When 'width' or 'height' is set to a value other than 'auto' on a replaced element, the size of content area is set to that value and the content may be scaled or otherwise deformed to fit the area. If both 'width' and 'height' are set, the scaling may even be different in the two directions. See the 'fit' property.

[Do we need control over size and scaling of backgrounds as well? If TVWeb wants to model overlay of text over TV as text in foreground and TV in background, it seems we do... Yes, see Background module.]

9.2. The 'auto' value

We describe the meaning of 'auto' on elements that have horizontal flow. Vertical flow is analogous, but with the roles of 'width' and 'height' interchanged.

For replaced elements there are two cases. (1) Both width and height are 'auto': in this case both are set to the intrinsic size. (2) Only one of the two is 'auto': in this case 'auto' is computed as the size that keeps the aspect ratio the same, i.e., width : height = intrinsic-width : intrinsic-height.

For non-replaced elements, 'auto' on height is always the intrinsic height that corresponds to the element's computed width. The computed value of 'auto' on 'width' depends on the type of box:

  1. If the element is the root element the width is UA-dependent on non-paged media. (It is recommended that the UA uses the viewport [ref] width.) On paged media, the value is the computed width value of the 'size' property.
  2. If the element is a flow root, width is the intrinsic width.
  3. Otherwise, if the element is a block-level element and its containing block also has a horizontal flow, equation (1) below determines the width.
  4. Otherwise, if the element is block-level and the containing block has a different orientation, the computed value is the intrinsic width.
  5. Otherwise (i.e., the element is positioned or is a table element), see the positioning[ref] or table[ref] modules.

[Need to explain that 'height: auto' in horizontal flow (and 'width: auto' in vertical flow) is the intrinsic height (or width). Probably need to specify that the height of a flow root (but not of other elements) includes any floating (and positioned?) descendants in that flow. This is so that a float descendant of another float remains visually inside the latter float.]

Note that in CSS2, floating elements (case 2) were given a certain small, UA-dependent width, but in CSS3 they are given their intrinsic width (often referred to as "shrink-wrapped").

9.3. Constraints on width, height and margins in block-level elements

For block-level elements with horizontal flow in a containing block also with horizontal flow, the 'width' and margins must satisfy this constraint:

(1)

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

The following cases can occur:

  1. If none of width, margin-left or margin-right was specified as 'auto', the equation is over-constrained. There are two sub-cases: (1) if the 'direction' of the element is 'ltr', the specified value of 'margin-right' is ignored and 'margin-right' is set to the value that makes the equation true; (2) if 'direction' is 'rtl', it is 'margin-left' that is ignored and computed from the equation.
  2. If exactly one of width, margin-left or margin-right is 'auto', its value is computed from the equation.
  3. If width and one or both margins are 'auto', the margins that are 'auto' are set to 0 and the equation is solved for width.
  4. If both margin-left and margin-right are 'auto', the equation is solved under the extra constraint that margin-left = margin-right.

If, after solving the equation, width has a value that is smaller than 'min-width', the computed value of 'width' is set to the computed value of 'min-width' and the constraint is evaluated again as if width had been specified with this value.

If, after solving the equation, width has a value that is larger than both 'max-width' and 'min-width', the computed value of 'width' is set to the larger of 'max-width' and 'min-width' and the constraint is evaluated again as if 'width' had been specified with this value.

Note: case 4 can be used to center block-level elements:

BLOCKQUOTE {
    width: 30em;
    margin-left: auto;
    margin-right: auto }

This is different from 'text-align: center', which centers each line inside the block, but not the block inside its parent.

Block-level elements with a vertical flow inside a containing block with a vertical flow are analogous, but with a constraint on height and margin-top/margin-bottom:

(2)

(height of containing block) = margin-top + border-top + padding-top + height + padding-bottom + border-bottom + margin-bottom

10. The 'box-width' and 'box-height' properties (or 'box-sizing')

Name: box-width, box-height
Value: <length> | <percentage> | auto | inherit | initial
Initial: auto
Applies to: same as 'width' and 'height'
Inherited: no
Percentages: see 'width' and 'height'
Media: visual
Computed value <length> or 'auto' (see text)

'Box-width' and 'box-height', if not set to 'auto', override 'width' and 'height' respectively. They set the width/height from border-edge to border-edge. I.e., 'box-width: X' is equivalent to setting 'width: (X - padding-left - border-left - padding-right - border-right)'

BUTTON { box-width: 10% }

The computed value is either the specified <length>, or the result of adding the relevant padding to the computed value of 'width' or 'height', except that if the computed value of 'width' resp. 'height' is 'auto', then so is 'box-width' resp. 'box-height'.

Other possibility:

Name: box-sizing
Value: content-box | border-box | inherit | initial
Initial: content
Applies to: elements to which 'width' or 'height' applies
Inherited: no
Percentages: N/A
Media: visual
Computed value 'content-box' or 'border-box'

Description:

content-box
This is the behavior of width and height as specified by CSS2. The specified width and height apply to the width and height respectively of the content box of the element. The padding and border of the element are laid out and drawn outside the specified width and height.
border-box
The specified width and height on this element determine the border box of the element. That is, any padding or border specified on the element is laid out and drawn inside this specified width and height. The content width and height is computed by subtracting the border and padding widths of the respective sides from the specified width and height. This is the behavior of width and height as commonly implemented by legacy HTML user agents for replaced elements and input elements.

Yet another possibility: Introducing simple expressions can also solve the same problem, but in a different way: BUTTON { border: 2px solid; width: 10% - 2 * 2px }

11. The 'min-width', 'max-width', 'min-height' and 'max-height' properties

Name: max-width, max-height
Value: <length> | <percentage> | auto | inherit
Initial: auto
Applies to: same as 'width' and 'height'
Inherited: no
Percentages: see 'width' and 'height'
Media: visual
Computed value <length> or 'auto' (see text)

Set the maximum width and height of an element's content area. 'Auto' means there is no maximum.

Name: min-width , min-height
Value: <length> | <percentage> | inherit | initial
Initial: 0
Applies to: same as 'width' and 'height'
Inherited: no
Percentages: see 'width' and 'height'
Media: visual
Computed value <length> or 'auto' (see text)

Set the minimum width and height of an element's content area.

'Min-width' overrides 'max-width', and both override 'width', in case any of them conflict. Analogous for 'min-height', 'max-height' and 'height'

12. The 'fit' and 'fit-position' properties

Name: fit
Value: fill | none | meet | slice | inherit | initial
Initial: fill
Applies to: replaced elements
Inherited: yes
Percentages: N/A
Media: visual
Computed value specified value (except for 'inherit' and 'initial')
Name: fit-position
Value: [ [<percentage> | <length> ]{1,2} | [ [top | center | bottom] || [left | center | right] ] ] | auto | inherit | initial
Initial: 0% 0%
Applies to: replaced elements
Inherited: yes
Percentages: refer to width and height of box itself
Media: visual
Computed value specified value (except for 'inherit' and 'initial')

The 'fit' property gives a hint for how to scale a replaced element if neither its 'width' nor its 'height' property is 'auto'. Not all replaced objects can be scaled, but images typically can.

fill
Scale the object's height and width independently so that the content just touches all edges of the box.
none
Do not scale the object.
meet
Make the object as large as possible with its width <= 'width' and height <= 'height', while preserving its aspect ratio. Position the object as for 'hidden'.
slice
Make the object as small as possible with its width >= 'width' and height >= 'height', while preserving its aspect ratio. Position the object as for 'hidden'. See 'overflow' for how to render the parts that stick out of the box.

See the 'overflow' property for what happens to parts of the object that stick out of the box.

The keywords are intended to convey the visual effect in the case that 'overflow' is 'hidden', which is expected to be the most common case.

Illustration of the four values

An example how each of the four values of 'fit' causes the object (gray rectangle) to be scaled to fit the given box (red dotted outline).

The 'fit-position' determines the alignment of the object inside the box. The values have the same meaning as the values on 'background-position', with the addition of the value 'auto', specifically:

<percentage> <percentage>
With a value pair of '0% 0%', the upper left corner of the image is aligned with the upper left corner of the box's padding edge. A value pair of '100% 100%' places the lower right corner of the image in the lower right corner of padding area. With a value pair of '14% 84%', the point 14% across and 84% down the image is to be placed at the point 14% across and 84% down the padding area.
<length> <length>
With a value pair of '2cm 2cm', the upper left corner of the image is placed 2cm to the right and 2cm below the upper left corner of the padding area.
'top left', 'left top'
Same as '0% 0%'.
'top', 'top center', 'center top'
Same as '50% 0%'.
'right top', 'top right'
Same as '100% 0%'.
'left', 'left center', 'center left'
Same as '0% 50%'.
'center', 'center center'
Same as '50% 50%'.
'right', 'right center', 'center right'
Same as '100% 50%'.
'bottom left', 'left bottom'
Same as '0% 100%'.
'bottom', 'bottom center', 'center bottom'
Same as '50% 100%'.
'bottom right', 'right bottom'
Same as '100% 100%'.
'auto'
Put one of the object's corners in the corresponding corner of the box, depending on the element's 'writing-mode':
writing-mode corner
lr-tb top left
rl-tb top right
tb-rl top right
tb-lr top left
bt-rl bottom right
bt-lr bottom left

Note: these properties do not exist in CSS2.

Note that areas of the box not covered by the replaced element will show the element's 'background'.

Note: the 'fit' property has the same meaning as the fit attribute in [SMIL1.0], except that the value "scroll" is not available, because the 'overflow' property can be used instead.

13. The 'content' property

Name: content
Value: [ <string> | <uri> | <counter> | attr(X) | open-quote | close-quote | no-open-quote | no-close-quote ]+ | link | normal | inherit
Initial: auto
Applies to: all elements
Inherited: no
Percentages: N/A
Media: all
Computed value specified value (except for 'inherit' and 'initial')

[Belongs in module "generated content."] This property indicates what the content of an element is. Values have the following meanings:

<string>
Literal text content (see the section on strings[ref]).
<uri>
The value is a URI that designates an external resource. If a user agent cannot support the resource because of the media types[ref] it supports, it must ignore the resource. Note: CSS3 offers no mechanism to change the size of the embedded object, or to provide a textual description, like the "alt" or "longdesc" attributes do for images in HTML. This may change in future levels of CSS.
<counter>
Counters[ref] may be specified with two different functions: 'counter()' or 'counters()'. The former has two forms: 'counter(name)' or 'counter(name, style)'. The generated text is the value of the named counter at this point in the formatting structure; it is formatted in the indicated style[ref]. The latter function also has two forms: 'counter(name, string)' or 'counter(name, string, style)'. The generated text is the value of all counters with the given name at this point in the formatting structure, separated by the specified string. The counters are rendered in the indicated style. See the section on automatic counters and numbering[ref] for more information.
open-quote and close-quote
These values are replaced by the appropriate string from the 'quotes' property.
no-open-quote and no-close-quote
Inserts nothing (the empty string), but increments (decrements) the level of nesting for quotes.
attr(X)
This function returns as a string the value of attribute X for the subject of the selector. The string is not parsed by the CSS processor. If the subject of the selector doesn't have an attribute X, an empty string is returned. The case-sensitivity of attribute names depends on the document language. Note: in CSS3, it is not possible to refer to attribute values for other elements of the selector.
link
The element is replaced by the object that it points to, provided the element is a link element, otherwise the meaning is the same as 'normal'. Note that this value can make the element into a replaced element.
normal
The normal case: the element's contents are the contents of the element in the source document.

The default rules for HTML include the following, which say that a P is a "normal" element, and IMG and OBJECT are "replaced" elements:.

P { content: auto }
OBJECT, IMG { content: link}

Note that the UA may be smart enough to recognize, especially in the case of OBJECT, that it cannot handle certain linked objects, and that therefore a particular OBJECT element is not really a link element, but a normal one.

Authors should put 'content' declarations in @media[ref] rules when the content is media-sensitive. For instance, literal text may be used for any media group, but images only apply to the visual media group, and sound files only apply to the aural media group.

The following rule causes a sound file to be played at the end of a quotation (see the section on aural style sheets[ref] for additional mechanisms):

@media aural {
   BLOCKQUOTE:after { content: url("beautiful-music.wav") }
   }

The next rule inserts the text of the HTML "alt" attribute before the image. If the image is not displayed, the reader will still see the "alt" text.

IMG:before { content: attr(alt) }

Authors may include newlines in the generated content by writing the "\A" escape sequence in one of the strings after the 'content' property. This inserts a forced line break, similar to the BR element in HTML. See "Strings"[ref] and "Characters and case"[ref] for more information on the "\A" escape sequence.

H1:before {
    display: block;
    text-align: center;
    content: "chapter\A hoofdstuk\A chapitre"
}

Generated content does not alter the document tree. In particular, it is not fed back to the document language processor (e.g., for re-parsing).

In future levels of CSS, the 'content' property may accept additional values, allowing it to vary the style of pieces of the generated content, but in CSS3, all the generated content has the same style.

Note, that in CSS2, this property was only allowed on the :before and :after pseudo-elements.

14. Styling hyperlinks

This section is in a very unstable state. Also, it is likely to be moved to either the UI module or a new, separate module on hyperlinks.

14.1. The @link rule

The @link rule determines whether an element is a link element and, if so, where to find the URI. It has one of the following forms:

  1. @link Selector1 = this(Attribute)
  2. @link Selector1 = first(Attribute)
  3. @link Selector1 = content
  4. @link Selector1 @with Selector2 = this(Attribute)
  5. @link Selector1 @with Selector2 = content

To determine if an element in the source document is a link element, first find the @link rule that applies. There may be several or none, and the cascading and specificity rules apply (see [cascading]). If there is an @link that applies, then depending on the type of @link rule:

  1. A rule of the form "this(Attribute)" says that the element is a link element if it has this attribute. The value of the attribute is interpreted as a URI reference.
  2. A rule of the form "first(Attribute)" says that the element is a link element if any of the descendant elements of the element's parent has this attribute. The first such attribute is interpreted as a URI reference.
  3. A rule of the form "content" says that the element is a link element (unconditionally) and that the element's content is interpreted as a URI reference. The content is the "flattened" content of the element and any descendants.
  4. A rule of the form "@with Selector2 = this(Attribute)" says that the element is a link element if its parent has a descendant that matches Selector2 when the parent is considered the root element for the purposes of matching the selector, and if that descendant has the given attribute. The first such attribute is interpreted as a URI reference.
  5. A rule of the form "@with Selector2 = content" is similar, except that the "flattened" content of the first matched descendant is taken as a URI reference.

Depending on the format of the source document, it may be necessary to modify the attribute value in ways defined by the format in order to determine the actual URI. For example, some formats may define special processing to change a relative URL into an absolute one, such as rules that involve a BASE or xml:base element.

If the attribute contains a relative URI reference and the document format specifies no rules, then the absolute URI is found by using the source document's own URI as a base.

For example, the A and IMG elements of HTML can be described like this:

@link a = this(href);
@link img = this(src);

The first A element in the following document matches the selector "a" and it has an "href" attribute and is thus a link element. The second one does not have an "href" and is therefore not a link element:

<p>
<a href="../">is this a link?</a>
and  what about
<a name="b4">this?</a>
</p>

The anchor and img elements of WML 1.0 can be described by these @link rules:

@link anchor @with go = this(href);
@link img = this(src);

Here is an example of an anchor element that matches the @link rule:

<anchor>
  follow me
  <go href="destination"/>
</anchor>

Here is an example that shows how images with a longdesc attribute can be made into a link to the long description:

@link img = this(longdesc);
img { content: attr(alt) }

Note that every element can only link to one document at a time, in particular, an img can link to its src or longdesc attribute, but not both at the same time. However, if we know that every img has a parent div with class "figure" (as in the present document), we can use the following trick:

@link img = this(src);
@link div.figure = first(longdesc);

Activating (clicking) the div will traverse the link to the longdesc.

CSS does not require that a UA reads a DTD, XML schema or other mechanism that may provide default values for absent attributes. Thus, for XML-based formats that do allow such mechanisms but that do not require them to be parsed the rendering may be different between UA's that read them and those that do not. This may happen in particular if the user asks a UA to render an XML-based document whose format the UA does not recognize. (Some UAs may offer this as a fallback option, besides saving the document to disk. This option is often referred to as "generic XML rendering," since the document is treated as if it had no other semantics than what is provided by CSS.)

HTML is an exception, however. CSS requires that UA's do not use default values in HTML and XHTML: only attributes set on the element instance are taken into account when evaluating the attr() values. [Check that XHTML itself doesn't already exclude DTD's and schemas.] [Check that the same is said about matching selectors.]

Note that some of the @link rules may require the parser to look ahead beyond an element to determine if the element is a link element, and may thus slow down progressive rendering.

Does '@link' apply to HTML documents? Or is it only a conformance requirement for non-HTML source documents?

Elements with two or more URLs (such as img with its src and longdesc) are not treated very satisfactorily...

14.2. The link-behavior property

Name: link-behavior
Value: normal | pop-up | confirm | expand | none | inherit | initial
Initial: normal
Applies to: link elements (unless 'content' is 'link'), and collapsed elements
Inherited: yes
Percentages: N/A
Media: all
Computed value specified value (except for 'inherit' and 'initial')

This property determines what the UA will do with a link element or a collapsed element (see 'collapse'). If a link element has 'content: link', the property does not apply. The values have the following meaning:

normal [or 'replace']
The element behaves as a hyperlink: it can be activated by the user (by clicking, by pressing return, etc., depending on the UA). When it is activated, its target replaces the current document completely. The UA should provide a Back function to restore the current document.
pop-up
The element behaves as a hyperlink, but when the element is activated, its target does not replace the current document, but pops up in a temporary window (if the UA's platform allows). When the user activates a 'pop-up' link in that window, another window pops up, etc., but when a 'normal' or 'confirm' link in any of those pop-up windows or in the current document is activated (and confirmed, in the case of 'confirm'), all pop up windows close and the target replaces the current document. (Note that HTML 4 "transitional" had a target attribute with similar behavior. This value is meant to replace, and improve upon, the attribute.)
confirm
Like 'normal', but activating the link first pops up a small window with some information about the target (see "Confirming link traversal" below for more rules) and the user has to confirm that he indeed wants to see the target. The UA determines what constitutes a confirmation. It might be a pair of "yes"/"no" buttons.
expand
The element behaves as a hyperlink, but on activation the target replaces only the element, not the whole document.
none
The element is inactive.

Note that the pseudo-classes :link and :visited apply to all link elements even if 'link-behavior' is 'none'.

Note also that 'expand' will normally cause re-flow. The resulting rendering is the same as when the 'content' property had been set to 'link', except that the rendering is only shown after activation and can be undone with the Back button.

This property influences the "normal" way of activating a hyperlink, which is often by mean of a click with first mouse button. It does not prohibit the UA to offer other ways of interaction. For example, many browsers provide a menu under the second mouse button with several options.

The user should be able to configure the size of a pop-up window just like that of a normal window (subject to the restrictions of the platform/window-system): the initial size should be configurable, but the window should also be re-sizable dynamically.

It is acceptable that the UA decreases the height of a particular pop-up window if the content needs a smaller window than the initial size (or decreases the width, if the content is a vertical flow).

It is also acceptable that the UA decreases the window's height resp. width if the root element of the document displayed in it has a specific (i.e., not 'auto' or a percentage) 'height' resp. 'width' property that is smaller than the user-configured initial window size.

When an element is a hyperlink and can thus be activated by the user, all parts of the element are active: all the boxes generated for the element or for its descendants are active, with the exception of boxes that belong to descendant elements that are themselves hyperlinks. For example, if activation is done with the mouse, a click on any of those boxes will activate the element. [check if this is true for floating (yes?) and for abs. pos. children (maybe no?)]

Here is an example:

a.note { link-behavior: pop-up }

The above causes hyperlinks of class ".note" to be displayed in a pop-up window.

Documents that use the "simple links" from the [XLink1.0] specification, could be rendered with these rules:

@namespace x url(http://www.w3.org/1999/xlink);
*[x|show=new] { link-behavior: pop-up }
*[x|show=replace] { link-behavior: normal }
*[x|show=embed] { content: link }
*[x|show=embed][x|actuate=onRequest] { link-behavior: expand }

This says that the x:show attribute determines how and when the target is displayed. (CSS cannot render the suggested effect of "new" + "onLoad" or "replace" + "onLoad," which is that the target is displayed immediately in a new window, respectively in place of the current document. The former would make windows appear without any user action, the latter is a feature already provided by HTTP.)

Note: In CSS1 & CSS2 the form elements of HTML were also counted as replaced elements, because they were considered to be replaced by buttons, text fields, etc. that were proprietary to the platform. In CSS3 these elements are normal, non-replaced elements. CSS3 has explicit properties that can make them look like they did in CSS1 and CSS2 (or make them look completely different)

[Is the Back button enough to collapse an expanded element again? Or should the user have an explicit collapse action? We could require that activating an expanded element or one of its parts (other than hyperlinks) will collapse the element again.]

14.3. Confirming link traversal

If the value of 'link-behavior' is 'confirm', the information displayed in the confirmation dialog depends on the UA and on the type of the target document. Here are some guidelines to follow:

What is a "reasonable time" depends on circumstances, but the goal is to maintain the illusion of hypertext, and make the user feel comfortable and in control. Example:

<STYLE>
  A.download { link-behavior: confirm }
</STYLE>
...
<A CLASS="download"
  TITLE="Are you sure you want to do this crazy thing?"
  HREF="ftp://ftp.mozilla.org/pub/mozilla/nightly/latest/">
    Download Latest Build</A>
...

[This might be considered abuse of the TITLE attribute. Is there a cleaner way?]

14.4. The collapse property

Name: collapse
Value: none | <'content'> | first-child | inherit | initial
Initial: none
Applies to: all elements
Inherited: no
Percentages: N/A
Media: interactive visual
Computed value specified value (except for 'inherit' and 'initial')

There is one kind of implicit link that CSS can exploit and present as a hyperlink and that is the relation between an element and its children. The values have the following meaning:

'none'
The element is not collapsed, but displayed normally.
<'content'>
The contents of the elements are not displayed, but instead the value of the property is displayed. See the 'content' property for the various values. The 'link-behavior' property applies, with the normal, un-collapsed element acting as link target of the collapsed element..
'first-child'
The contents of the property are not displayed, except for the first child element. If there is no child, nothing is displayed. The 'link-behavior' property applies, as for <content>.

Note that this property can make an element behave almost like a link element, but it does not make the :link and :visited pseudo-classes match.

Here is an example:

OL { collapse: url("downarrow.png") }
LI { collapse: url("rightarrow.png") }

This will result in the OL element being displayed as an icon. When activated, the image disappears and the contents of the OL is displayed. The contents consists of LI elements (we assume this is HTML) which are in turn displayed as images. The contents of those LI elements can be displayed by clicking on their icons.

The following example will display the TITLE attribute instead of the list and allow the user to expand the list by activating that title:

OL { collapse: attr(TITLE); link-behavior: expand }

The expanded element can also be displayed as a separate page. That is in fact the initial value of 'link-behavior'. This example shows every DIV as a number, which, when activated, displays the DIV as a new page, just like a normal hyperlink would do:

DIV { collapse: counter(div-counter); counter-increment: div-counter }

Here are three more examples, showing how 'link-behavior' and 'collapse' can turn images on and off. The first one turns images off completely, showing the ALT text instead:

IMG { content: attr(ALT) }

The second allows users to activate the ALT text to load the image:

IMG { collapse: attr(ALT); link-behavior: expand }

The third also allows user to activate the ALT text, but the image will take over the canvas:

IMG { collapse: attr(ALT); link-behavior: replace }

We assume here that the UA default style for IMG contains 'content: link', so that the normal, un-collapsed rendering of IMG makes it a replaced element.

This example collapses a list to its first item:

UL { collapse: first-child }

In a document where sections are marked-up with SECT and each section starts with a heading as its first element, the following can be used to collapse sections to just the heading:

SECT { collapse: first-child }

All the properties of the element, such as margin, background, display, and positioning, apply to the normal contents as well as to temporary content, in so far as they make sense. For example, an image is treated as a replaced element, so properties such as 'text-indent' and 'font-family' don't apply.

If a link element has both the 'link-behavior' and 'collapse' properties set, then activating the element only expands the element. The expanded element then has to be activated to get to the target of the link.

If an element is set to 'collapse: first-child', and the element is in its collapsed state, selectors will match as if the element's other children were not there. For example, the element's child element, if any, will match the ':last-child' selector.

14.5. The ":expanded" and ":collapsed" pseudo-classes

An element that is collapsed is considered to be in a different state from when it is activated and shown expanded. The ":expanded" pseudo-class can be used to put a different style on the element in its expanded state, ":collapsed" in its collapsed state.

This example assumes that there is an example element. The first rule set defines it to be collapsed to just the character "@" and sets the style for both the collapsed and expanded states. The second rule set overrides the background for the expanded state.

copyright {
    collapse: "Š";
    width: 70%;
    background: #FFF;
    border: solid }
copyright:expanded {
    background: #FF0 }

Another option is to have both a :collapsed and a :expanded pseudo-class and use the 'content' property in both. There is no need for a 'collapse' property then. The fact that the element has two states follows from the fact that the 'content' is different in the two states.

The element in either of its states can have a 'position' property, allowing the target to appear somewhere else than where the source anchor was. Because of the confusion that nonlocal effects can cause, this has to be used with care.

This example shows a list as a pop-up menu. Clicking on the text (from the "title" attribute) will open the list as an absolutely positioned overlay at approximately the same position:

UL { collapse: attr(title); link-behavior: expand }
UL:expanded { position: absolute; top: auto; left: auto }

[Does it need 'zindex: 1', or will it automatically appear in front?]

14.6. Overlapping source anchors

It may be the case that inside a link element there is another link element. It depends on the UA how the user activates an element (it could be by clicking on it, by tabbing to it and pressing Enter, by pressing the element's shortcut key, etc.), but if the inner element is activated, it should not also activate the outer one.

14.7. The Back button

Most interactive UAs allow the user to go back to a previous state with a simple command, often by pressing a button labelled "back." The effect of this command, let's call it simply "the Back button," depends on the behavior of the hyperlink that was activated. Here are some guidelines:

Note that a target that is displayed as a result of a value 'replace' on the source anchor is not the result of a user activation and cannot be "un-displayed" with the back button.

15. The float property

A float is a box that creates a new flow, while the parent flow wraps around it. The 'float' property determines where the box is positioned relative to the parent flow: left or right (for horizontal flows), top or bottom (for vertical flows)

Example: the following rule floats all IMG boxes with class="icon" to the left (and sets the left margin to '0'):

IMG.icon { 
  float: left;
  margin-left: 0;
}

Consider the following HTML source and style sheet:

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN">
<HTML>
  <HEAD>
    <TITLE>Float example</TITLE>
    <STYLE type="text/css">
      IMG { float: left }
      BODY, P, IMG { margin: 2em }
    </STYLE>
  </HEAD>
  <BODY>
    <P><IMG src=img.gif alt="This image will illustrate floats">
       Some sample text that has no other...
  </BODY>
</HTML>

The IMG box is floated to the left. The content that follows is formatted to the right of the float, starting on the same line as the float. The line boxes to the right of the float are shortened due to the float's presence, but resume their "normal" width (that of the containing block established by the P element) after the float. This document might be formatted as:

Image illustrating how floating boxes interact with margins.

Formatting would have been exactly the same if the body of the document had been:

<BODY>
  <P>Some sample text 
  <IMG src=image.gif alt="This image will illustrate floats">
           that has no other...
</BODY>

because the content to the left of the float is displaced by the float and re-flowed down its right side.

Name: float
Value:    left | right | top | bottom | inside | outside | start | end | none | inherit | initial
Initial:    none
Applies to:    all but positioned elements and generated content
Inherited:    no
Percentages:    N/A
Media:    visual
Computed value specified value (except for 'inherit' and 'initial')

The values have the following meanings:

left, top
If the containing block has horizontal flow: the element generates a box that is floated to the left. Content flows on the right side of the box, starting at the top (subject to the 'clear' property). If the containing block has vertical flow the box is floated to the top and content flows on the bottom side of the box (subject to the 'clear' property).

Note: for readability it is recommended to use 'left' in style sheets for horizontal flow and 'top' for vertical flow.

It would be more intuitive (less surprising) if 'left' only worked in horizontal flow and 'top' only in vertical flow.

right, bottom
Analogous to 'left', but content flows on the left side, respectively the top side of the box.
inside
Same effect as 'left' or 'right' depending on whether the float will appears on a right, resp. left page in paged media. Same as 'left' on non-paged media. (See the Paged media module [ref] for information on left/right pages.)
outside
Same effect as 'right' or 'left' depending on whether the float will appears on a right, resp. left page in paged media. Same as 'right' on non-paged media.
start
Same effect as either 'left', 'right', 'top' or 'bottom, depending on the 'direction' of the containing block, as follows:
'direction' effect
ltr left/top
rtl right/bottom
end
Same effect as either 'left', 'right', 'top' or 'bottom', depending on the orientation of the flow and the 'direction' of the containing block, as follows:
horizontal vertical vertical-lr
ltr right bottom bottom
rtl left top top
none
The box is not floated.

Note: The keywords 'start' and 'end' are intended to be mnemonic for floating towards the "start of the line" and "end of the line" respectively. They are most useful for floats that must float to the left or right depending on the script and in those cases avoid having to use language selectors.

The 'display-role' property has the following interaction with 'float'.

A floating box causes the content of elements in its parent flow to wrap around the rectangular outline of the floating box only, not around any descendant box of the floating box that may stick out of the floating box. (Note that whether such a descendant overlaps other content or is clipped depends on the 'overflow' property.)

Should also have float to top/bottom of page. In paged media module?

Here are the precise rules that govern the behavior of floats (rules are for horizontal flow, vertical flow is analogous):

  1. Principle of horizontal containment: The left margin edge of a left-floating box may not be to the left of the left edge of its containing block. An analogous rule holds for right-floating boxes. (Note that margins can be negative, so the content might still be outside the containing block.)
  2. Principle of vertical containment: A floating box's top margin edge may not be higher than the top of its containing block.
  3. Principle of avoidance of overflow: The right margin edge of a left floating box may not be to the right of the right edge of its containing block, unless its left margin edge coincides with the containing block's left edge. Analogous for a right-floating box. (This makes floating boxes "wrap" when their collective width would be wider than the containing block. The only case where a float can cause overflow is when the float itself is wider than the containing block.)
  4. Principle of preservation of ordering: The top margin edge of a floating box may not be higher than the top margin edge of any float in the current flow that is generated by an earlier element in the source.
  5. Principle of progressive rendering: The top margin edge of a floating box may not be higher than the top of any line box that contains a box generated by an element earlier in the source. (This ensures that lines above the current one, that may already have been rendered, do not have to be redrawn.)
  6. Principle of excluded quarter planes: If there is an earlier left-floating box in the current flow, the left margin-edge of the current box must be to the right of the that box's right margin-edge or the current box's top margin edge must be below its bottom margin edge. If there is an earlier right floating box, the right margin-edge of the current box must be to the left of the earlier box's left margin edge, or the current box's top margin edge must be below its bottom margin edge. (Note: another name for this principle might be "avoiding overlap", but it is stronger than that.)
  7. Principle of tight packing: A floating box must be placed as high as possible without violating principles 1-6.
  8. Principle of meaningful names: A left-floating box must be put as far to the left as possible, a right-floating box as far to the right as possible, without violating principles 1-7.

In a multicolumn box [link], [...]

Here is an illustration of the rules. Assume this source fragment:

<STYLE TYPE="text/css">
  P { width: 24em }
  #L1 { float: left; width: 8em; height: 3em }
  #L2 { float: left; width: 4em; height: 6em }
  #R1 { float: right; width: 6em; height: 9em }
  #L3 { float: left; width: 7em; height: 9em }
  #R2 { float: right; width: 3em; height: 5em }
</STYLE>
<P>
  <IMG ID=L1 SRC="L1.png" ALT="L1">
  <IMG ID=L2 SRC="L2.png" ALT="L2">
  <IMG ID=R1 SRC="R1.png" ALT="R1">
  <IMG ID=L3 SRC="L3.png" ALT="L3">
  <IMG ID=R2 SRC="R2.png" ALT="R2">
  blah blah blah blah blah...
</P>

The figure below shows the result. Note that L3 could not be to the right of L1 and L2, so it had to be below both of them. R2 could not be placed higher than L3, because it came after L3.

How floating boxes are positioned

Layout of floating boxes.

A float can overlap boxes in its parent flow (e.g., when a normal flow box next to a float has negative margins). When an inline-level box overlaps with a float, it is rendered in front of the float. When a block-level box overlaps, it is rendered behind the float.

Here is an illustration, showing what happens when a float overlaps borders of elements in the normal flow.

Image showing a floating image that overlaps the borders of two
paragraphs: the borders are interrupted by the image.

A floating image obscures borders of block boxes it overlaps.

An old idea (at least from 1996) is to add a value 'contour' to 'float', so that the float is no longer rectangular, but takes on its "intrinsic" shape. This allows to wrap text around it much tighter. The syntax of 'float' becomes:

Value: [ <float-side> || <wrap-type> ] | inherit | initial

where <float-side> is: left | right | top | bottom | inside | outside | start | end | none; and <wrap-type> is box | contour. The default <float-side> is 'none' and the default <wrap-type> is 'box'.

How to find the shape of an object depends on the type of object. For a GIF or PNG image, the contour is the boundary between fully transparent parts of the image and the rest. For other objects, it is possible to define a 'shape' property to explicitly define the desired contour, but that may be taking it too far.

For a left-floating object, only the right and bottom edges of the contour are used, and the contour is "simplified" so that there are no holes and text is never interrupted by part of the float.

16. The clear property

Name: clear
Value: none | left | right | top | bottom | inside | outside | start | end | both | inherit | initial
Initial:    none
Applies to:    block-level elements
Inherited:    no
Percentages:    N/A
Media:    visual
Computed value specified value (except for 'inherit' and 'initial')

This property indicates which sides of an element's box(es) may not be adjacent to an earlier floating box. (It may be that the element itself has floating descendants; the 'clear' property has no effect on those.)

This property may only be specified for block-level elements (including floats). For compact and run-in boxes, this property applies to the final block box to which the compact or run-in box belongs.

Values have the following meanings when applied to non-floating block boxes:

left, top
If the element is in a horizontal flow, the top margin of the generated box is increased enough that the top border edge is below the bottom margin edge of any left-floating boxes that resulted from elements earlier in the source document. If the containing block has a vertical flow, the right margin is increased so that the right border edge is to the left of the left margin edge of any earlier top-floating boxes. In vertical-lr flow, the left margin is increased until the left border edge is to the right of the right margin edge of any earlier top floats.
right, bottom
Analogous, but the margin is increased to stay clear of any right/bottom floating boxes, rather than left/top ones.
inside
Same effect as 'left' or 'right' depending on whether the element's boxes will appears on a right, resp. left page in paged media. Same as 'left' on non-paged media. (See the Paged media module [ref] for information on left/right pages.)
outside
Same effect as 'right' or 'left' depending on whether the element's boxes will appears on a right, resp. left page in paged media. Same as 'right' on non-paged media.
both
The generated box is moved clear of both left/top and right/bottom floating boxes of earlier elements in the source document.
none
No constraint on the box's position with respect to floats.

[Be more precise about the order in which margins are established: collapse first, then add effect of clear; collapse positive margins only, then add 'clear, then add negative margins; collapse earlier elements only, then add clear, then collapse following elements... Need to dig out an old thread on www-style.]

When the property is set on floating elements, it results in a modification of the rules for positioning the float. An extra constraint is added:

[define vertical case]

Example. Assuming a rule such as this:

P { clear: left }

formatting might look like this:

Image showing a floating image and the effect of 'clear: left'
on the two paragraphs.

Both paragraphs have set 'clear: left', which causes the second paragraph to be "pushed down" to a position below the float -- its top margin expands to accomplish this.

17. The 'float-displace' property

Name: float-displace
Value: line | indent | block | block-within-page | none | inherit | initial
Initial: line
Applies to: all block-level elements
Inherited: yes
Percentages: N/A
Media: visual
Computed value Same as specified value
Computed value: specified value (except for 'inherit' and 'initial')

This property determines the line wrapping policy in the presence of floats. Values have the following meanings:

line
Line boxes should be shortened and moved so as to avoid floats. The margin, border, padding and background of the element are not affected by floats. (This is the behavior as described in CSS2.) [add description or image?]
indent
The distance from the margin edge of the floats and the start of the line box is set to the distance between the active reference indent edge (see the 'indent-edge-reset' property) and the content edge of the block box. This ensures that relative indents are preserved in the presence of floats.

Example of lines wrapping around a float individually.

Example

block

The containing block's width as used by the horizontal formatting model is reduced by the width of the floats intruding upon its content area (not taking into account floating descendants or floating elements that appear later in the document tree). The block is then flowed in this reduced containing block width.

If the effective containing block width is, by the algorithm given above, reduced to a value smaller than the sum of the margin-left, border-width-left, padding-left, width, padding-right, border-width-right, and margin-right values (treating any 'auto' values as zero) then the margin-top of the block is increased until the effective containing block width is no longer so constrained or until all floats have been cleared, whichever occurs first.

Example of blocks being made narrower because of floats

Example

block-within-page
As for the 'block' value, but the determination of intrusions that adjust the width of the block is done separately on each page on which the block appears. Thus, the block may be narrowed on the first page due to one or more intrusions, but may expand (or contract) its width on subsequent pages with different intrusions. The computed value of the 'width' property for this case is...?
none
The box is not affected by floats (except if 'clear' is not set to 'none').

A set of rules for HTML might look like this:

OL, UL, LI {float-displace: indent}
TABLE {float-displace: block}

Lines in a list will get extra indentation when they are next to a float, so you can still see that they are part of the list, and tables will be made narrower as a whole.

18. Collapsing margins

The top and bottom margins of a block-level box define the minimum distance of the box to block-level boxes above and below it. The actual distance between boxes is the maximum of the margins involved (unless there are any negative margins, see below). We say that such margins collapse.

For example, in this HTML fragment

<UL STYLE="margin-bottom: 1em">
  <LI STYLE="margin-bottom: 0.5em">...</LI>
</UL>
<P STYLE="margin-top: 0.6em">
  ...
</P>

and assuming there are no paddings and borders, the bottom of the last line box of the <LI> will be 1em above the top of the first line box of the <P>, since 1em is the maximum of the three margins.

The principle is that adjacent margins of block-level boxes in the same flow collapse. The precise rules are as follows.

When the margins of two or more boxes collapse, it means that the computed value of all margins involved is the maximum of the nonnegative specified margins plus the minimum of the negative specified margins.

Note that this means that "collapsing" is a commutative relation (if margin A collapses with margin B, then margin B collapses with margin A) as well as a transitive relation (if A collapses with B and B collapses with C, then A collapses with C).

For the purposes of these rules, elements with 'display: none' are treated as if they did not exist at all.

In a horizontal flow, the following margins collapse:

  1. The bottom margin of a box and the bottom margin of its last child, provided both are block-level and the former has no bottom padding, no bottom border and horizontal flow.
  2. The top margin of a box and the top margin of its first child, provided both are block-level and the former has no top padding, no top border and horizontal flow.
  3. The bottom margin of a box and the top margin of its next sibling, provided both are block-level.
  4. The top and bottom margin of a block-level box, if the the box has a height of 'auto' or 0, no top or bottom padding, no top or bottom border and no content (i.e., no line boxes and no replaced content).

Note that "no content" is not the same as "empty element" in XML terms. For example, an empty element may have content because of generated text[ref], and a nonempty element may have no content, when none of its descendants has any content. Example:

<style type="text/css">
  div.test:before {content: "Test"}
</style>

<div class="test"/>

<div><em></em></div>

The first div is an empty element, but does have content (and thus its top and bottom margins are not adjacent and do not collapse). The second div is not empty, but nevertheless it has no content, and its top and bottom margins are therefore adjacent and will collapse.

A vertical flow is analogous. To be precise, if the orientation of a flow is vertical:

  1. The left margin of a box collapses with the left margin of its last child, provided both are block level and the former has no left padding, no left border and vertical orientation.
  2. The right margin of a box collapses with the right margin of its first child, provided both are block level and the former has no right padding, no right border and vertical orientation.
  3. The left margin of a box and the right margin of its next sibling, provided both are block-level.
  4. The left and right margin of a block-level box, if it has a width of 'auto' or 0, no left or right padding, no left or right border and no content (i.e., no line boxes and no replaced content).

Analogously, if the orientation is vertical-lr, the following margins collapse:

  1. The right margin of a box and the right margin of its last child, provided both are block level and the former has no right padding, no right border and vertical-lr orientation.
  2. The left margin of a box and the left margin of its first child, provided both are block level and the former has no left padding, no left border and vertical-lr orientation.
  3. The right margin of a box and the left margin of its next sibling, provided both are block-level.
  4. The left and right margin of a block-level box, if it has a width of 'auto' or 0, no left or right padding, no left or right border and no content (i.e., no line boxes and no replaced content).

Note that margins of floating boxes do never collapse, neither with normal flow boxes nor with other floating boxes.

Here are some examples. Assume these style rules:

H1 { margin-bottom: 2.2em }
H2.subtitle { margin-top: -1em }
P { margin-top: 0.9em; margin-bottom: 0 }
UL { margin-top: 1.6em }
LI { margin-top: 0.6em }
BLOCKQUOTE.break { margin-top: 0.8em; border: thin solid }

In the following example, the bottom of the h1 and the top of the h2 collapse to a margin of 2.2em - 1em = 1.2em:

<H1>The flight of the bumblebee</H1>
<H2 CLASS=subtitle>Accompanied by winds and woods</H2>

In the following example the bottom of the first p, the top of the UL, the top of the LI and the top of the second P collapse to a margin of 1.6em = max(0, 1.6em, 0.6em, 0.9em):

<P>...in the following list:</P>
<UL>
  <LI><P>one item must be the first</P></LI>
</UL>

In the following example, the margins between the H1 and the BLOCKQUOTE collapse (2.2em), but the border of the BLOCKQUOTE keeps the P from collapsing with either of them. The P starts 0.9em below that border:

<H1>ceasar's words</H1>
<BLOCKQUOTE CLASS=break>
  <P>gallia est omnis divisa in partes tres...</P>
</BLOCKQUOTE>

Note that in paged media [ref] margins that occur at the top or bottom of a page disappear, in a mechanism similar to (but not the same as) collapsing.

Note that the combination of collapsing margins with floats can interfere with progressive rendering to a certain extent. For example, in the following situation, the position of the floating div won't be known until the position of the div after the float has been calculated, because the two margins (1em and 2em) have to collapse:

    ...
    This line is in the normal flow.
  </div>
  <div style="display: block; margin-top: 1em">
  <div style="float: left; background: silver">
    This is a floating div.
  </div>
  <div style="display: block; margin-top: 2em">
    This div is in the normal flow.
  </div>
</div>

Float positioned after margins are collapsed

The float is positioned to align with the top of the containing block, but the top of the containing block is influenced by the div after the float.

19. The line-height property

Name: line-height
Value: normal | <number> | <length> | <percentage> | inherit | initial
Initial: normal
Applies to: all elements
Inherited: yes
Percentages: refer to computed font-size of the element itself
Media: visual
Computed value 'normal', <number> or <length>

[This section and the two following ones ('line-height-policy' and 'line-box-contain') will eventually be moved to the "Line box model" module [CSS3-linebox].]

Sets the height of lines. Since a line may contain boxes belonging to different elements, the exact height of a line depends on the interaction between the line-height values of all those elements. See 'line-box-contain'. The values have the following meaning:

normal
The computed value is UA-dependent. It is recommended that UA's use either a <number> between 1.0 and 1.2 or a <length> between 1.0em and 1.2em.
<length>
Sets the computed value to this <length>. Negative values are illegal.
<percentage>
Sets the computed value to the percentage times the element's computed font size. Negative values are illegal.
<number>
Sets the computed value to the number times the element's computed font size. However, unlike for percentages, child elements inherit the number, not the computed value. Negative values are illegal.

The three rules in the example below have the same effective line height (12pt):

DIV { line-height: 1.2; font-size: 10pt }     /* number */
DIV { line-height: 1.2em; font-size: 10pt }   /* length */
DIV { line-height: 120%; font-size: 10pt }    /* percentage */

The computed value of 'line-height' is 'normal' when it is specified as 'normal' and a <number> when it is specified as a <number>. For example, if 'line-height' is '1' and 'font-size' is 12pt, the computed value that is inherited by the element's children is '1' and not '12pt', even though the latter is the actual value that is used for the element's own text.

Note: in CSS2 the percentage and the number were multiplied by the actual font size, not the computed size. This is changed in CSS3.

20. The line-height-policy property

[This is currently incompatible with CSS2. Needs further discussion.]

Determines how the height of line boxes is computed.

Name: line-height-policy
Value: normal | stack | enforce | snap | inherit | initial
Initial: normal
Applies to: inline elements
Inherited: yes
Percentages: N/A
Media: visual
Computed value specified value (except for 'inherit' and 'initial')
stack
The 'line-height' property of the inline box is ignored. Instead, there is a constraint on the line box in which this box is contained that its top must be as high as the margin-top of the inline box and the line box's bottom as low as the margin-bottom of the inline box.
enforce
The 'line-height' of the inline box is ignored. Instead, there is a constraint on the line box that it must be exactly as high as the 'line-height' property of the containing block. Note that 'vertical-align' does not play a role here.
normal
If the inline box is replaced, there is a constraint on the line box that its top must be as high as the margin-top of the inline box and the line box's bottom as low as the margin-bottom of the inline box. If the inline box is not replaced, there is a constraint that the line box must be as high as the 'line-height' value of the inline box. Note that in the latter case 'vertical-align' plays no role.
snap
As 'normal', but with the extra constraint that the height of the line box must be a multiple of the 'line-height' of the containing block.

The height of the line box can then be found by computing the smallest height for which all the constraints hold.

Note that in all cases except 'stack' the text of an inline, non-replaced box may end up partially or completely outside the line box, overlapping other line boxes. In the case the inline box has 'stack', that can only happen if it has negative margins.

Examples: To ensure that all lines are always exactly as high as the block's line-height, without regard for possible overlap because of superscripts or inline images, set this:

BODY { line-height-policy: enforce }

To make sure that a superscript does not overlap the previous line, but stays at least 0.1em away from the bottom of the previous line box, do this:

SUP { line-height-policy: stack; margin-top: 0.1em }

To ignore the size of an image and treat it almost as if it were a letter, allowing it to stick out of the line box:

IMG.letter-like { line-height-policy: enforce }

21. The line-box-contain property

[This is an alternative to the 'line-height-policy', due to David Baron]

Name: line-box-contain
Value: [ block || inline || font || text || replaced || inline-box ] | none | inherit | initial
Initial: block inline replaced
Applies to: all elements
Inherited: yes
Percentages: N/A
Media: visual
Computed value specified value (except for 'inherit' and 'initial')

This property enumerates the aspects of an element that contribute to the height of a line line box.

block
The logical box (whose height is the 'line-height' of the block) of the anonymous inline element established by a block-level element with this value must fit within the line box.
inline
The logical box (whose height is the 'line-height') of all non-replaced inline boxes with this value must fit within the line box.
font
The font bounding box of all non-whitespace characters contained as children of elements with this value must be included within the line box. [Do I mean the bounding box?]
text
The bounding box of all glyphs contained as children of elements with this value must be included within the line box. (This would be particularly useful for :first-letter pseudo-elements and probably for math.)
replaced
The margin box of all replaced elements with this value within the line must fit within the line box.
inline-box [or maybe inline-border and inline-margin]
The margin-box of all non-replaced inline elements with this value in the line must fit within the line box.
none
Elements with this value do not contribute to the size of the line box.

If the property has no value for all elements within a line, then the line box has 0 height, and the line within the anonymous inline established by the block that coincides with the line block is the baseline of that anonymous inline block (or should it be determined by the 'vertical-align' property of the block?). [This is arbitrary. Does anyone have better ideas?]

Note that the CSS2 model is equivalent to 'block inline replaced' but the backwards-compatible HTML model is similar to (but not exactly) 'font replaced' [1].

Concerns: * How does this work with the cascade? * What about determining the visual size of inline boxes?

[1] I believe the differences are restricted to the first line of LI elements, the last line of LI, DD, and DT elements, and issues concerning whitespace around images. [DB]

The height of each line box is established as follows (we describe the case for horizontal flow, but vertical flow is analogous). First align all the boxes on the line relative to each other according to the rules for 'vertical-align'. The line box must satisfy all of the following constraints:

  1. For each box on the line that has 'font' in its value of 'line-box-contain', the line box must be high enough to contain the top and bottom of that box's text.
  2. For each box that has 'inline' in 'line-box-contain', the top of the line box must be at least as high as the top of the box's text plus the box's half-leading. The bottom of the line box must be at least as low as the bottom of the text plus the half-leading.
  3. For each box that has 'inline-box' in 'line-box-contain', the top of the line box must be at least as high as the margin-top of this box. The bottom of the line box must be at least as low as the margin-bottom.
  4. For each replaced box that has 'replaced' in its 'line-box-contain', the line box must contain the margin-top and margin-bottom of this box. [The value 'replaced' is not strictly needed. 'Inline-box' also does the job, except that it is not automatically restricted to replaced elements.]
  5. For each box that has 'text' in 'line-box-contain', the top of the line box must be at least as high as the top of each glyph in the box (excluding those in child elements). The bottom of the line box must be at least as low as the bottom of each glyph in the box (excluding child elements).
  6. If the enclosing block for this line has 'block' in 'line-box-contain', then the top of the line box must be at least as high as the text top plus the half-leading of an anonymous inline element and the bottom of the line box as low as the text bottom plus the half leading. This must hold whether or not this line actually contains such an element.

Thus 'block' can be used to set an overall minimum line height (viz. the value of 'line-height' of the element itself) for all lines in an element, independent of the actual contents of each line. In particular, setting 'line-box-contain' to just 'block' and no other values will ensure that all lines are the same height, at the possible risk of some tall inline elements overlapping with lines above or below.

The half-leading of a box is defined as half the computed value of 'line-height' minus half the computed value of 'font-size', i.e., (line-height - font-size)/2.

The top of the text is the top of the em-box of a box's nominal font, whether or not there actually is any letter that tall. Replaced elements, for example, have no text, but still have a nominal font and are thus a text top. The rules above refer to the position of the text top after the box has been aligned with 'vertical-align'.

22. The overflow property

Name: overflow
Value: visible | hidden | scroll | auto | inherit | initial
Initial: visible
Applies to: block-level and replaced elements
Inherited: no
Percentages: N/A
Media: visual
Computed value specified value (except for 'inherit' and 'initial')

This property specifies whether the content of a block-level or replaced element is clipped when it overflows the element's box (which is acting as a containing block for the content). Values have the following meanings:

visible
This value indicates that content is not clipped, i.e., it may be rendered outside the content box.
hidden
This value indicates that the content is clipped and that no scrolling mechanism should be provided to view the content outside the clipping region; users will not have access to clipped content. The size and shape of the clipping region is specified by the 'clip' property.
scroll
This value indicates that the content is clipped and that if the user agent uses a scrolling mechanism that is visible on the screen (such as a scroll bar or a panner), that mechanism should be displayed for a box whether or not any of its content is clipped. This avoids any problem with scrollbars appearing and disappearing in a dynamic environment. When this value is specified and the target medium is 'print' or 'projection', overflowing content should be printed.
auto
The behavior of the 'auto' value is UA-dependent, but should cause a scrolling mechanism to be provided for overflowing boxes.

[Michel has an interesting proposal to allow overflowing text to be indicated by an ellipsis ("…") or other text ("More…"), both for individual overflowing lines and for overflowing blocks.]

[Automatic scrolling (the "marquee" effect) is an alternative way to deal with overflow. Should it be added to 'overflow' with maybe one or two extra properties to control speed and direction?]

Even if 'overflow' is set to 'visible', content may be clipped to a UA's document window by the native operating environment.

Example(s):

Consider the following example of a block quotation (BLOCKQUOTE) that is too big for its containing block (established by a DIV). Here is the source document:

<DIV>
<BLOCKQUOTE>
<P>I didn't like the play, but then I saw
it under adverse conditions - the curtain was up.
<DIV class="attributed-to">- Groucho Marx</DIV>
</BLOCKQUOTE>
</DIV>

Here is the style sheet controlling the sizes and style of the generated boxes:

DIV { width : 100px; height: 100px;
      border: thin solid red;
      }

BLOCKQUOTE   { width : 125px; height : 100px;
      margin-top: 50px; margin-left: 50px; 
      border: thin dashed black
      }

DIV.attributed-to { text-align : right; }

The initial value of 'overflow' is 'visible', so the BLOCKQUOTE would be formatted without clipping, something like this:

Rendered overflow

Setting 'overflow' to 'hidden' for the DIV element, on the other hand, causes the BLOCKQUOTE to be clipped by the containing block:

Clipped overflow

A value of 'scroll' would tell UA's that support a visible scrolling mechanism to display one so that users could access the clipped content.

Implementation note: it is recommended that scrolling causes the content and the padding to scroll, but the border and the margin to remain fixed. Also, any visible scrolling mechanism (scrollbars, panner, etc.) should be placed just inside the border.

The combination of collapsing margins, 'max-height' and 'overflow: auto' can lead to subtle differences in implementations, unless special care is taken. A UA should assume that an element can be rendered without a scrolling mechanism first, perform all the collapsing of margins, and check that the content height is indeed less than the 'max-height'. If it is not, the process is repeated under the assumption that a scrolling mechanism is needed.

In the following document fragment, the outer DIV has 'height: auto', but 'max-height: 5em'. The inner DIV has large margins that do not fit in 5em, but a small content that does:

...
    #d1 { overflow: auto; max-height: 5em }
    #d2 { margin: 3em; line-height: 1 }
...
<div id="d1">
  <div id="d2">
    This DIV has big margins.
  </DIV>
</DIV>

If we assume that d1 needs scroll bars, then all contents of d1 will be inside the scrolling region, including the single line of text and twice 3em of margins, which adds up to 7em. Since 7em is greater than 5em, the maximum allowed height, it seems we made the right assumption and d1 indeed needs scrollbars.

However, we should have started by assuming that no scrollbars are needed. In that case the margins of d2 collapse with the margins of d1 and the content height of d1 is just the height of the line of text, 1em, which is less than 5em, proving that the assumption was correct and d1 indeed should not have scrollbars.

23. The clip property

[Implementation of 'clip' in CSS2 only seem to apply it to positioned elements. Do we restricts it to those? If so, we should move the property to the Positioning module.]

Name: clip
Value:    | auto | <shape> | inherit | initial
Initial:    auto
Applies to:    block-level and replaced elements
Inherited:    no
Percentages:    N/A
Media:    visual
Computed value specified value (except for 'inherit' and 'initial')

A clipping region defines what portion of an element's rendered content is visible. By default, the clipping region has the same size and shape as the element's box(es). However, the clipping region may be modified by the 'clip' property.

Note that the 'clip' property only has effect on elements that have a 'overflow' property with a value other than 'visible'. <shape> is either 'rect(...)' or 'inset(...)'. Values have the following meanings:

auto
The clipping region has the same size and location as the element's content area(s).
rect(T, R, B, L)
The clipping region is a rectangle, defined by four offsets from the top-left corner of the element's content area, definining, respectively, the top, right, bottom and left edge of the clipping region.
inset(T, R, B, L) [was this the agreed-upon name?]
The clipping region is a rectangle, defined by four offsets: B is the offset of the top of the clipping region from the top of the content area, R from the right, B from the bottom and L from the left.

<top>T, R, B and L may either be a <length> value or 'auto'. Negative lengths are permitted. The value 'auto' means that the given edge of the clipping region will be the same as the edge of the element's content box.

diagram of rect vs inset

Diagram of the rectangles defined by rect() and inset().

When coordinates are rounded to pixel coordinates, care should be taken that no pixels remain visible when R - L = 0 or B - T = 0, and conversely that no pixels remain hidden when R is equal to the element's width and B equal to the element's height.

The element's ancestors may also have clipping regions (in case their 'overflow' property is not 'visible'); what is rendered is the intersection of the various clipping regions.

If the clipping region exceeds the bounds of the UA's document window, content may be clipped to that window by the native operating environment.

Example(s):

The following rule:

IMG { clip: rect(5px, 40px, 45px, 5px); }

will create the rectangular clipping region delimited by the dashed line in the following illustration:

A clipping region

An image of 50 by 55 pixels is clipped with a clipping mask of 35 by 40 pixels.

The following two rules are equivalent. Both of them clip the img element so that only the upper right corner is visible:

img { overflow: hidden; clip: rect(0, 100%, 30%, 70%) }
img { overflow: hidden; clip: inset(0, 0, 70%, 70%) }

Note. In CSS3, all clipping regions are rectangular. It is possible that future extensions permit non-rectangular clipping.

24. The visibility property

Name: visibility
Value:    visible | hidden | collapse | inherit | initial
Initial:    visible
Applies to:    all elements
Inherited:    yes
Percentages:    N/A
Media:    visual
Computed value specified value (except for 'inherit' and 'initial')

The 'visibility' property specifies whether the boxes generated by an element are rendered. Invisible boxes still affect layout. (Set the 'display' property to 'none' to suppress box generation altogether). Values have the following meanings:

visible
The generated box is visible.
hidden
The generated box is invisible (fully transparent), but still affects layout.
collapse
Please consult the section on dynamic row and column effects [ref] in tables. If used on elements other than rows or columns, 'collapse' has the same meaning as 'hidden'.

Note that there is a separate property 'opacity' (see the Color module [CSS3-color]) to set the transparency of elements to values between fully opaque and fully transparent.

In the following example, pressing either form button invokes a user-defined script function that causes the corresponding box to become visible and the other to be hidden. Since these boxes have the same size and position, the effect is that one replaces the other. (The script code is in a hypothetical script language. It may or may not have any effect in a CSS-capable UA.)

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN">
<HTML>
<HEAD>
<STYLE type="text/css">
<!--
   #container1 { position: absolute; 
                 top: 2in; left: 2in; width: 2in }
   #container2 { position: absolute; 
                 top: 2in; left: 2in; width: 2in;
                 visibility: hidden; }
-->
</STYLE>
</HEAD>
<BODY>
<P>Choose a suspect:</P>
<DIV id="container1">
   <IMG alt="Al Capone" 
        width="100" height="100" 
        src="suspect1.jpg">
   <P>Name: Al Capone</P>
   <P>Residence: Chicago</P>
</DIV>

<DIV id="container2">
   <IMG alt="Lucky Luciano" 
        width="100" height="100" 
        src="suspect2.jpg">
   <P>Name: Lucky Luciano</P>
   <P>Residence: New York</P>
</DIV>

<FORM method="post" 
      action="http://www.suspect.org/process-bums">
   <P>
   <INPUT name="Capone" type="button" 
          value="Capone" 
          onClick='show("container1");hide("container2")'>
   <INPUT name="Luciano" type="button" 
          value="Luciano" 
          onClick='show("container2");hide("container1")'>
</FORM>
</BODY>
</HTML>

25. Profiles

There are 3 modules defined by this chapter:

  1. CSS1 box model: horizontal text, floats
  2. CSS2 box model: CSS1 plus run-in
  3. CSS3 box model: CSS2 plus vertical, baseline-identifier, line-height-policy

The 3 modules consist of the following properties/values:

CSS1 box model
  • width, height
  • border properties, margin properties, padding properties
  • float (left, right, none), clear (left, right, both, none)
  • line-height
  • [...]
CSS2 box model CSS1 box model, plus:
  • min-width, max-width, min-height, max-height
  • [...]
CSS3 box model CSS2 box model plus:
  • box-sizing
  • float (top, bottom, inside, outside), clear (top, bottom, inside, outside)
  • [...]

26. Conformance

[...]


Acknowledgements

[acknowledgements. David Baron, Ian Hickson]

David Baron discovered that the assumption about whether a scrolling mechanism is needed can influence whether it is indeed needed or not. See under

References

[CSS3-color]
Tantek Çelik; Chris Lilley. CSS3 module: color. 5 March 2001. W3C working draft. (Work in progress.) URL: http://www.w3.org/TR/2001/WD-css3-color-20010305
[CSS3-linebox]
Eric A. Meyer. CSS3 module: linebox model. (forthcoming). W3C working draft. (Work in progress.)
[CSS3-positioning]
Bert Bos. CSS3 module: absolute positioning. (forthcoming). W3C working draft. (Work in progress.)
[CSS3-text]
Michel Suignard; Chris Lilley (eds). CSS3 module: text. 17 May 2001. W3C working draft. (Work in progress.) URL: http://www.w3.org/TR/2001/WD-css3-text-20010517
[SMIL1.0]
Various. Synchronized Multimedia Integration Language (SMIL) 1.0 Specification. June 1998. W3C Recommendation. URL: http://www.w3.org/TR/1998/REC-smil-19980615
[SVG1.0]
Various. Scalable Vector Graphics (SVG) 1.0 Specification. 2 August 2000. W3C Candidate Recommendation. URL: http://www.w3.org/TR/2000/CR-SVG-20000802
[XLink1.0]
DeRose, Steve; Maler, Eve; Orchard, David; Trafford, Ben. XML Linking Language (XLink) Version 1.0. 3 July 2000. W3C Candidate Recommendation. URL: http://www.w3.org/TR/2000/CR-xlink-20000703

Index

Property index

Property Values Initial Applies to Inh. Percentages Media
border , border-top, border-right, border-bottom, border-left [ <border-width> || <border-style> || <border-color> ] | inherit | initial none all elements no N/A visual
border-break open | close | inherit | initial open elements with a border yes N/A visual
border-color <border-color>{1,4} | inherit | initial (see individual properties) all elements no N/A visual
border-radius-topright, border-radius-bottomright, border-radius-bottomleft, border-radius-topleft, border-radius <length> <length>? | inherit | initial 0 all elements no N/A visual
border-style <border-style>{1,4} | inherit | initial (see individual properties) all elements no N/A visual
border-top-color , border-right-color, border-bottom-color, border-left-color <color> | transparent | inherit | initial the value of the 'color' property all elements no N/A visual
border-top-style , border-right-style', border-bottom-style, border-left-style <border-style> | inherit | initial none all elements no N/A visual
border-top-width , border-right-width, border-bottom-width, border-left-width <length> | thin | medium | thick | inherit | initial medium all elements no N/A visual
border-width <border-width>{1,4} | inherit | initial (see individual properties) all elements no N/A visual
box-sizing content-box | border-box | inherit | initial content elements to which 'width' or 'height' applies no N/A visual
box-width, box-height <length> | <percentage> | auto | inherit | initial auto same as 'width' and 'height' no see 'width' and 'height' visual
clear none | left | right | top | bottom | inside | outside | start | end | both | inherit | initial none block-level elements no N/A visual
clip | auto | <shape> | inherit | initial auto block-level and replaced elements no N/A visual
collapse none | <'content'> | first-child | inherit | initial none all elements no N/A interactive visual
content [ <string> | <uri> | <counter> | attr(X) | open-quote | close-quote | no-open-quote | no-close-quote ]+ | link | normal | inherit auto all elements no N/A all
display inline | block | inline-block | list-item | run-in | compact | marker | table | inline-table | table-row-group | table-header-group | table-footer-group | table-row | table-column-group | table-column | table-cell | table-caption | ruby | ruby-base | ruby-text | ruby-base-group | ruby-text-group | none | inherit | initial inline all elements no N/A visual ('none' applies to all)
display-model inline-inside | block-inside | table | ruby | inherit | initial text all elements no N/A visual
display-role none | block | inline | list-item | marker | run-in | compact | table-row | table-cell | table-row-group | table-header-group | table-footer-group | table-column | table-column-group | table-caption | ruby-text | ruby-base | ruby-base-group | ruby-text-group | inherit | initial inline all elements no N/A visual
fit fill | none | meet | slice | inherit | initial fill replaced elements yes N/A visual
fit-position [ [<percentage> | <length> ]{1,2} | [ [top | center | bottom] || [left | center | right] ] ] | auto | inherit | initial 0% 0% replaced elements yes refer to width and height of box itself visual
float left | right | top | bottom | inside | outside | start | end | none | inherit | initial none all but positioned elements and generated content no N/A visual
float-displace line | indent | block | block-within-page | none | inherit | initial line all block-level elements yes N/A visual
line-box-contain [ block || inline || font || text || replaced || inline-box ] | none | inherit | initial block inline replaced all elements yes N/A visual
line-height normal | <number> | <length> | <percentage> | inherit | initial normal all elements yes refer to computed font-size of the element itself visual
line-height-policy normal | stack | enforce | snap | inherit | initial normal inline elements yes N/A visual
link-behavior normal | pop-up | confirm | expand | none | inherit | initial normal link elements (unless 'content' is 'link'), and collapsed elements yes N/A all
margin [ <length> | <percentage> | auto ]{1,4} | inherit | initial (see individual properties) all elements no width* of containing block visual
margin-top , margin-right, margin-bottom, margin-left, margin-inside, margin-outside <length> | <percentage> | auto | inherit | initial 0 all elements no width* of containing block visual
max-width, max-height <length> | <percentage> | auto | inherit auto same as 'width' and 'height' no see 'width' and 'height' visual
min-width , min-height <length> | <percentage> | inherit | initial 0 same as 'width' and 'height' no see 'width' and 'height' visual
overflow visible | hidden | scroll | auto | inherit | initial visible block-level and replaced elements no N/A visual
padding [ <length> | <percentage> ]{1,4} | inherit | initial (see individual properties) all elements no width* of containing block visual
padding-top , padding-right, padding-bottom, padding-left [ <length> | <percentage> ] | inherit | initial 0 all elements no width* of containing block visual
visibility visible | hidden | collapse | inherit | initial visible all elements yes N/A visual
width, height <length> | <percentage> | auto | inherit | initial auto all elements, except inline-level elements with 'display-model' of 'text' no width, resp. height of containing block, but see prose visual