CSS basic box model

[LONGSTATUS] [DATE: 26 Sep 2006]

This version:
[VERSION]
Latest version:
[LATEST]
Previous version:
[PREVIOUS]
Feedback:
www-style@w3.org with subject line “[css-box-3] … message topic …” (archives)
Editors:
, W3C,
Anton Prowse, Invited Expert,

Abstract

Status of this document

The CSS Working Group plans to ask for W3C Recommendation status for this specification only when there are sufficiently many implementations. See the section “CR exit criteria” for details.

This draft is undergoing changes and many parts are not consistent with other modules of CSS.

Please, refer to CSS level 2 [[!CSS21]] instead for the definition of the basic box model.

This module should eventually replace corresponding parts of the revised CSS level 2 specification [[!CSS21]]. But this is an early draft and any differences to level 2 are most likely unintentional, unless they concern new features, such as vertical text or float displacement. Please help us improve the next draft by pointing out such differences.

How to read this specification

All sections are normative, unless stated otherwise.

Examples look like this and normally start with the word “Example.” Examples are not normative.

Notes look like this and normally start with the word “Note.” Notes are not normative.

Editorial notes look like this. They will be removed before the document becomes Candidate Recommendation.

Each property is defined in part in the text and in part by a table that groups together a number of facts about the property, including a regular expression to restrict its syntax. See [where?] for the meaning. The “Inherited” and “Initial” rows in the table are used by the Cascading and Inheritance module [[CSS3CASCADE]] and “Media” by the Media Queries specification [[MEDIAQ]].

The specification may refer to the used value and the computed value of a property. Unless stated explicitly, the short form “value” means the computed value.

Dependencies on other modules

This CSS module depends on the following other CSS modules:

Introduction & definitions

Some issues that affect multiple sections in this document:

