Copyright ©2001 W3C® (MIT, INRIA, Keio), All Rights Reserved. W3C liability, trademark, document use and software licensing rules apply.
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).
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.
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:
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.
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.
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.
Here are some definitions (the values of the properties refer to the computed values [reference]):
Note that if this nearest ancestor has columns, the containing block is a column. See the multicolumn module[ref].
@link
' rule and the 'collapse' property.
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.
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.
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.)
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:
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:
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.
Note that :before and :after pseudo elements of this element are also not rendered, see [generated].)
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.
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:
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.
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?]
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).
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:
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.
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.
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.
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).
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.
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.]
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:
[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").
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:
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
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:
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 }
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'
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.
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.
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:
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.
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:
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.
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.
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:
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:
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...
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:
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.]
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?]
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:
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.
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?]
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.
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.
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:
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:
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.
'direction' | effect |
---|---|
ltr | left/top |
rtl | right/bottom |
horizontal | vertical | vertical-lr | |
---|---|---|---|
ltr | right | bottom | bottom |
rtl | left | top | top |
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):
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.
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.
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.
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:
[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:
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:
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.
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.
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:
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:
Analogously, if the orientation is vertical-lr, the following margins collapse:
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>
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:
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.
[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') |
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 }
[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.
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:
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'.
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:
[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.
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:
Setting 'overflow' to 'hidden' for the DIV element, on the other hand, causes the BLOCKQUOTE to be clipped by the containing block:
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.
[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:
<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.
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.
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:
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.
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:
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>
There are 3 modules defined by this chapter:
The 3 modules consist of the following properties/values:
CSS1 box model |
|
CSS2 box model | CSS1 box model, plus:
|
CSS3 box model | CSS2 box model plus:
|
[...]
[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
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 |