Horizontal centering (more precisely: centering in the inline direction). The draft contains several suggestions:

  1. Setting 'margin' to ''fill''. ''Fill'' is similar to ''auto'', but allowed to be negative:
    P {margin: 1em fill}
  2. Setting a property 'alignment' on the element to center:
    P {alignment: center}
  3. Setting a property 'child-align' on the parent of the element to center:
    DIV {child-align: middle}
  4. Rely on grid templates [[CSS3LAYOUT]]. You set a template on the parent or on the element itself. One or the other may be easier. E.g., to horizontally center the single child of a horizontal DIV):
    DIV {grid: ". @ ." }

    To horizontally center a P with a template on the P itself requires that the width of the P isn't set with the 'width' property, but with the 'grid-columns' property (or the 'grid' shorthand). In the example below the width is set to 'fit-content':

    P {grid: * fit-content *  ".  @ ."}

    To vertically center the single child of a vertical DIV:

    DIV {grid: "@"}
    DIV:slot(@) {vertical-align: middle}

    To vertically center a P inside a vertical parent by means of a template on the P itself requires that the height of the P isn't set with 'height', but with 'grid-rows' (or the 'grid' shorthand). Below, the height is set to 10em:

    P {grid: "." *
             "@" 10em
             "." * }

    See also ACTION-18 (especially the ideas at end of Bert's comment ), which is continued in ISSUE-53.

Ensuring that the bottom padding (more precisely: the foot padding) starts after any preceding and descendant floats.

The main use case is to make sure an element is at least as high as all its floating descendants. I.e., at the end of the element, clear the floats that are descendants of the element. That may or may not also clear any floats that were declared before the element. Some possible approaches:

  1. Set 'overflow' to anything else than 'visible' (and 'height' to 'auto'). This requires no new property, but has the side effect of influencing the scrolling mechanism. It also doesn't clear any floats that occurred before the element and doesn't distinguish left, right or other floats. [2004-02-29 ftf]
  2. A new property 'clear-after'.
  3. Use the value ''shrink-wrap'' (or some other name, e.g., ''contain'') on 'height' (and 'width', in case of vertical text) to make an element into a flow root. This requires no new property, only a new value, but doesn't clear any floats before the element and doesn't distinguish left, right or other floats. [The idea to add the functionality to 'height' is due to IanH 2004-02-29]
  4. The same, but only allow the new keyword on the 'min-height' and 'min-width' properties. [The idea to add the functionality to 'min-height' is due to Fantasai, 2012-09]
  5. A new value ''container'' on 'display'. This doesn't allow a ''list-item'' to clear its floats.

Vertical centering and alignment (more precisely: in the block flow direction).

The use cases are centering a single child vertically in its parent, centering all content of an element vertically (e.g., all text on a slide) and aligning only the last child (or the last n children) against the bottom of the parent.

Possible solutions include:

  1. No new features, just use absolute positioning and transformations together:

    .container {
       height: 10em; /* Some sufficient height */
       position: relative }
    .container > * {
       margin: 0;
       position: absolute;
       top: 50%;
       transform: translate(0, -50%) }

    (The 'top' moves the top down by half the container's height, the 'transform' moves the top up by half the element's own height.) This only works if we are sure the container is tall enough, because it will not automatically grow. It only works if there is exactly one child: it cannot center a sequence of paragraphs in a DIV, nor the text content of a P.

  2. No new features, just use flexbox: Set 'display: flex', 'flex-direction: column' and 'justify-content: center' on the container. This has the side effect of changing both the container and the children to block boxes, and inhibiting margin collapsing between the children, so it isn't suitable to, e.g. vertically center a set of list items in a UL, or the text content of a P.

  3. Extending 'vertical-align' to apply to block elements:
    DIV {vertical-align: middle}

    This centers or aligns all content, it cannot top-align the first child and bottom-align the last.

  4. Allowing 'vertical-align' on a new type of box called ''container''. (The main function of ''container'' is to contain its floating descendants.) This wouldn't allow a ''list-item'', a ''table-caption'' or an 'inline-block'' to center its content.')
  5. Setting 'margin' to ''fill'':
    P {margin-top: fill}

    This works to center an element in its parent, but not to center the content of an element with only text.

  6. Relying on grid templates [[CSS3LAYOUT]]. If there are enough elements, that could work:
    <STYLE>
     BODY {grid: "a . b"} /* 3 columns */
     SECTION.a {flow: a; grid: "@" "." "z"} /* 3 rows */
     SECTION.b {flow: b; grid: "@" "." "z"} /* 3 rows */
     P.note {flow: z}
    </STYLE>
    <SECTION CLASS=a>
     <H1>...</H1>
     <P>...
     <P CLASS=note>...
    </SECTION>
    <SECTION CLASS=b>
     <H1 ID=b>...</H1>
     <P>...
     <P CLASS=note>...
    </SECTION>
    

    And assuming 'vertical-align' applies to slots, then that also vertically centers the contents of an element. (This centers horizontally if the element is vertical, because 'vertical-align' is relative to the writing mode.)

    P {grid: "@"}
    P:slot(@) {vertical-align: center}

    But it is not enough to bottom-align the two paragraphs with class “note” in this example:

    <STYLE>
     BODY {grid: "a . b"}
     H1#a, H1#a ~ P {flow: a}
     H1#b, H1#b ~ P {flow: b}
     P.note {/* align to bottom?? */}
    </STYLE>
    <H1 ID=>...</H1>
    <P>...
    <P CLASS=note>...
    <H1 ID=b>...</H1>
    <P>...
    <P CLASS=note>...
    
  7. Use centering in the inline direction after switching the parent to an orthogonal block flow direction. E.g., if the document is horizontal and we want to vertically center the single child of a DIV:

    DIV {writing-mode: vertical-rl}
    DIV > * {writing-mode: horizontal; width: 100%;
      margin-top: auto; margin-bottom: auto}

    This cannot top-align the first child and bottom-align the second.

  8. Vertically centering a single element could also be modeled as a float with an offset. A draft of [[CSS-PAGE-FLOATS]] from 2013 suggests the following to center a P vertically inside its parent DIV:

    DIV {height: 15em;
      colums: 1}            /* Make the DIV act like a "page" */
    P {float: top left;     /* Place the P in the corner of the DIV... */
      float-offset: 0 50%}  /* ... and add 50% offset vertically */

    Floats like this also allow to put all children at the top and the last child against the bottom. But only one child: trying to push multiple children down to the bottom results in their order being reversed.

Investigate if it is possible to make a pseudo-element to select anonymous boxes ('::paragraph'). See minutes of 10 Aug 2011.

Note: The model in this specification differs from the model described in the CSS level 2 specification [[!CSS21]], because it is generalized to apply also to vertical text. A document using only features from level 2 renders exactly as described there, (except possibly for features that are undefined in that specification and have become defined since).

CSS assumes that the document to lay out is modeled as a tree of elements. Each element has an ordered list of zero or more child elements, with an optional string of text before the list, in-between the children and after the list. Each child has one parent, except for the unique element that has no parent, which is called the root element.

Note that such a tree can be described in XML or SGML, but also in other notations and that it is the definition of that notation, not CSS, that determines the equivalence between the abstract tree and the concrete notation. E.g., SGML often allows white space to be added between elements for readability, which does not result in a string of spaces in the abstract tree.

CSS describes how each element and each string of text is laid out by transforming the document tree into a set of rectangular boxes, whose size, position, and stacking level on the canvas depend on their properties. We say that an element generates one or more boxes. There are numerous different types of boxes. [Or maybe only one? I.e., a block-level box is just a normal box that happens to be generated by a block-level element?] A block box is like a paragraph; a line box is like a single line of text; and inline boxes are like words inside a line.

Define the box tree. (Is the space between words a kind of box as well, or a spacer item? Is the current selection a box? Is there a defined order among sibling boxes? If so, are bidi inline boxes ordered in reading order or in visual order?)

[Define the box tree before pagination and then describe how pagination can break one box into two?]

When the specification says a box A contains a box B it means B is a child of A in the box tree. Typically, box B is geometrically contained within box A as well, but that need not be the case, because of, e.g., overflow or negative margins.

Note: The precise rules are below and in other modules, but in summary, [write something that helps convey the idea of a flow, e.g.:] a block-level box contains either other block-level boxes (e.g., a section containing paragraphs, or a table containing rows), or it contains line boxes (e.g., a paragraph containing lines of text). A line box contains inline-level boxes (e.g., a line with words in different styles). An inline-level box may contain either text interspersed with more inline-level boxes, or it may contain a block-level box (e.g., a small table that is rendered inline).

Each generated box in the rendering
  has a link to the element that generated it.

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

For example, a fragment of HTML such as

<ul>
 <li>The first item in the list.
 <li>The second item.
</ul>

may result in [rewrite the following sentence?] one block-level box for the ul element, containing two block-level boxes for the two li elements, each of which has one line box (i.e., one line of text). Both line boxes contain two inline-level boxes: one that contains the list bullet and one that contains the text.

Note how the li is transformed into multiple boxes, including one that contains “generated content,” viz., the list bullet, which is not present in the source document.

If the document is rendered in a narrow window, it may be that the li elements get transformed into even more boxes, because the text requires multiple lines. And if the document is rendered on paper or in multiple columns, it may be that a page break falls in the middle of the ul element, so that it is not transformed into a single block-level box, but into two smaller ones, each on a different page or column.

Each box belongs to exactly one element. It is either generated directly by the element, or it is an anonymous box, which has been inserted to ensure that every box and its parent are of mutually compatible types as defined by the layout rules of CSS. An anonymous box is defined to belong to whichever element generates the box's closest element-generated ancestor box. When we need to be precise, we say that the anonymous box is induced, rather than generated, by the element it belongs to.

For example, an anonymous table wrapper box that is created around a table cell because the table cell element doesn't have a table element as parent, belongs to the parent element of the table cell, not to the table cell itself.

An anonymous box is never a principal box. Except for that, an anonymous box cannot be distinguished by its property values and characteristics from a box generated by some hypothetical document element. Remove this note? Do we actually use the concept of “principal box” anywhere?

Properties are set on elements [[!CSS3CASCADE]] and influence how the element is turned into boxes. Every box has the same properties with the same values as the element to which it belongs, except for anonymous boxes: inheritable properties on anonymous boxes have the same value as the element, while non-inheritable properties have the initial value. The only property that boxes do not have is the 'display' property. [Is this useful? Or is it better to say that boxes are just rectangles with a border, a background, a position, a bunch of other boxes inside, and a reference to the element they belong to? They don't really have properties then and it is only a convenience to say the “the box has a font X.

Boxes do not have specified values [[!CSS3CASCADE]], but they do have computed, used and actual values.

Boxes are frequently referred to by their property values. For example, a “floated box” is a box whose computed value of 'float' is not ''none'', and a “positioned box” is a box whose computed value of 'position' is not ''static''. However, terms such as block-level box, block container box and table box describe characteristics which cannot be deduced solely from a box's property values.

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

The various areas and edges of a typical box

Boxes have padding, a border and margins (see the figure). Different properties determine the thickness of each of these (which may be zero). The margins of adjacent boxes are also subject to collapsing (i.e., the actual margin between adjacent boxes may be less than the sum of the boxes' individual margins).

Each box has a content area (a.k.a. content box). The rectangle that bounds this area is the content edge. Around the content area is the padding area and its outside bounds are called the padding edge. The padding area and content area together form the padding box. Outside the padding is the border area and the outside boundary of that area is the border edge. The border area, padding area and content area together form the border box. Finally, outside the border is the margin area and its outer edge is the margin edge.

When the specification says that the padding or border is “absent” on some side of the box, that means that its thickness is zero.

Line boxes cannot have any padding, border or margin, and therefore their margin edge, border edge, padding edge and content edge all coincide.

Note that the margin, unlike the border and padding, may have a negative thickness. That is one way to make adjacent boxes overlap each other.

Note that the edges always form rectangles, even if there is a 'border-radius' [[CSS3BG]] or a shape [[CSS3-EXCLUSIONS]].

We say that a box or element is horizontal if its 'writing-mode' property is ''horizontal-tb'', otherwise it is vertical.

Note that there are theoretically eight possible orientations for text, but CSS only defines six:

'writing-mode: horizontal-tb' 'writing-mode: vertical-rl' 'writing-mode: vertical-lr'
'direction: ltr'

Text is written from left to right and paragraphs grow downwards

Text is written top to bottom and paragraphs grow to the left

Text is written top to bottom and paragraphs grow to the right

'direction: rtl'

Text is written from right to left and paragraphs grow downwards

Text is written bottom to top and paragraphs grow to the left

Text is written bottom to top and paragraphs grow to the right

There is no “horizontal-bt.” More information about 'writing-mode' and 'direction' can be found in [[!CSS3-WRITING-MODES]].

Calculations of the size and position of boxes are usually very similar for horizontal and vertical boxes, except that the horizontal and vertical directions are interchanged. To avoid many almost identical definitions, this specification therefore often uses abstract terms instead of top, right, bottom, left, width and height: four terms (block-start, block-end, inline-start and inline-end) for the four edges of a box, four terms (A edge, B edge, C edge and D edge) for the edges of the children of a box and two terms (measure and extent) for the width and height of a box.

XSL-FO [[XSL11]] uses “inline-progression dimension” for “measure” and “block-progression dimension” for “extent.”

The block-start, block-end, inline-start and inline-end edge of a box refer to the top, right, bottom and left edges, depending on the 'writing-mode' and 'direction' properties of that box, as follows:

'writing-mode' 'direction' “block-start” “inline-end” “block-end” “inline-start” Diagram
''horizontal-tb'' ''ltr'' top right bottom left
''rtl'' top left bottom right
''vertical-rl'' ''ltr'' right bottom left top
''rtl'' right top left bottom
''vertical-lr'' ''ltr'' left bottom right top
''rtl'' left top right bottom

For example, the “block-start padding” by default refers to the 'padding-top' and the “inline-end border” is by default the 'border-right'.

Similarly, the specification sometimes refers to the measure and extent of a box, instead of width and height, as follows:

'Writing-mode' “measure” “extent”
''horizontal-tb'' width height
''vertical-rl'' height width
''vertical-lr'' height width

These correspond to the dimensions in the inline base direction and the block flow direction, respectively.

An alternative term for the measure is logical width and an alternative term for extent is logical height. These terms occasionally occur in other CSS modules.

The extent of a box is thus the distance between the block-start and block-end edges, while the measure of the box is the distance between the inline-start and inline-end edges.

When boxes are laid out to form a flow (see below), their edges play different roles in the alignment of the boxes within that flow. The orientation of the flow determines which edge of a box is aligned to which edge of another box. These roles are independent of the orientation of the box itself. We distinguish four roles for the edges of a box, called A edge, B edge, C edge and D edge. They depend on the 'writing-mode' and 'direction' properties of the box's containing block (defined below), and map to the four sides as follows:

'writing-mode' of
containing block
'direction' of
containing block
“A edge” “B edge” “C edge” “D edge”
''horizontal-tb'' ''ltr'' top right bottom left
''rtl'' top left bottom right
''vertical-rl'' ''ltr'' right bottom left top
''rtl'' right top left bottom
''vertical-lr'' ''rtl'' left bottom right top
''ltr'' left top right bottom

For example, block-level boxes in a flow are laid out such that the A edge of the first box is against the block-start edge of the containing block and then the A edge of each subsequent box is put against the C edge of its predecessor. For typical English text (i.e., horizontal text), this means the top edge (= A edge) of the first paragraph is at the top edge (= block-start) of the document, the top (A edge) of the second paragraph is against the bottom (C edge) of the first paragraph, and so on, until the bottom (C edge) of the last paragraph becomes the bottom (block-end) of the document.

An element is called orthogonal if it is either a vertical element with a horizontal containing block or a horizontal element with a vertical containing block. An orthogonal flow is a flow whose flow root is an orthogonal element.

The viewport and the canvas

User agents for continuous media generally offer users a viewport (a window or other viewing area on the screen) through which users consult a document. User agents may change the document's layout when the viewport is resized (see the initial containing block).

When the viewport is smaller than the area of the canvas (see below) on which the document is rendered, the user agent usually offer a scrolling mechanism. There is at most one viewport per canvas, but user agents may render to more than one canvas (i.e., provide different views of the same document).

For all media, the term canvas describes the space where the formatting structure is rendered. The canvas is infinite for each dimension of the space.

Flows

The flow (sometimes called normal flow) is one of the two basic kinds of layout in CSS, together with line layout [[CSS3LINE]]. It can be used, e.g., to layout a sequence of paragraphs, headings, lists and floated elements in a single column. Other CSS modules, such as tables [[CSS3TBL]], positioning [[CSS3POS]], flex boxes [[CSS3-FLEXBOX]] and grid templates [[CSS3LAYOUT]], build on the flow model by defining ways to split a document into more than one flow and positioning and aligning those flows in various ways on the canvas.

A flow is constructed starting from a box called the flow root by the rules below. We say the flow is channeled by the flow root.

Are there more intuitive names than flow root?

The initial flow is the flow that contains the root of the box tree.

Despite not being a box, the initial containing block is said to be the flow root of the initial flow.

How do we model pagination? If a flow is broken over two pages or columns, do we call it a single flow or two flows? I.e., is the page box the flow root of the flow, or is the page box something else, more like the viewport, which influences the layout of a flow but isn't part of it? See [[CSS3-BREAK]].

Only block container boxes (defined below) can be flow roots. (Which implies that the children of a flow root are laid out in a block formatting context.)

Several (combinations of) properties cause an element to generate boxes that are flow roots. This module defines a few. Other modules may define more.

For example, this module defines that any of the following make a box into a flow root:

Other examples: The table layout module [[CSS3TBL]] defines that a table cell generates a box that is a flow root; the positioning module [[CSS3POS]] defines that an absolutely positioned element generates a flow root; the grid template module [[CSS3LAYOUT]] defines that a template element generate several flow roots; and the transforms module [[CSS3-TRANSFORMS]] defines that an element with a transform generates a flow root.

The flow of a given flow root is a set of boxes. A box belongs to the flow if all of the following are true:

  1. The used value of 'display' is ''block'', ''list-item'', ''table'' or ''flex''.
  2. The used value of 'float' is ''none''.
  3. The used value of 'position' is ''static'' or ''relative''.
  4. It is either a child of the flow root or a child of a box that belongs to the flow.

Note that the flow root is itself not part of the flow it channels and that each flow root channels at most one flow.

Note that the last rule above implies that a flow with its flow root together are always a connected subset of the box tree. In other words; together, they form a subtree of the box tree with possibly some branches removed.

Note that the element tree and the box tree are not necessarily parallel: the element a box belongs to need not be the child of the element that generated the box's parent. E.g., run-in elements may generate boxes that become children of boxes from sibling elements; and the 'flow' property [[CSS3LAYOUT]] and the 'position' property [[CSS3POS]] may cause an element to generate a box that becomes the child of a box from a grandparent or other ancestor element. E.g., 'DIV {flow: b}' (see [[CSS3LAYOUT]]) makes the DIV generate boxes that become children of the box generated by slot b in some ancestor. And 'DIV {position: absolute}' causes the DIV to generate a box that becomes a child of the box generated by the ancestor that established the DIV's containing block.

For example, the fragment

<div class=sidebar>
 <p>Text in a sidebar.
 <p>Here is quote:
 <blockquote lang=ja>
  <p>...
 </blockquote>
 <p>Etc. etc.
</div> 

with the style

div.sidebar { writing-mode: tb; float: left }
blockquote[lang|=ja] { writing-mode: rl; height: 10em }

defines two flows:

  1. The div is a flow root, because it floats. Its flow consist of the 1st, 2nd and 4th p and the blockquote.
  2. The blockquote is a vertical box inside a horizontal parent and it is thus a flow root. Its flow is formed by the 3rd p.

(The div itself belongs to a third flow, but its flow root is not shown in the fragment.)

Note that a flow root is not necessarily block-level, it may be an ''inline-block'', e.g.

Note that a box belongs to at most one flow. (Some boxes do not belong to any flow, because they are part of a different kind of layout, such as table layout.)

An element that generates a flow root box is itself also called a flow root.

Note: The terminology in the CSS level 2 specification is different. A flow root is called “an element that establishes a new formatting context.

A consequence of this terminology is that an element, unlike a box, can be the flow root of several flows. E.g., template elements [[CSS3LAYOUT]] generate several flow root boxes. Depending on what properties are set on a list item and on its marker pseudo-element, a list item can also generate zero, one or two flow roots.

Types of boxes

The layout of boxes in the flow is in large part determined by the interplay of the 'display' properties of an element and its parent, and then fine-tuned with margins and padding.

The value ''compact'' is missing in [[!CSS-DISPLAY-3]].

Block-level boxes, containing blocks, flows and anonymous boxes

Split this section. Put the definition of containing block in its own section and move it to right after the Flows section above.

A block-level box is a box that has a computed value for 'display' of ''block'', ''container'', ''list-item'', ''table'', ''table-*'' (i.e., all table boxes, see [[CSS3TBL]]), ''run-in'' (under certain circumstances, see “Run-in boxes” ), or ''compact'' (under certain circumstances, see “Compact boxes”).

An inline-level box is a box that has a computed value for 'display' of ''inline'', ''inline-block'', ''inline-table'', ''ruby'', ''run-in'' (under certain circumstances), or ''compact'' (under certain circumstances).

[What about the other ruby values?]

An anonymous box, informally, is a box that cannot be addressed with CSS selectors. All its properties, except for 'display', have their default values (either the initial value or inherited). Anonymous boxes are created when the CSS box model requires a child box with a certain value for 'display', but the child actually has a different value. In that case an anonymous box of the right kind is created and wraps the child (or children). Other modules (e.g., [[CSS3TBL]], [[!CSS3TEXT]]) may also define anonymous boxes. The anonymous boxes defined by this module are the following:

Note that the anonymous boxes defined in this module are all block-level, but anonymous boxes defined in other modules may be different.

The containing block of a box is a rectangle that is associated with the box and that is used in various definitions in this specification. Apart from a size and a position, the rectangle also has 'direction' and 'writing-mode' properties. The containing block of a box is defined as follows:

Other modules may introduce other types of boxes with other rules for how to find their containing block. E.g., the containing block of an absolutely positioned element.

In the above, a block container box is, informally, a box that can contain block boxes. More precisely: any box generated by a (pseudo-)element with a computed value for 'display' of ''block'', ''inline-block'', ''table-caption'', ''table-cell'' or ''list-item''. Note that most floating and absolutely positioned elements have a computed 'display' of ''block''. Also, a flow root has a computed 'display' of ''block''. Or insert the definition of block container box from CSS 2.1 here?

Also define principal box somewhere.

Note that the above is modified by the Absolute Positioning module [[CSS3POS]]: in particular, if a box's 'position' property is neither ''static'' nor ''relative'', its containing block is established differently.

If an element [or a viewport?] has scrollbars (see 'overflow'), then any space taken up by the scrollbars should be excluded from (subtracted from the dimensions of) any containing block formed by that element.

Mixing the box model with other formatting models

There may be documents that combine different layout models, such as documents that combine HTML (typically rendered with the CSS box model) and SVG (rendered with its own graphics model). If an element that is rendered according to the CSS box model has a child that is to be rendered with a different model, that child needs to have a 'display' property with a value that indicates that the child is not in the box model.

Such a child is treated as a replaced element for the purposes of determining its size, position, margins, padding and border.

Should we allow a more complex model, where such a child may negotiate with the CSS environment to have several boxes and several baselines, so that it can take part in line breaking and page breaking?

This specification defines no value(s) for the 'display' property that indicate that an element is formatted according to a different model than the box model, but separate specifications may do so.

The padding properties

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

Sets the thickness of the padding area. The value may not be negative.

Allow negative padding?

Define 'auto' or remove it. (Probably define it: it seems useful for stretching the padding, like 'margin: auto' strectches the margin.)

'Padding' is a shorthand for the other four properties. If 'padding' has four 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.

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).

Note that percentages are not required for CSS level 2.

For example, the following two ways to set the padding of h1 are equivalent:

h1 { padding: 0.5em }
h1 { padding-top: 0.5em;
     padding-right: 0.5em;
     padding-bottom: 0.5em;
     padding-left: 0.5em }

Values may not be negative, thus the third line is ignored, but what about the fourth?

p { font-size: 10pt;
    padding-left: 2em;
    padding: -11pt;
    padding-left: calc(1em - 11pt)
}

The margin properties

Margins in CSS serve to add both horizontal and vertical space between boxes.

Name: margin-top, margin-right, margin-bottom, margin-left
Value: <length> | <percentage> | fill | auto
Initial: 0
Applies to: see text
Inherited: no
Animatable: yes
Percentages: width* of containing block
Media: visual
Computed value: the percentage as specified or the absolute length or ''auto''
Canonical order: N/A
*) if the containing block is horizontal, otherwise the height
Name: margin
Value: [ <length> | <percentage> | fill | auto]{1,4}
Initial: (see individual properties)
Applies to: see text
Inherited: no
Animatable: yes
Percentages: width* of containing block
Media: visual
Computed value: see individual properties
Canonical order: N/A
*) if the containing block is horizontal, otherwise the height

These properties set the thickness of the margin area. The value may be negative.

'Margin' is a shorthand for the other four. If 'margin' has four values, 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.

For example, the following two ways of setting the margins of p are equivalent:

p { margin: 1em 2em }
p { margin-top: 1em;
    margin-right: 2em;
    margin-bottom: 1em;
    margin-left: 2em }

The values are as follows:

<length>
Sets the margin to the given length. Note that the actual distance to the next element may be different, due to margin collapsing.
<percentage>
Sets the margin to the given percentage of the extent of the containing block. If that dimension depends on the value of this percentage, then the percentage is taken relative to ''100vw'' or ''100vh'' instead, depending on whether the containing block is horizontal, respectively vertical.
fill
Makes the margin depend on the available space, as defined in “Calculating widths, heights and margins” and in [the section that defines how block-level boxes are laid out in a flow]
auto
On the A edge and C edge, the used value of ''auto'' is 0. On the B edge and D edge, the used value depends on the available space, as defined in “Calculating widths, heights and margins.”

Note that inside flexboxes [[CSS3-FLEXBOX]], the meaning of ''auto'' is different, because there it also has an effect on the A edge and C edge.

Another option is to combine a length/percentage with ''fill'', to set a desired margin in case there is no space to distribute, e.g. ''1.2em + fill'' or ''fill(1.2em)''. Is that ever needed?

'Fill' could also be a unit, like '%' or 'fr', so that some fills can get more space than others. Is that useful?

Andrew Fedoniouk proposed the '%%' unit. '50%%' is 50% of the remaining space. This allows fills to sum up to more or less than 100%. More than 100% is probably not useful, it guarantees overflow. But less than 100% might be.

The keywords 'min-content', 'max-content' and 'available' could also be useful, at least for the inline-start and inline-end margin of a box. Then you can make a box that takes up no space by setting 'width: available; margin-right: calc(0 - available)'

The properties apply to all boxes except certain table-* boxes (see [[CSS3TBL]]) and certain inline-level boxes (see [[!CSS3TEXT]]).

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).

The width and height properties

Name: width
Value: [<length> | <percentage>] && [border-box | content-box]? | available | min-content | max-content | fit-content | auto
Initial: auto
Applies to: all elements but non-replaced inline elements, table rows, and row groups
Inherited: no
Animatable: yes
Percentages: refer to width of containing block
Media: visual
Computed value: the specified keyword; or the specified percentage (with ''border-box'' or ''content-box'' if present); or the absolute length (with ''border-box'' or ''content-box'' if present); or ''auto'' if the property does not apply; (also see prose under <percentage>)
Canonical order: the length or percentage before the keyword, if both are present
Name: height
Value: [<length> | <percentage>] && [border-box | content-box]? | available | min-content | max-content | fit-content | complex | auto
Initial: auto
Applies to: all elements but non-replaced inline elements, table columns, and column groups
Inherited: no
Animatable: yes
Percentages: see prose
Media: visual
Computed value: the specified keywords, the specified percentage (see prose under <percentage>) or the absolute length; ''auto'' if the property does not apply
Canonical order: the length or percentage before the keyword, if both are present

These properties specify the width and height of the content area or border area (depending on 'box-sizing') of certain boxes.

Values have the following meanings:

<length>
Specifies the size using a length unit. Negative values are illegal. If the keyword ''border-box'' is present, the length sets the size of the border box; if ''content-box'' is present, it sets the size of the content box; if neither is present, the 'box-sizing' property determines which size is set.
<percentage>
Specifies a percentage width or height. The percentage is calculated with respect to the width (in the case of 'width') or height (for 'height') of the generated box's containing block. Negative percentages are illegal. If the containing block's width, resp. height depends on this element, then the percentage is relative to '100vw', resp. '100vh'. If the keyword ''border-box'' is present, the percentage sets the size of the border box; if ''content-box'' is present, it sets the size of the content box; if neither is present, the 'box-sizing' property determines which size is set.
available
Equal to the containing block width or height minus the current element's margin, border, and padding. If the required width, resp. height of the containing block is unknown (depends on this element), then ''available'' is equal to '100vw', resp. '100vh'.
max-content
The max-content width or height.
min-content
The min-content width or height.
fit-content
Equal to max(''min-content'', min(''max-content'', ''available'')).
auto
The width or height depends on the values of other properties. See Calculating widths, heights and margins below.
complex
(Only on 'height'.) The same as ''auto'', except that elements with a complex aspect ratio are considered to have an intrinsic ratio. More precisely: for the purposes of the section on “Calculating widths, heights and margins,” the element is treated as if its height was ''auto'' and it had an intrinsic ratio.

Another possible value is <non-negative-number>, which would mean ''min-content'' times that number.

The width property of ''@viewport'' [[CSS-DEVICE-ADAPT]] is a shorthand for min-width and max-width and can have either one or two values. Anything we can do to alleviate risk of the confusion?

Note that ''available'', ''max-content'', ''min-content'', ''fit-content'', ''border-box'', ''content-box'' and ''complex'' do not exist in level 2.

The keyword values (in contrast to length and percentage values) are not influenced by the 'box-sizing' property, they always set the size of the content box.

''Available'', ''max-content'', ''min-content'' and ''fit-content'' only have effect in the inline progression direction: they are equivalent to ''auto'' when set on the 'height' of horizontal elements or on the 'width' of vertical elements.

Note that 'width: fit-content' is the same as 'width: auto' for floats and tables, and 'width: available' is the same as 'width: auto' for blocks in the normal flow.

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

p { width: 100px }

This example shows the use of the keyword values. Assume these style rules:

div {width: 20em}
p.available {width: available}
p.min-content {width: min-content}
p.max-content {width: max-content}
p.fit-content {width: fit-content}
p.float {float: left; width: auto}
p.auto {width: auto}
* {outline: thin solid red}

Then a document like this might be rendered as in the figure below:

<div>
  <p class=available>available: as wide as parent.
  <p class=min-content>min-content: as narrow as possible.
  <p class=max-content>max-content: As wide as needed, even
    if that means wider than the parent.
  <p class=fit-content>fit-content: As wide as needed.
  <p class=fit-content>fit-content: As wide as needed, but
    no wider than the parent.
  <p class=float>auto: depends on flow (=float).
  <p class=auto>auto: depends on flow (=normal).
</div>

Image: paragraphs of different
  widths

Rendering of the example: ''min-content'' and ''max-content'' depend only on the content; ''available'' depends only on the containing block; ''fit-content'' depends on both; and ''auto'' acts either like ''available'' or like ''fit-content'', depending on the type of box.

This example sets the width of the border box of an element to 50%. It includes a fallback (48%) for UA that do not support the ''border-box'' keyword, such as level 2 UAs:

div.side {
    width: 48%;
    width: 50% border-box }

It is equivalent to

div.side {
    width: 50%;
    box-sizing: border-box }

except that the latter doesn't have a fallback for level 2 UAs (which don't support the 'box-sizing' property).

The min-width, max-width, min-height and max-height properties

Name: min-width, min-height
Value: [ [<length> | <percentage>] && [border-box | content-box]? ] | available | min-content | max-content | fit-content
Initial: 0
Applies to: all elements but non-replaced inline elements, table rows, and row groups
Inherited: no
Animatable: yes
Percentages: refer to width, resp. height of containing block
Media: visual
Computed value: the percentage as specified (with ''border-box'' or ''content-box'', if present), the keyword as specified, or the absolute length (with ''border-box'' or ''content-box'', if present)
Canonical order: the length or percentage before the keyword, if both are present
Name: max-width, max-height
Value: [ [<length> | <percentage>] && [border-box | content-box]? ] | available | min-content | max-content | fit-content | none
Initial: none
Applies to: all elements but non-replaced inline elements, table rows, and row groups
Inherited: no
Animatable: yes
Percentages: refer to width, resp. height of containing block
Media: visual
Computed value: the percentage as specified (with ''border-box'' or ''content-box'', if present); the keyword as specified; the absolute length (with ''border-box'' or ''content-box'', if present); or none
Canonical order: the length or percentage before the keyword, if both are present

These properties allow authors to constrain content widths and heights to a certain range. Values have the following meanings:

<length>
Specifies a fixed minimum or maximum for 'width' or 'height'. Negative values are illegal.
<percentage>
Specifies a minimum or maximum for 'width' or 'height' as a percentage of the corresponding dimension of the containing block. Negative percentages are illegal. If the containing block's dimension is negative, the used value is zero. If that containing block's dimension depends on this element's dimension, then the resulting layout is undefined. Or: use the initial value?
max-content
The max-content width or height.
min-content
The min-content width or height.
available
The containing block width or height minus margin, border, and padding.
fit-content
For 'max-width'/'max-height', same as ''max-content''. For 'min-width'/'min-height', same as ''min-content''.
none
No limit on the width or height of the box.

The keyword values (in contrast to length and percentage values) are not influenced by the 'box-sizing' property, they always set the size of the content box.

''Available'', ''max-content'', ''min-content'' and ''fit-content'' only have effect in the inline progression direction: they are equivalent to 0 when set on the 'min-height' of horizontal elements or on the 'min-width' of vertical elements; they are equivalent to ''none'' when set on the 'max-height' of horizontal elements or on the 'max-width' of vertical elements.

Definition of min-content/max-content

The size of a box often depends on the intrinsic width or height of its content. This section defines two characteristics of a box: the max-content size and the min-content size. They refer to the measure.

For horizontal boxes, the max-content width is, roughly, the size the content would have if no “soft” line breaks were inserted, i.e., if each paragaph is one long line; the min-content width is, roughly, the narrowest the box can get by breaking all lines at all possible break points. Another way of thinking about them is that they are, respectively, the width that minimizes the height; and the narrowest the content can get without unintended overflow.

For example, in a simple paragraph with just text the max-content width is the width of the line if all words are laid out on one line; and the min-content width is the width of the longest word (or the longest syllable, if hyphenation is turned on).

The min-content width of a horizontal, non-replaced element E is defined as the smallest length M ≥ 0 such that

OVERFLOW(E,M) ≤ OVERFLOW(E,w) for all w ≥ 0

where the function OVERFLOW(E,w) is defined as follows. Set the 'display' of E to ''block'', 'float' to ''none'', 'position' to ''static'', 'overflow' to ''visible'', 'min-width' to ''0'', 'max-width' to ''none'', 'height' to ''auto'', 'min-height' to ''0'', 'max-height' to ''none'' and 'width' to w. Then measure the total width W of E including all overflow, considering E and all its descendants in the same flow and all floats of which E is the containing block. Then

OVERFLOW(E,w) = W - w

The max-content width of a horizontal, non-replaced element E is defined as the smallest length M ≥ 0 such that

HEIGHT(E,M) ≤ HEIGHT(E,w) for all w ≥ 0

where HEIGHT(E,w) is defined as follows. Set the 'display' of E to ''block'', 'float' to ''none'', 'position' to ''static'', 'overflow' to ''visible'', 'min-width' to ''0'', 'max-width' to ''none'', 'height' to ''auto'', 'min-height' to ''0'', 'max-height' to ''none'', 'width' to w and lay out E as a flow root. Then HEIGHT(E,w) is the height as defined below in “Auto heights for flow roots.”

The corresponding definitions for vertical elements are analogous, with width and height swapped.

OVERFLOW is not necessarily monotonic in w and a binary search for min-content and max-content may thus fail.

Say something about acceptable near-optimal results?

Note that the ''min-content'' width of a block may be larger than the ''min-content'' of all its children, because it may be impossible to break a line between two children.

The intrinsic sizes of replaced elements are defined in [[!CSS3-IMAGES]].

Aspect ratios of replaced elements

For the purposes of the width and height calculations below, CSS distinguishes four kinds of replaced elements:

Type 1: replaced elements with both intrinsic width and intrinsic height.
These are replaced elements that are meant to be displayed with a certain fixed factor (the intrinsic ratio) between their width and height and also have a default size. Different formats may have different ways of specifying the size, e.g., a width and a ratio, or a raster and a resolution in dots per inch. Raster images fall in this category.
Type 2: replaced elements with only an intrinsic ratio
These are replaced elements that are meant to be displayed with a certain fixed factor between their width and height, but without a default size. SVG images often fall in the this category.
Type 3: replaced elements with a complex aspect ratio
These are replaced elements that do not have a fixed ratio between their width and height, but that do have a functional relation between them in the sense that to every width corresponds a certain height and vice-versa. HTML documents are examples of this: the width can be chosen freely, but at every width there is a definite intrinsic height.
Type 4: replaced elements without an intrinsic ratio
These are replaced elements that have no relation between their width and height. Certain SVG images are examples of this.

For raster images without reliable resolution information, a size of 1 px unit per image source pixel must be assumed. These images thus are of type 1.

E.g., according to the section on inline replaced elements below, if the replaced element is an HTML document and the height is specified as ''auto'', e.g.:

... <object data="example.html"
      style="width: 30em; height: auto"></object>...

then the used height will be 150px, which is unlikely to be the real height of the example.html document. But if the height is specified as ''complex'', e.g.:

... <object data="example.html"
      style="width: 30em; height: complex"></object>...

then the height will be the height the example.html document normally has when displayed on its own with the given width. This enables almost seamless integration of external text in a document, without a scrollbar or other scrolling mechanism. (The external text is still displayed with its own style sheet.)

An external mathematical formula in MathML is an example of replaced content with an intrinsic width and height. Assume the file m.mml contains a formula, then the HTML fragment

... derive <img src="m.mml"
alt="that the sum of p(i) for i greater than 0 equals N">
for the case...

renders the formula at its intrinsic size.

(Note, however, that it is often better to specify the formula directly in the HTML file, rather than as an external reference. That way it shares the style of the surrounding text and can be broken over two lines if it is too wide.)

Block-level formatting

In a block formatting context, block-level boxes are laid out in the manner of a series of paragraphs.

The boxes of a flow are laid out one after the other in the direction of the 'writing-mode' property of the flow root and in the same order as in the source document. Their position is given by how much their margins overlap (see “Collapsing margins”) and by the fact that their side margin edges coincide with the edges of their containing block. More precisely: Each box's D and B edge coincide with respectively the inline-start and inline-end edges of its containing block.

When is a block formatting context established?

TODO: Need to deal with anonymous block boxes.

An example of the last point above is this document fragment:

<p>Somebody whose name I have
forgotten, said, long ago: <q>a box is
a box,</q> and he probably meant it.</p>

with these style rules:

p { display: block }
q { display: block; margin: 1em }

The p element has both line boxes and a child box for the q element, which is a block-level element. The line boxes before the q are wrapped in an anonymous block-level box and so are the line boxes after the q. The resulting tree of boxes might be as follows (refer to the figure):

The P element has two line boxes before the q and one
  after. The first two are wrapped in an anonymous box, the last one
  is wrapped in another anonymous box.

When the fragment is rendered, the text before the q is wrapped in an anonymous block and the text after the q in another.

Collapsing margins

Certain adjoining margins, as defined in this section, combine to form a single margin. Those margins are said to collapse. Margins are adjoining if there are no nonempty content, padding or border areas or clearance to separate them.

For example, in the following fragment with the given style rules:

p { display: block; margin-bottom: 2em 0 1em 0 }
div { display: block; margin: 2.5em 0 }
...
<p>First paragraph</p>
<div>
  <p>Second paragraph</p>
</div>

the bottom margin of the first p (=1em), the top margin of the div (=2.5em) and the top margin of the second p (=2em) collapse. The result is a single margin of 2.5em (the maximum of the three) between the bottom of the first p and the top of the second.

Three margins collapse: 1em + 2.5em + 2em

Schematic representation of the previous example.

In the following fragment,

p { display: block; margin: 2em 0 1em 0 }
div { display: block; margin: 2.5em 0;
      border: thin solid }
...
<p>First paragraph</p>
<div>
  <p>Second paragraph</p>
</div>

the bottom margin of the first p and the top margin of the div collapse, but the top margin of the second p does not collapse with them, because it is not adjoining; the border of the div separates them.

Only two margins collapse: 1em + 2.5em

Schematic representation of the previous example.

If a set of adjoining margins collapses, then the width of the resulting margin is M - N, where M is the maximum of the adjoining margins that are positive, or zero if there are none; and N is the minimum of the adjoining margins that are negative, or zero if there are none. But if any of the margins is ''fill'', then the resulting margin is also ''fill''.

We call an element or box collapsed through if two of its margins collapse with each other.

The most common use of collapsing through elements is that empty paragraphs don't cause extra white space:

<p>First paragraph
<p>Second paragraph
<p>
<p>Last paragraph

There is equal space between the first and the second paragraphs as between the second and the last.

The following two sets of rules determine which margins collapse.

Except when forbidden by the list above, the following margins collapse:

If a box X is collapsed through then the position of its A border edge is defined as follows.

Note that box X itself is invisible and its position has no effect on the positions of the other elements with whose margins it is being collapsed; the border edge position is only required for laying out descendants of X.

In a horizontal flow, the bottom margin of an in-flow block-level element is adjoining to the top margin of its next in-flow block-level sibling, unless that sibling has clearance:

<p style="margin-bottom: 2em">The bottom margin of this
box…</p>

<p style="margin-top: 3em">… collapses with the top margin
of this box, to yield max(2em, 3em) = 3em margin.</p>

The top margin of an in-flow block-level element is adjoining to its first in-flow block-level child's top margin if the element has no top border, no top padding, and the child has no clearance:

<div style="margin-top: 2em; padding: 0; border: 0">
  <p style="margin-top: 3em">
    The top margin of the DIV and the P
    collapse, to yield max(2em, 3em) = 3em margin.
  </p>
</div>

The bottom margin of an in-flow block-level element with a 'height' of ''auto'' and 'min-height' less than the element's used height and 'max-height' greater than the element's used height is adjoining to its last in-flow block-level child's bottom margin if the element has no bottom padding or border:

<div style="margin-bottom: 2em; padding: 0; border: 0;
    height: auto; min-height: 0; max-height: 100em">
  <p style="margin-bottom: 3em">
    The bottom margin of the DIV and the P collapse, to yield max(2em,
    3em) = 3em margin.
  </p>
</div>

An element's own margins are adjoining if the 'min-height' property is zero, and it has neither vertical borders nor vertical padding, and it has a 'height' of either 0 or ''auto'', and it does not contain a line box, and all of its in-flow children's margins (if any) are adjoining:

<div style="margin-top: 2em; margin-bottom: 3em">
  <p style="position: absolute">
    The DIV is empty and its top and bottom margins collapse.
  </p>
</div>

When an element's own margins collapse, and that element has had clearance applied to it, its top margin collapses with the adjoining margins of subsequent siblings but that resulting margin does not collapse with the bottom margin of the parent block:

<div style="margin-bottom: 2em">
  <p style="float: left">
    The margins of the next two Ps collapse
  <p style="clear: left; margin-top: 4em; margin-bottom: 3em">
    
  </p>
  <p style="margin-top: 1em; margin-bottom: 1em">
    
  </p>
</div>

The top and bottom margins of the two empty Ps collapse all together. But they can't collapse with the bottom of the DIV, because one of the two empty P's has clearance.

Check this. This is probably the only possible interpretation of the rules, but it is certainly not obvious that the clearance of one element may stop later elements from collapsing…

Collapsing is based on the used value of 'padding', 'margin', and 'border' (i.e., after resolving any percentages). The collapsed margin is calculated over the used value of the various margins.

Inline-level formatting

In an inline formatting context, inline-level boxes are laid out in the manner of a run of words and sentences. Inline-level formatting, and the behavior of inline-level boxes, is specified in the text specification [[!CSS3TEXT]].

Calculating widths, heights and margins

The following two algorithms define the used value of 'width' and 'height' respectively and also the used values of the 'margin' properties and of 'top', 'right' 'bottom' and 'left'.

Note that they do not affect the computed values of 'width' and 'height'. Also note that in some cases the used width has to be known in order to calculate the used height, or vice versa,

For 'width':

  1. The tentative used width is calculated following the rules in the subsections below. If 'transform' is not ''none'', it is assumed to be 'rotate(0)' (i.e., the identity transform) for the purposes of this calcutlation.
  2. If the tentative used width is greater than 'max-width', the same rules are applied again, but this time using the computed value of 'max-width' as the computed value for 'width'.
  3. If the resulting width is smaller than 'min-width', the same rules are applied again, but this time using the computed value of 'min-width' as the computed value for 'width'.

For 'height':

  1. The tentative used height is calculated following the rules in the sections below. If 'transform' is not ''none'', it is assumed to be 'rotate(0)' (i.e., the identity transform) for the purposes of this calcutlation.
  2. If the tentative used height is greater than 'max-height', the same rules are applied again, but this time using the computed value of 'max-height' as the computed value for 'height'.
  3. If the resulting height is smaller than 'min-height', the same rules are applied again, but this time using the computed value of 'min-height' as the computed value for 'height'.

If 'transform' is not ''none'', the used width or height is further modified as follows:

Note that translations [[!CSS3-2D-TRANSFORMS]] do not affect the width or height and also do not affect the placement of boxes in the normal flow (see “Basic flow layout” ).

However, for replaced elements with an intrinsic ratio and both 'width' and 'height' specified as ''auto'', the algorithm is as follows:

Select from the table the resolved height and width values for the appropriate constraint violation. Take the max-width and max-height as max(min, max) so that minmax holds true. In this table w and h stand for the results of the width and height computations ignoring the 'min-width', 'min-height', 'max-width' and 'max-height' properties. Normally these are the intrinsic width and height, but they may not be in the case of replaced elements with intrinsic ratios.

Constraint violation Resolved width Resolved height
none w h
w > max-width max-width max(max-width * h/w, min-height)
w < min-width min-width min(min-width * h/w, max-height)
h > max-height max(max-height * w/h, min-width) max-height
h < min-height min(min-height * w/h, max-width) min-height
(w > max-width) and (h > max-height), where (max-width/w ≤ max-height/h) max-width max(min-height, max-width * h/w)
(w > max-width) and (h > max-height), where (max-width/w > max-height/h) max(min-width, max-height * w/h) max-height
(w < min-width) and (h < min-height), where (min-width/w ≤ min-height/h) min(max-width, min-height * w/h) min-height
(w < min-width) and (h < min-height), where (min-width/w > min-height/h) min-width min(max-height, min-width * h/w)
(w < min-width) and (h > max-height) min-width max-height
(w > max-width) and (h < min-height) max-width min-height

Then apply the appropriate rules in the subsections below, as if 'width' and 'height' were computed as these values.

The following subsections apply if the element's containing block is horizontal. If it is vertical, the same rules apply, but with every occurrence of “left” replaced by “top,” “right” by “bottom,” “top” by “right,” “bottom” by “left”, “height” by “width” and “width” by “height.”

For the purposes of evaluating percentages in the following subsections, if the width of the containing block is unknown, then assume the width is '100vw'. Likewise, if the height of the containing block is unknown, then assume it is '100vh'.

Inline, non-replaced elements

The 'width' and 'height' properties do not apply. For each of 'left', 'right', 'top', 'bottom', 'margin-left', 'margin-right', 'margin-top' and 'margin-bottom', the used value is calculated from the computed value by evaluating percentages and replacing ''auto'' and ''fill'' by 0.

Note that this section applies equally when the containing block is horizontal as when it is vertical.

Inline or floating, replaced elements

The used values of 'margin-left', 'margin-right', 'margin-top' and 'margin-bottom' derive from the computed value, except that a computed value of ''auto'' becomes a used value of '0'.

If 'height' and 'width' both have computed values of ''auto'' and the element also has an intrinsic width, then that intrinsic width is the used value of 'width'.

If 'height' and 'width' both have computed values of ''auto'' and the element also has an intrinsic height, then that intrinsic height is the used value of 'height'.

If 'height' and 'width' both have computed values of ''auto'' and the element has no intrinsic width, but does have an intrinsic height and intrinsic ratio; or if 'width' has a computed value of ''auto'', 'height' has some other computed value, and the element has an intrinsic ratio; then the used value of 'width' is:

(used height) * (intrinsic ratio)

If 'height' and 'width' both have computed values of ''auto'' and the element has no intrinsic height, but does have an intrinsic width and intrinsic ratio; or if 'height' has a computed value of ''auto'', 'width' has some other computed value, and the element has an intrinsic ratio; then the used value of 'height' is:

(used width) / (intrinsic ratio)

If 'height' and 'width' both have computed values of ''auto'' and the element has an intrinsic ratio but no intrinsic height or width and the containing block's width doesn't itself depend on the replaced element's width, then the used value of 'width' is calculated from the constraint equation used for block-level, non-replaced elements in normal flow. The used value for 'height' is: (used width) / (intrinsic ratio).

If 'width' has a computed value of 'auto', and the element has an intrinsic width but no intrinsic ratio, then that intrinsic width is the used value of 'width'.

If 'height' has a computed value of 'auto', and the element has an intrinsic height but no intrinsic ratio, then that intrinsic width is the used value of 'width'.

If 'width' has a computed value of ''auto'', but none of the conditions above are met, then the used value of 'width' becomes 300px. If 300px is too wide to fit the device, UAs should use the width of the largest rectangle that has a 2:1 ratio and fits the device instead.

If 'height' has a computed value of ''auto'' and none of the rules above define its used value, then the used value of 'height' must be set to the height of the largest rectangle that has a 2:1 ratio, has a height not greater than 150px, and has a width not greater than the device width.

Theoretically, a device may be wider than than 300px but not tall enough for 150px. In that case the resulting replaced element will be too tall. But this is the formulation in CSS 2.1 and it seems not worth improving such an edge case.

Percentage intrinsic widths are first evaluated with respect to the containing block's width, if that width doesn't itself depend on the replaced element's width. If it does, then a percentage intrinsic width on that element can't be resolved and the element is assumed to have no intrinsic width.

Note that this section applies equally when the containing block is horizontal as when it is vertical.

Block-level, non-replaced elements in normal flow when 'overflow' computes to ''visible''

This section also applies to block-level non-replaced elements in normal flow when 'overflow' does not compute to ''visible'' but has been propagated to the viewport.

The used values of the block-start padding, block-end padding, block-start margin and block-end margin are calculated from their computed values, with any ''auto'' values replaced by 0.

The complexity of this section comes from the fact that ''auto'' values on 'width' and 'height' are resolved differently for horizontal and for vertical elements, and differently for parallel flows then for orthogonal flows (i.e., when the containing block is horizontal and the element itself vertical, or vice-versa). In paginated contexts, the element may further be split into boxes of unequal sizes.

There are three principles. The first is: If the element's size in the direction of the containing block's measure (i.e., between the B edge and the D edge) is ''auto'', then that size is the same as the containing block (minus the element's own margins, padding and borders, if applicable).

The second principle applies to orthogonal flows only, and only if they are not in a paginated environment: If an element is orthogonal and its measure (i.e., the distance between its A edge and C edge) is ''auto'', then it is treated as a multi-column element [[!CSS3COL]] and 'column-width', if not already set, is set to a value derived from the containing block's size and the initial containing block

The last principle applies to orthogonal flows in a paginated environment, e.g., in paged media or inside a multi-column element: Just like in a non-paginated environment, if an element is orthogonal and its measure is ''auto'', then it is treated as a multi-column element [[!CSS3COL]] and 'column-width', if not already set, is set to a certain value. But, in addition, if that means that the first column would be so wide as stick out of the page or column (the “fragmentainer,” see [[CSS3-BREAK]]), then that first column is made narrower until it fits. But not narrower than ''min-content''. (If at that size it still doesn't fit, it may instead be moved to the next page/column or, if that is not possible, overflow.)

If the computed value of the extent is not ''auto'', then the used value is calculated by evaluating the computed value. Otherwise, the extent is the distance between two edges that are defined as follows:

The above reflects the fact that the margins of the element may collapse with the margins of its first and last children (unless the element has a border or padding). In that case the children's margins fall outside the block flow dimension.

The position of the edges is calculated without applying relative positioning, if any, to the children. And only children in the normal flow are taken into account, i.e., floating boxes and absolutely positioned boxes are ignored.

For example, the DIV in this fragment has a bottom border but no padding or border at the top. The height is thus calculated from the border edge of the first child (img1) to the margin edge of the last child (img2). The result is 8em.

div {border-bottom: 0.2em dashed}
img {height: 3em; display: block; margin: 1em}
...
<div>
  <img src="img1" alt=...>
  <img src="img2" alt=...>
</div>

The top margin of the first IMG does
    not contribute to the height of the DIV.

The height is measured from the top border edge of the first IMG to the bottom margin edge of the last.

With respect to the measure, one of the following constraints must hold among the used values of the given properties.

The used values of the above properties, except for any values that are ''auto'', are calculated from the computed values, evaluating percentages. If this makes the measure negative, then set its used value to 0. Ditto for inline-start padding and inline-end padding. Note that such negative values can only happen when the specified value includes 'calc()'. Then apply one of the following cases:

  1. If none of the values is ''auto'', then there are three sub-cases:

    1. If the current element's 'alignment' is ''center'', then the used values of inline-start margin and inline-end margin are set so that they are the same and the constraint is satisfied.
    2. If 'alignment' corresponds to the inline-end edge, then the used value of the inline-end margin is set to the value that satisfies the constraint.
    3. If 'alignment' has any other value, then the used value of the inline-start margin is set to the value that satisfies the constraint.
  2. If the measure is ''auto'', then set the used value of all other properties in the constraint that are ''auto'' to 0 and set the used value of the measure so that the constraint is satisfied. If that makes the used value negative, then set it to 0 instead and apply case 1 above.
  3. If both the inline-start and inline-end margins are ''auto'', and 'alignment' is 'center', then solve the constraint under the extra condition that the inline-start and inline-end margin are equal.
  4. If both the inline-start and inline-end margins are ''auto'', and 'alignment' is not 'center', then solve the constraint under the extra condition that the inline-start and inline-end margins are equal. But if that makes them negative, then set both to 0 and apply case 1 above.
  5. If only the inline-start margin is ''auto'' and 'alignment' corresponds to the inline-end edge, then set the inline-start margin to the value that satisfies the constraint.
  6. If only the inline-start margin is ''auto'' and 'alignment' does not correspond to the inline-end edge, then set the inline-start margin to the value that satisfies the constraint. But if that makes it negative, then set it to 0 instead and apply case 1 above.
  7. If only the inline-end margin is ''auto'' and 'alignment' corresponds to the inline-start edge, then set the inline-end margin to the value that satisfies the constraint.
  8. If only the inline-end margin is ''auto'' and 'alignment' does not correspond to the inline-start edge, then set the inline-end margin to the value that satisfies the constraint. But if that makes it negative, then set it to 0 instead and apply case 1 above.

Note that the best way to center a block is 'margin-left: auto; margin-right: auto; alignment: center'. Setting the margins to ''auto'', instead of leaving them at 0, provides a fallback for UAs that do not support 'alignment' (which is a level 3 feature).

Note also that only 'alignment: center' guarantees proper centering. Setting the margins to ''auto'' only centers blocks if they are narrower than their containing block, because only one of the two margins is allowed to become negative.

The following examples illustrate different ways of aligning a fixed-width block in its parent. Assume English text, default values for 'writing-mode' and 'direction', a P of fixed with (e.g., 'width: 30em'), and the following HTML mark-up:

<div>
  <p>A paragraph here.
</div>

The following aligns the right border edge of the P with the right content edge of the DIV:

p {alignment: right}

The following centers the P:

p {alignment: center}

Adding ''auto'' margins provides a fallback for UAs that do not support 'alignment'. (The fallback has the desired effect as long as the DIV is wider than the P.)

p {margin-left: auto; margin-right: auto; alignment: center}

“Conflicting” combinations of ''auto'' margins and 'alignment' are well-defined, but not very useful. They cause 'alignment' to be all but ignored. The following right-aligns the P (unless it is too wide for the DIV):

p {margin-left: auto; alignment: left}

Similarly, the following left-aligns the P in the DIV:

p {margin-right: auto; alignment: right}

Fixed or percentage margins can be combined with alignment. The following puts the right border edge of the P at 2em inside the right content edge of the DIV:

p {margin-right: 2em; alignment: right}

The following does the same. The value of 'margin-left' is ignored in a right-aligned block:

p {margin-right: 2em; margin-left: 4em; alignment: right}

Other block-level, non-replaced elements in normal flow

This section applies to block-level, non-replaced elements when 'overflow' does not compute to ''visible'' (except if the 'overflow' property's value has been propagated to the viewport).

The used values of block-start padding, block-end padding, block-start margin and block-end margin are calculated from the computed values, with any ''auto'' values replaced by 0.

If the block flow dimension is ''auto'', the used value is defined by “''Auto'' heights for flow roots.” Otherwise, the used value is evaluated from the computed value.

Apply the rules for inline-start margin, inline-start padding, measure, inline-end padding and inline-end margin as given above in “Block-level, non-replaced elements in normal flow when 'overflow' computes to ''visible''.”

'Inline-block' or floating, non-replaced elements

Not yet generalized with block-start, block-end, etc.

The used values of 'margin-left', 'margin-right', 'margin-top' and 'margin-bottom' are derived from their computed values, except that a computed value of ''auto'' gives a used value of 0.

If the computed value of 'width' is ''auto'', the used value is the same as for ''fit-content''. Otherwise the computed value is evaluated to give the used value.

If the computed value of 'height' is ''auto'', the used value is defined by “''Auto'' heights for flow roots.” If it contains a percentage and the height of the containing block is not known (depends on this element), then the used value is also defined by “''Auto'' heights for flow roots.” Otherwise it is calculated by evaluating the computed value.

For inline-block boxes, the margin box is used when calculating the height of the line box. Does this belong here?

Absolutely positioned, non-replaced elements

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

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

For the purposes of calculating the static position, the containing block of fixed positioned elements is the initial containing block instead of the viewport, and all scrollable boxes should be assumed to be scrolled to their origin.

This constraint must hold among the used values:

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

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

If none of the three is ''auto'': If both 'margin-left' and 'margin-right' are ''auto'', solve the equation under the extra constraint that the two margins get equal values, unless this would make them negative, in which case when direction of the containing block is ''ltr'' (''rtl''), set 'margin-left' ('margin-right') to zero and solve for 'margin-right' ('margin-left'). Should we remove the phrase starting with “unless”? If one of 'margin-left' or 'margin-right' is ''auto'', solve the equation for that value. If the values are over-constrained, ignore the value for 'left' (in case the 'direction' property of the containing block is ''rtl'') or 'right' (in case 'direction' is ''ltr'') and solve for that value.

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

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

This constraint must also hold among the used values:

'top' + 'margin-top' + 'border-top-width' + 'padding-top' + 'height' + 'padding-bottom' + 'border-bottom-width' + 'margin-bottom' + 'bottom' = height of containing block

If all three of 'top', 'height', and 'bottom' are ''auto'', set 'top' to the static position and apply rule number three below.

If none of the three are ''auto'': If both 'margin-top' and 'margin-bottom' are ''auto'', solve the equation under the extra constraint that the two margins get equal values. If one of 'margin-top' or 'margin-bottom' is ''auto'', solve the equation for that value. If the values are over-constrained, ignore the value for 'bottom' and solve for that value.

Otherwise, pick the one of the following six rules that applies.

  1. 'top' and 'height' are ''auto'' and 'bottom' is not ''auto'': The used value of 'bottom' is its computed value. The used height is defined by “''Auto'' heights for flow roots.” The used values of 'margin-top' and 'margin-bottom' are their computed values, except that any ''auto'' gives a used value of 0. Finally, the constraint gives the used value of 'top'.
  2. 'top' and 'bottom' are ''auto'' and 'height' is not ''auto'': The used value of 'top' is its static position. The used values of 'margin-top' and 'margin-bottom' are their computed values, except that any ''auto'' gives a used value of 0. Finally, the constraint gives the used value for 'bottom'.
  3. 'height' and 'bottom' are ''auto'' and 'top' is not ''auto'': The used height is defined by “''Auto'' heights for flow roots.” The used values of 'margin-top' and 'margin-bottom' are their computed values, except that any ''auto'' gives a used value of 0. Finally, the constraint gives the used value of 'bottom'.
  4. 'top' is ''auto'', 'height' and 'bottom' are not ''auto'': The used values of 'margin-top' and 'margin-bottom' are their computed values, except that any ''auto'' gives a used value of 0. The constraint gives the used value for 'top'.
  5. 'height' is ''auto'', 'top' and 'bottom' are not ''auto'': The used values of 'margin-top' and 'margin-bottom' are their computed values, except that any ''auto'' gives a used value of 0. The constraint gives the used value for 'height'.
  6. 'bottom' is ''auto'', 'top' and 'height' are not ''auto'': The used values of 'margin-top' and 'margin-bottom' are their computed values, except that any ''auto'' gives a used value of 0. The constraint gives the used value for 'bottom'.

Absolutely positioned, replaced elements

This situation is similar to the previous one, except that the element may have an intrinsic size or ratio. The sequence of substitutions is now:

  1. The used value of 'width' and 'height' is determined as for inline replaced elements.
  2. For each of 'top', 'right', 'bottom', 'left', 'margin-top', 'margin-right', 'margin-bottom' and 'margin-left', if the computed value is not ''auto'', the used value is equal to the computed value.
  3. If both 'left' and 'right' have the value ''auto'', then if 'direction' of the containing block is ''ltr'', the used value of 'left' is its static position; else if 'direction' is ''rtl'', the used value of 'right' is its static position.
  4. If both 'top' and 'bottom' have the value ''auto'', then the used value of 'top' is its static position.
  5. If 'left' or 'right' (or both) are ''auto'', and 'margin-left' is ''auto'', then the used value of 'margin-left' is 0.
  6. If 'left' or 'right' (or both) are ''auto'', and 'margin-right' is ''auto'', then the used value of 'margin-right' is 0.
  7. If neither 'left' nor 'right' are ''auto'' and both 'margin-left' and 'margin-right' are ''auto'', then the used values satisfy the extra constraint that 'margin-right' and 'margin-left' are equal, unless this would make them negative, in which case when the direction of the containing block is ''ltr'' (''rtl''), the used value of 'margin-left' ('margin-right') is 0. Remove the part starting with “unless”? It looks better to center the image.

The remaining used values, if any, follows from these two constraints:

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

'top' + 'margin-top' + 'border-top-width' + 'padding-top' + 'height' + 'padding-bottom' + 'border-bottom-width' + 'margin-bottom' + 'bottom' = height of containing block

If the first equation is over-constrained, ignore the value for either 'left' (in case the 'direction' property of the containing block is ''rtl'') or 'right' (in case 'direction' is ''ltr'') and solve for that value.

If the second equation is over-constrained, ignore the value for 'bottom' and solve for that value.

Block-level, replaced elements in normal flow

Apply the rules for inline replaced elements, but ignore the resulting values for 'margin-left' and 'margin-right'. To compute the used value of those, apply the rules for block-level, non-replaced elements using the used values just found for 'width', 'border' and 'padding' as if they were the computed values.

Floating, non-replaced elements

The used values of the margins are derived from the computed values, except that the used values of any margins computed as ''auto'' are '0'.

The used value of 'width' is derived from the computed value, except that if 'width' is computed as ''auto'', the used value is the same as for ''fit-content''.

If the computed value of 'height' is ''auto'', the used value is given by “''Auto'' heights for flow roots.” If the computed value includes a percentage and the height of the containing block is not known (depends on this element), then the used value is computed as if the computed value were ''auto''. Otherwise the computed value is evaluated to give the used value.

Auto heights for flow roots

In certain cases (see the preceding sections), the height of an element is computed as follows:

If it only has inline-level children, the height is the distance between the top of the topmost line box and the bottom of the bottommost line box.

If it has block-level children, the height is the distance between the top margin-edge of the topmost block-level child box and the bottom margin-edge of the bottommost block-level child box.

Absolutely positioned children are ignored, and relatively positioned boxes are considered without their offset. Note that the child box may be an anonymous block box.

In addition, if the element has any floating descendants whose bottom margin edge is below the bottom, then the height is increased to include those edges. Only floats that are children of the element itself or of descendants in the normal flow are taken into account, e.g., floats inside absolutely positioned descendants or other floats are not.

The float property

Name: float
Value: left | right | top | bottom | start | end | none | <page-floats>
Initial: none
Applies to: all, but see text
Inherited: no
Animatable: no
Percentages: N/A
Media: visual
Computed value: as specified
Canonical order: order of grammar

This property specifies whether a box should float to the left, right, or not at all. It only applies if the element has a 'display' other than ''none'' and a 'position' of ''static'' or ''relative''.

The 'float' property in turn influences the computed value of 'display'. See “The display property.”

The values of this property have the following meanings:

top
Same as ''left''
left
If 'writing-mode' is ''tb'', the element generates a box that is floated to the left and content flows on the right side of the box (subject to the 'clear' property). If 'writing-mode' has a different value, the element generates a box that is floated to the top and content flows on the bottom side of the box (subject to the 'clear' property).
bottom
same as ''right''
right
Similar to ''left'', except the box is floated to the right (if 'writing-mode' is ''tb'') or to the bottom (otherwise), and content flows on the left or top side of the box.
start
If the containing block's 'direction' is ''ltr'', then the same as ''left''; otherwise the same as ''right''.
end
If the containing block's 'direction' is ''rtl'', then the same as ''right''; otherwise the same as ''left''.
none
The box is not floated.
<page-floats>
See Generated Content for Paged Media [[CSS3GCPM]]. Check that the names page-top, page-bottom, next-top, or otherwise do not clash with top and bottom

User agents may treat float as ''none'' on the root element.

Introduction to floats

(This section is not normative.)

A float is a box that is shifted to the left or right on the current line. The most interesting characteristic of a float (or “floating” box) is that content may flow along its side (or be prohibited from doing so by the 'clear' property). Content flows down the right side of a left-floated box and down the left side of a right-floated box. The following is a (non-normative) introduction to float positioning and content flow; the exact rules governing float positioning are given in the next section.

A floated box is shifted to the left or right until its margin edge touches the containing block edge or the margin edge of another float. If there is a line box, the top of the floated box is aligned with the top of the current line box.

If there isn't enough horizontal room for the float, it is shifted downward until either it fits or there are no more floats present.

Since a float is not in the flow, non-positioned block boxes created before and after the float box flow vertically as if the float didn't exist. However, line boxes created next to the float are shortened to make room for the margin box of the float. If a shortened line box is too small to contain any further content, then it is shifted downward until either it fits or there are no more floats present. Any content in the current line before a floated box is re-flowed in the first available line on the other side of the float. In other words, if inline boxes are placed on the line before a left float is encountered that fits in the remaining line box space, the left float is placed on that line, aligned with the top of the line box, and then the inline boxes already on the line are moved accordingly to the right of the float (the right being the other side of the left float) and vice versa for rtl and right floats.

In the following document fragment, the containing block is too narrow to contain the content next to the float, so the content gets moved to below the floats where it is aligned in the line box according to the text-align property.

p { width: 10em; border: solid aqua; }
span { float: left; width: 5em; height: 5em; border: solid blue; }

...

<p>
  <span> </span>
  Supercalifragilisticexpialidocious
</p>

This fragment might look like this:

Image illustrating the effect of an
  unbreakable piece of content being reflowed to just after a float
  which left insufficient room next to it for the content to fit.

The text is too long to fit in a shortened line box next to the float (dark blue box) and so it is pushed down until it is passed the float.

Several floats may be adjacent, and this model also applies to adjacent floats in the same line.

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.01//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.png 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.

An image showing the various margins of the BODY, P and IMG element. Not that the top margin of the floating IMG does not collapse with the top margins of the P and BODY elements.

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

<BODY>
  <P>Some sample text 
  <IMG src=img.png 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.

As stated in “Collapsing margins,” the margins of floating boxes never collapse with margins of adjacent boxes. Thus, in the previous example, vertical margins do not collapse between the P box and the floated IMG box.

The contents of floats are stacked as if floats generated new stacking contexts, except that any elements that actually create new stacking contexts take part in the float's parent's stacking context. A float can overlap other boxes in the normal flow (e.g., when a normal flow box next to a float has negative margins). When this happens, floats are rendered in front of non-positioned in-flow blocks, but behind in-flow inlines.

Here is another 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.

The following example illustrates the use of the 'clear' property to prevent content from flowing next to a float.

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 – clearance is added above its top margin to accomplish this (see the 'clear' property).

Rules for positioning floats

Here are the precise rules that govern the positions of floats with a horizontal containing block. References to other elements in these rules refer only to other elements in the same flow as the float's parent.

  1. 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 elements.
  2. If the current box is left-floating, and there are any left-floating boxes generated by elements earlier in the source document, then for each such earlier box, either the left margin edge of the current box must be to the right of the right margin edge of the earlier box, or its top must be lower than the bottom of the earlier box. Analogous rules hold for right-floating boxes.
  3. The right margin edge of a left-floating box may not be to the right of the left margin edge of any right-floating box that is to the right of it. Analogous rules hold for right-floating elements.
  4. A floating box's top margin edge may not be higher than the top of its containing block. When the float occurs between two collapsing margins, the float is positioned as if it had an otherwise empty anonymous block parent taking part in the flow. The position of such a parent is defined by the rules in the section on margin collapsing.
  5. The top margin edge of a floating box may not be higher than the margin top of any block-level or floated box generated by an element earlier in the source document.
  6. The top margin edge of an element's floating box may not be higher than the top of any line-box containing a box generated by an element earlier in the source document.
  7. A left-floating box that has another left-floating box to its left may not have its right margin edge to the right of its containing block's right edge. (Loosely: a left float may not stick out at the right edge, unless it is already as far to the left as possible.) An analogous rule holds for right-floating elements.
  8. A floating box must be placed as high as possible.
  9. 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. A higher position is preferred over one that is further to the left/right.

This HTML fragment results in the b floating to the right.

<P>a<SPAN style="float: right">b</SPAN></P>

If the P element's width is enough, the a and the b will be side by side. It might look like this:

An a at the left side of a box and a b at the right side

The rules for a float with a containing block with 'writing-mode: rl' are exactly the same after replacing left with top, right with bottom, top with right, bottom with left and adjusting the text accordingly. Here they are:

[Still some words like lower and higher to replace...]

  1. The top margin edge of a top-floating box may not be above the top edge of its containing block. An analogous rule holds for bottom-floating elements.
  2. If the current box is top-floating, and there are any top-floating boxes generated by elements earlier in the source document, then for each such earlier box, either the top margin edge of the current box must be below the bottom margin edge of the earlier box, or its right must be to the left of the left margin edge of the earlier box. Analogous rules hold for bottom-floating boxes.
  3. The bottom margin edge of a top-floating box may not be below the top margin edge of any bottom-floating box that is below it. Analogous rules hold for bottom-floating elements.
  4. A floating box's right margin edge may not be to the right of the right edge of its containing block. When the float occurs between two collapsing margins, the float is positioned as if it had an otherwise empty anonymous block parent taking part in the flow. The position of such a parent is defined by the rules in the section on margin collapsing.
  5. The right margin edge of a floating box may not be to the right of the right margin edge of any block-level or floated box generated by an element earlier in the source document.
  6. The right margin edge of an element's floating box may not be to the right of the right edge of any line-box containing a box generated by an element earlier in the source document.
  7. A top-floating box that has another top-floating box above it may not have its bottom margin edge below its containing block's bottom edge. (Loosely: a top float may not stick out at the bottom edge, unless it is already as far to the top as possible.) An analogous rule holds for bottom-floating elements.
  8. A floating box must be placed as far to the right as possible.
  9. A top-floating box must be put as far to the top as possible, a bottom-floating box as far to the bottom as possible. A position further to the right is preferred over one that is further to the top/bottom.

The rules for a float with a containing block with 'writing-mode: lr' are exactly the same after replacing left with top, right with bottom, top with left and bottom with right. They are given here for completeness:

[...]

Note that a box with a value of 'float' other than ''none'' is a flow root.

The border box of a table, a block-level replaced element, or an element in the normal flow that is a flow root (such as an element with 'overflow' other than ''visible'') must not overlap any floats in the same flow as the element itself. If necessary, implementations should clear the said element by placing it below any preceding floats, but may place it adjacent to such floats if there is sufficient space, by increasing one margin and decreasing the opposite margin. (“Sufficient space” means that the opposite margin does not become negative.)

The clear property

Name: clear
Value: none | left | right | both
Initial: none
Applies to: block-level elements
Inherited: no
Animatable: no
Percentages: N/A
Media: visual
Computed value: as specified
Canonical order: N/A

[To do: copy from CSS2 [[!CSS21]] and generalize to vertical text, define clearance.]

The clear-after property

Name: clear-after
Value: none | left | right | top | bottom | inside | outside | start | end | both | descendants
Initial: none
Applies to: block-level elements
Inherited: no
Animatable: no
Percentages: N/A
Media: visual
Computed value: specified value
Canonical order: N/A

It is sometimes useful to make sure that the bottom border of a block-level element goes below floating elements. The 'clear-after' property increases the element's padding as needed. More precisely: If the element has a block-end padding or block-end border, and there are any floats on the indicated side(s) in the current flow up to and including the end of this element, then find the one whose C margin edge is furthest away from the block-start content edge of the containing block. If that C margin edge is further from the containing block's block-start than the element's block-end content edge is, then increase the element's block-end padding by the difference.

The effect of 'clear-after: left' on a paragraph next to a floating image: the bottom padding of the paragraph is stretched, so that the original padding and the border go below the float.

Note: Since a floating element is a flow root, setting 'clear-after' on such an element only takes into account any descendant floats in the flow established by the element itself.

These four images illustrate the effect of 'clear-after' on elements with and without padding or border. They show two documents, both have two paragraphs and the top paragraph contains a floating image. In the document on the left, the first paragraph does not have any bottom padding or border. In the document on the right it does. The top row shows the layout without any 'clear-after', the bottom row shows the effect of setting 'clear-after: left' on the first paragraph.

'clear-after' Without padding or border With padding and border
''none''

The text of the second paragraph wraps around the floating image that started in the first paragraph.

The floating image that starts in the first paragraph overlaps the bottom border of that paragraph. The text of second paragraph wraps around the image as well.

''left''

As the first paragraph has no padding that can be stretched or border that can be moved, the 'clear-after' has no effect on it and the layout is exactly the same as in the first image.

The effect of 'clear-after' on the first paragraph is to increase the bottom padding so that the bottom border is now below the floating image. The second paragraph thus starts lower as well and doesn't have to wrap around the image.

The value of the property determines which kinds of floats are taken into account:

none
No effect.
left, top
Only left and top floating elements are considered.
right, bottom
Only right and bottom floating elements are considered,
inside
If the bottom of the element occurs on a right-hand page, only left floating elements are considered. On a left-hand page, only right floating elements. On media that are not paged, 'inside' means the same as 'left'.
outside
Analogous
start
If the 'direction' of the element is 'ltr', same as 'left', otherwise same as 'right'.
end
If the 'direction' of the element is 'ltr', same as 'right', otherwise same as 'left'.
both
Both left/top and right/bottom floats are considered.
descendants
All floats in the element's flow that are descendants of the element are considered, but not any other floats.

Use only two values: height-includes-floats and height-does-not-include floats? [DavidB 2004-02-29]

Instead of a new property 'clear-after', another idea is to add one or more values to 'clear'. If 'clear' is turned into a set, instead of a single value, one could add the value 'after' (clears both left and right floats) or several values like 'left-after' and 'right-after':

Name: clear
Value: none | [ left | right | top | bottom | inside | outside | start | end | both | after]+
Initial: none
Applies to: block-level elements
Inherited: no
Animatable: no
Percentages: N/A
Media: visual
Computed value: specified value
Canonical order: order of keywords as in grammar

The following rule would ensure that a SECTION starts below all preceding floats and doesn't end until after all floats it contains:

section {clear: left right after}

Daniel Beardsmore proposed a property 'underhang-limit: <count of full lines>' to protect against the case that the last line of a paragraph (or the last few lines) is shown under a float. In that case it looks better to indent that line like the other lines of the paragraph. The default is '1', i.e., no protection.

Overflow

When some content of an element is placed outside the element's content box, the element is said to overflow. This module allows overflow to be clipped, other modules may add other treatments, e.g., scale it down or to scroll it (“marquee,” see [[CSS3-MARQUEE]]).

The overflow, overflow-x and overflow-y properties

In the preceding sections, several things (such as flow roots) depend on the value of 'overflow'. We probably need to rewrite them in terms of “overflow-x and/or -y” or similar.

Name: overflow-x, overflow-y,
Value: visible | hidden | scroll | auto | no-display | no-content
Initial: visible
Applies to: non-replaced block-level elements and non-replaced ''inline-block'' elements
Inherited: no
Animatable: no
Percentages: N/A
Media: visual
Computed value:as specified, except 'visible', see text
Canonical order: N/A
Name: overflow
Value: [ visible | hidden | scroll | auto | no-display | no-content ]{1,2}
Initial: see individual properties
Applies to: non-replaced block-level elements and non-replaced ''inline-block'' elements
Inherited: no
Animatable: no
Percentages: N/A
Media: visual
Computed value:as specified, except 'visible', see text
Canonical order: N/A

These properties specify whether content is clipped when it overflows the element's content area. It affects the clipping of all of the element's content except any descendant elements (and their respective content and descendants) whose containing block is the viewport or an ancestor of the element. 'Overflow-x' determines clipping at the left and right edges, 'overflow-y' at the top and bottom edges.

'Overflow' is a shorthand. If it has one keyword, it sets both 'overflow-x' and 'overflow-y' to that keyword; if it has two, it sets 'overflow-x' to the first and 'overflow-y' to the second. Keywords 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.
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'', overflowing content may be printed.
auto
The behavior of the ''auto'' value is UA-dependent, but should cause a scrolling mechanism to be provided for overflowing boxes.
no-display
When the content doesn't fit in the content box, the whole box is removed, as if 'display: none' were specified. [This idea is due to Till Halbach <tillh@opera.com>, July 21, 2005]
no-content
When the content doesn't fit in the content box, the whole content is hidden, as if 'visibility: hidden' were specified. [This idea is due to Till Halbach <tillh@opera.com>, July 21, 2005]

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

UAs must apply the 'overflow' property set on the root element to the viewport. HTML UAs must instead apply the 'overflow' property from the BODY element to the viewport, if the value on the HTML element is ''visible''. The ''visible'' value when used for the viewport must be interpreted as ''auto''. The element from which the value is propagated must have a used value for 'overflow' of ''visible''.

The para above is from CSS 2.1. Need to check if the introduction of overflow-x/y changes anything.

In the case of a scrollbar being placed on an edge of the element's box, it should be inserted between the inner border edge and the outer padding edge. The space taken up by the scrollbars affects the computation of the dimensions in the rendering model.

A UA may use multiple scrolling mechanisms at the same time. E.g., if content overflows both to the right and to the bottom, it may use a marquee effect for the overflow to the right and a scrollbar for the overflow to the bottom.

Note that a box with 'overflow' other than ''visible'' is a flow root.

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:

<div>
<blockquote>
<p>I didn't like the play, but then I saw
it under adverse conditions - the curtain was up.</p>
<cite>- Groucho Marx</cite>
</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
      }

cite { display: block;
       text-align : right; 
       border: none
       }

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

[image: Rendered overflow]

Possible rendering with 'overflow: visible'

Setting 'overflow' to ''hidden'' for the <div>, on the other hand, causes the <blockquote> to be clipped by the containing block:

[image: Rendered overflow]

Possible rendering with 'overflow: hidden'

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

Consider this case where an absolutely positioned element is mixed with an overflow parent. Style sheet:

container { position: relative; border: solid; }
scroller { overflow: scroll; height: 5em; margin: 5em; }
satellite { position: absolute; top: 0; }
body { height: 10em; }

Document fragment:

<container>
 <scroller>
  <satellite/>
  <body/>
 </scroller>
</container>

In this example, the “scroller” element will not scroll the “satellite” element, because the latter's containing block is outside the element whose overflow is being clipped and scrolled.

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 and would normally just fit:

...
    #d1 { overflow: auto; max-height: 5em }
    #d2 { margin: 2em; 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 the height of d1, including the single line of text and twice 2em of margins, adds up to 5em plus a scrollbar. Since that 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 content height of d1 is exactly the maximum height of 5em, proving that the assumption was correct and d1 indeed should not have scrollbars.

The computed values of 'overflow-x' and 'overflow-y' are the same as their specified values, except that some combinations with 'visible' are not possible: if one is specified as 'visible' and the other is 'scroll' or 'auto', then 'visible' is set to 'auto'. The computed value of 'overflow' is equal to the computed value of 'overflow-x' if 'overflow-y' is the same; otherwise it is the pair of computed values of 'overflow-x' and 'overflow-y'.

The scrolling mechanism depends on the UA. The most common mechanism is a scrollbar, but panners, hand cursors, page flickers, etc. are also possible. A value of 'scroll' would tell UAs that support a visible scrolling mechanism to display one so that users can access the clipped content. The 'overflow-style' property lets an author specify one or more preferred scrolling mechanism.

Note that 'overflow-x' and 'overflow-y' did not exist in CSS2.

Note that 'text-overflow' (see [[!CSS3TEXT]]) can be used to give a visual indication where text has been clipped.

The visibility property

Name: visibility
Value: visible | hidden | collapse
Initial: visible
Applies to: all elements
Inherited: yes
Animatable: no
Percentages: N/A
Media: visual
Computed value: as specified
Canonical order: N/A

This 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, nothing is drawn), but still affects layout. Furthermore, descendants of the element will be visible if they have 'visibility: visible'.
collapse
See the Tables module [[CSS3TBL]]. If used on elements other than rows, row groups, columns, or column groups, ''collapse'' has the same meaning as ''hidden''.

The alignment property

Name: alignment
Value: top | right | bottom | left | center
Initial: see text
Applies to: block-level elements
Inherited: no
Animatable: no
Percentages: N/A
Media: visual
Computed value: specified value
Canonical order: N/A

For consistency with 'text-align', maybe this should be called 'block-align'.

This property influences how a block in the normal flow is aligned in its parent in the inline progression direction. It affects the used values of 'margin-left' and 'margin-right' (for horizontal blocks) or 'margin-top' and 'margin-bottom' (for vertical blocks), as defined in “Calculating widths, heights and margins.”

The initial value depends on both 'writing-mode' and 'direction', as follows:

tb rl lr
ltr left top top
rtl right bottom bottom

Note that this property doesn't exist in level 2.

The 'alignment' property in combination with the ''fit-content'' value of 'width' can be used to make borders that enclose just the content of a heading, without the need for an additional element:

h2 {
  margin-top: 1em;
  margin-bottom: 1em;
  border: solid;
  padding: 0.5em;
  alignment: center;
  width: fit-content}
<p>Lorem ipsum dolor sit amet...
<h2>A section heading</h2>
<p>Lorem ipsum dolor sit amet...
<h2>Another section heading</h2>
<p>Lorem ipsum dolor sit amet...

See the figure below for a possible rendering.

Image: centered headings with border tightly
  around the text

A possible rendering of the example.

The child-align property

Other names: block-align (but note that it influences the children of the block, not the block itself), block-vertical-align (but note that it really means horizontal if the block's 'writing-mode' is ''lr'' or ''rl''), and align-content (current name in [[CSS3-ALIGN]]).

Name: child-align
Value: top | middle | bottom | left | right | auto
Initial: auto
Applies to: block-level elements, table cells and inline blocks
Inherited: yes
Animatable: no
Percentages: N/A
Media: visual
Computed value: the initial value or as specified
Canonical order: N/A

This property describes how block-level content of a block is aligned vertically, or more precisely: in the block progression direction. Values have the following meanings:

top, bottom, left, right
Child blocks are aligned in the current block depending on the 'child-align' and 'writing-mode' as follows:
top bottom left right
tb top bottom top top
rl right right left right
lr left left left right
middle
Child blocks are centered in the block progression direction.
auto
Child blocks are aligned according to 'writing-mode': at the top if ''tb'', at the right if ''rl'' and at the left if ''lr''.

An element with 'child-align' values other than ''auto'' is a flow root. Content of such a block is formatted as follows:

  1. Content is laid out as a regular sequence of blocks.
  2. To be discussed: If the smallest rectangle that encloses all margin boxes of the children (excluding absolutely positioned children and counting relatively positioned children as if they had zero offset) is bigger in the block progression direction than the content box of the current element, then the content is placed in that content box as if 'child-align' were ''top''.
  3. The content is shifted such that the rectangle that encloses all margin boxes of the children (excluding absolutely positioned children and counting relatively positioned children as if they had zero offset) touches an edge of the content box. Which edge of the rectangle and which edge of the content box is determined by the table above. But if 'child-align' is 'middle', the rectangle is instead centered in the content box.

Note that the effect of 'child-align' can also be achieved with template layout [[CSS3LAYOUT]]. E.g.,

div {child-align: bottom}

is the same as

div {grid: "a"};
div::slot(a) {vertical-align: bottom}

except that the latter forces the DIV to be a block, while the former leaves the 'display' value of the DIV unchanged (but has no effect unless the DIV is block-level).

When this property applies and is not ''auto'', then 'vertical-align' does not apply. E.g., the placement of the content of a table cell is determined by 'vertical-align' only if 'child-align' is ''auto'', otherwise 'child-align' determines the placement.

Or, alternatively, 'child-align' doesn't apply to elements that 'vertical-align' applies to, i.e., only to ''block'', ''list-item'', ''inline-block'' and ''run-in'' (under circumstances).

In paged media and in multi-column layout, page breaks and column breaks are calculated first, then the content is vertically aligned according to the property within each portion of the parent block.

Stacking contexts

This section defines the painting order in more detail than described in the rest of the specification.

Definitions

Tree Order
Preorder depth-first traversal of the rendering tree, in logical (not visual) order for bidirectional content, after taking into account properties that move boxes around such as the 'run-in' value of 'display'.
Element
In this description, “element” refers to actual elements, pseudo-elements, and anonymous boxes. Pseudo-elements and anonymous boxes are treated as descendants in the appropriate places. For example, an outside list marker comes before an adjoining '::before' box in the line box, which comes before the content of the box, and so forth.

Painting order

The bottom of the stack is the furthest from the user, the top of the stack is the nearest to the user:

All layers are between the canvas
      and the user

Schematic diagram of a stacking context with four layers.

The stacking context background and most negative positioned stacking contexts are at the bottom of the stack, while the most positive positioned stacking contexts are at the top of the stack.

The canvas is transparent if contained within another, and given a UA-defined color if it is not. It is infinite in extent and contains the root element. Initially, the viewport is anchored with its top left corner at the canvas origin.

The stacking order for an element generating a stacking context (see the 'z-index' property) is:

  1. If the element is a root element:

    1. background color of element over the entire canvas.
    2. background image of element, over the entire canvas, anchored at the origin that would be used if it was painted for the root element.
  2. If the element is a block, list-item, or other block equivalent:

    1. background color of element unless it is the root element.
    2. background image of element unless it is the root element.
    3. border of element.

    Otherwise, if the element is a block level table:

    1. table backgrounds (color then image) unless it is the root element.
    2. column group backgrounds (color then image).
    3. column backgrounds (color then image).
    4. row group backgrounds (color then image).
    5. row backgrounds (color then image).
    6. cell backgrounds (color then image).
    7. all table borders (in tree order for separated borders).
  3. Stacking contexts formed by positioned descendants with negative z-indices (excluding 0) in z-index order (most negative first) then tree order.

  4. For all its in-flow, non-positioned, block-level descendants in tree order: If the element is a block, list-item, or other block equivalent:

    1. background color of element.
    2. background image of element.
    3. border of element.

    Otherwise, the element is a table:

    1. table backgrounds (color then image).
    2. column group backgrounds (color then image).
    3. column backgrounds (color then image).
    4. row group backgrounds (color then image).
    5. row backgrounds (color then image).
    6. cell backgrounds (color then image).
    7. all table borders (in tree order for separated borders).
  5. All non-positioned floating descendants, in tree order. For each one of these, treat the element as if it created a new stacking context, but any positioned descendants and descendants which actually create a new stacking context should be considered part of the parent stacking context, not this new one.

  6. If the element is an inline element that generates a stacking context, then:

    1. For each line box that the element is in:

      1. Jump to 7.2.1 for the box(es) of the element in that line box (in tree order).
  7. Otherwise: first for the element, then for all its in-flow, non-positioned, block-level descendants in tree order:

    1. If the element is a block-level replaced element, then: the replaced content, atomically.

    2. Otherwise, for each line box of that element:

      1. For each box that is a child of that element, in that line box, in tree order:

        1. background color of element.

        2. background image of element.

        3. border of element.

        4. For inline elements:

          1. For all the element's in-flow, non-positioned, inline-level children that are in this line box, and all runs of text inside the element that is on this line box, in tree order:

            1. If this is a run of text, then:

              1. any underlining affecting the text of the element, in tree order of the elements applying the underlining (such that the deepest element's underlining, if any, is painted topmost and the root element's underlining, if any, is drawn bottommost).
              2. any overlining affecting the text of the element, in tree order of the elements applying the overlining (such that the deepest element's overlining, if any, is painted topmost and the root element's overlining, if any, is drawn bottommost).
              3. the text.
              4. any line-through affecting the text of the element, in tree order of the elements applying the line-through (such that the deepest element's line-through, if any, is painted topmost and the root element's line-through, if any, is drawn bottommost).
            2. Otherwise, jump to 7.2.1 for that element.

          For inline-block and inline-table elements:

          1. For each one of these, treat the element as if it created a new stacking context, but any positioned descendants and descendants which actually create a new stacking context should be considered part of the parent stacking context, not this new one.

          For inline-level replaced elements:

          1. the replaced content, atomically.

        Some of the boxes may have been generated by line splitting or the Unicode bidirectional algorithm.

      2. Optionally, the outline of the element (see 10 below).

    3. Optionally, if the element is block-level, the outline of the element (see 10 below).

  8. All positioned descendants with 'z-index: auto' or 'z-index: 0', in tree order. For those with 'z-index: auto', treat the element as if it created a new stacking context, but any positioned descendants and descendants which actually create a new stacking context should be considered part of the parent stacking context, not this new one. For those with 'z-index: 0', treat the stacking context generated atomically.

  9. Stacking contexts formed by positioned descendants with z-indices greater than or equal to 1 in z-index order (smallest first) then tree order.

  10. Finally, implementations that do not draw outlines in steps above must draw outlines from this stacking context at this stage. (It is recommended to draw outlines in this step and not in the steps above.)

Notes

The background of the root element is only painted once, over the whole canvas.

While the backgrounds of bidirectional inlines are painted in tree order, they are positioned in visual order. Since the positioning of inline backgrounds is unspecified in CSS 2.1, the exact result of these two requirements is UA-defined. CSS3 may define this in more detail. [Replace 2.1 by 3. Check if inline backgrounds are still undefined, otherwise say result is UA-dependent.]

The 'float-displace' and 'indent-edge-reset' properties [alternative 1]

The 'float-displace' property defines different ways in which text can wrap around a float.

Could this property be merged with 'wrap-flow' in [[CSS3-EXCLUSIONS]]?

The 'float-displace' property

Name: float-displace
Value: line | indent | block | block-within-page
Initial: line
Applies to: all block-level elements
Inherited: yes
Animatable: no
Percentages: N/A
Media: visual
Computed value: Same as specified value
Canonical order: N/A

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 between 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 of 'float-displace: indent'. Note that the “bar” paragraph has the same indent (green arrow) next to the float as below it .

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 of 'float-displace: block'

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...?

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 'indent-edge-reset' property

Name: indent-edge-reset
Value: none | margin-edge | border-edge | padding-edge | content-edge
Initial: none
Applies to: all elements with a block-level inner formatting context.
Inherited: no
Animatable: yes
Percentages: n/a
Media: visual
Computed value: specified value
Canonical order: N/A

This property determines which edge to use as the reference indent edge when calculating the amount of indent to preserve when the value of 'float-displace' is set to ''indent''.

none
This block does not introduce a new reference edge.
margin-edge
border-edge
padding-edge
content-edge
A new reference indent edge is introduced by this block. Which edge is used as the reference indent edge is determined by which value is given.

The reference indent edge is the nearest ancestor in the same formatting context which has a non-none value for 'indent-edge-reset'. If no ancestor in the formatting context has a value specified for this property, then the content edge of the root of the formatting context is used.

The ‘float-displace’ property [alternative 2]

Alternative definition, that (1) avoids the need for 'indent-edge-reset' and (2) changes not just the line boxes, but also the content edge, so that list markers stay close to the content:

Name: float-displace
Value: line | indent | block | block-within-page
Initial: line
Applies to: all block-level elements
Inherited: yes
Animatable: no
Percentages: N/A
Media: visual
Computed value: Same as specified value
Canonical order: N/A
line

Line boxes are shortened so they don't overlap floats. See below for the details. The element's margin, border or padding are not influenced by the presence of floats. (This is the only behavior in CSS level 2.)

indent

Line boxes are first shortened as for ''line''. If the distance between the inline-start edge of the content box and the inline-start edge of the line box is then not zero, then that distance is further increased by the element's relative indent (defined below). Ditto for the inline-end edge. The element's margin, border or padding are not influenced by the presence of floats.

block

The margins of the element are increased (and the width thus reduced) by the amount necessary so that the border box of the element doesn't overlap any floats in the same flow that are created by elements earlier in the document; and then the margins are increased even more by the amount of the relative indent on the relevant side of the element. If that causes the element to have more overflow than it would have had with a value of ''line'', the element is moved down instead (by adding clearance) just enough that it doesn't have more overflow, or that its top border edge is just below the bottom margin edge of all floats.

Line boxes inside the element are shortened and/or moved as needed the same way as for ''line''.

Note that floats that are descendants of the element do not influence the element's margins, but they may influence the line boxes.

block-within-page

Like block, except that the parts of the element on different pages are treated as separate blocks for the purpose of this property and are only indented as necessary to avoid floats on the same page.

Note that centered text ('text-align' is ''center'') is centered relative to the content edges, not relative to the edges of the line box.

Note also that ''block'' and ''block-within-page'' influence the position of the element's list marker (if any), because list markers are positioned relative to the content edge. Indeed, this may be the main reason for using 'float-displace': to move the list markers from one side of the float (or on top of the float) to the other side.

A line box normally stretches from an element's content edge to the opposite content edge, unless it overflows (see [[!CSS3TEXT]]), but if the element's 'float-displace' is ''line'' or ''indent'' it may fall short of either or both content edges. The following defines how line boxes are shortened in the case of ''line'':

For all elements E, and all floats F whose parent is in the same flow as E, and all line boxes L of E: if L contains any inline boxes that are generated by elements that come after F in the document, then L must may not overlap the exclusion zone of F.

Note that a line box next to a float cannot overflow: if an inline box is too wide for a shortened line box, the line box is left empty and the inline box is put in the next line box in which it fits, or the next one that is not shortened by floats. [Is this indeed correctly defined in [[!CSS3TEXT]]?]

Implementation note: Note that the height of a line box depends on its content. It may be, e.g., that a line box next to a float has enough room horizontally for three words, but adding the third word would increase the height of the line box and make it overlap the next float further down. In that case the third word cannot be added to that line box and must be put in the next line box (or even further down).

The relative indent on side S of an element E is defined recursively as follows:

How line boxes are constructed is explained in the CSS Text Module [[!CSS3TEXT]]. The presence of a float modifies that construction in two ways: the length of the line box can become shorter (i.e., shorter than the distance between the element's content edges) and, unlike a normal line box, such a shorter line box may be empty. The following describes these effects in detail.

We consider construction of line boxes in horizontal elements first. (Vertical elements are analogous and are defined below.) Let L be a line box

The ‘float-displace’ property [alternative 3]

Yet another alternative. This one adds a fixed indent rather than one that depends on the context:

Name: float-displace
Value: auto | <length> && [ block | block-within-page ]?
Initial: line
Applies to: all block-level elements
Inherited: no
Animatable: no
Percentages: N/A
Media: visual
Computed value: Same as specified value
Canonical order: N/A
auto

Line boxes are shortened and/or moved so they don't overlap floats. (This is the only behavior in CSS level 2.)

<length>

Line boxes are shortened and/or moved as for ''auto'', except that the amount they are shortened by, if possible, is equal to the amount necessary to not overlap any float plus the given <length>.

block

If the keyword ''block'' is present in addition to a <length>, the margins of the element are increased (and the width thus reduced) by the amount necessary so that the border box of the element doesn't overlap any floats in the same flow that are created by elements earlier in the document; and then the margins are increased even more by the given <length>. If that causes the element to have more overflow than it would have had with a value of ''auto'', the element is moved down instead (by adding clearance) just enough that it doesn't have more overflow, or that its top border edge is just below the bottom margin edge of all earlier floats in the same flow.

Line boxes inside the element are shortened and/or moved as needed the same was as for ''auto''.

Note that floats that are descendants of the element do not influence the element's margins, but they may influence the line boxes.

block-within-page

Like block, except that the parts of the element on different pages are treated as separate blocks for the purpose of this property and are only indented as necessary to avoid floats on the same page.

Note that all values, except ''auto'', also cause centered lines to no longer be centered if they are next to a float.

Note also that ''block'' and ''block-within-page'' influence the position of the element's list marker (if any), because list markers are positioned relative to the content edge. Indeed, this may be the main reasons for using 'float-displace': to move the list markers from one side of the float (or on top of the float) to the other side.

Example: Assume that the floating image is tall than the paragraph it is part of.

img {float: left}
ul {float-displace: 2em block}
li {margin-left: 2em}

with document fragment

<p>
  <img src=... alt=... style="float: left">
  Paragraph before the list.

<ul>
  <li>First item
  <li>Second item
</ul>

Without the image, the rendering might look like this:

Paragraph before the list.

  * First item
  * Second item

With the image, but without the rule for 'float-displace', the output might look like this:

+----+Paragraph before the list.
|\  /|
| */ |First item
| *\ |Second item
|/  \|
+----+

With the 'float-displace' rule, the UL is indented extra to avoid the image, plus 2em more:

+----+Paragraph before the list.
|\  /|
| \/ |  * First item
| /\ |  * Second item
|/  \|
+----+

Conformance

Acknowledgments

To do…

References

Normative references

Informative references

Index

Property index