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.
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.
This CSS module depends on the following other CSS modules:
Some issues that affect multiple sections in this document:
Horizontal centering (more precisely: centering in the inline direction). The draft contains several suggestions:
P {margin: 1em fill}
P {alignment: center}
DIV {child-align: middle}
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:
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:
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.
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.
DIV {vertical-align: middle}
This centers or aligns all content, it cannot top-align the first child and bottom-align the last.
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.
<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>...
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.
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).
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.
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.
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.
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:
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:
div
is a flow root, because it floats. Its flow
consist of the 1st, 2nd and 4th p
and the
blockquote
.
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.
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]].
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.
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.
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) }
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:
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).
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:
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>
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).
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:
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.
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]].
For the purposes of the width and height calculations below, CSS distinguishes four kinds of replaced elements:
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.)
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):
When the fragment is rendered, the text before the q is wrapped in an anonymous block and the text after the q in another.
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.
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.
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 margin P collapses with a margin Q and margin Q with a margin R, then P, Q and R collapse together. (“Collapsing is transitive”)
A margin of a box collapses with the block-start margin of its parent box if those two margins are adjoining.
A margin of a box collapses with the block-end margin of its parent box if those two margins are adjoining.
The C margin of a box collapses with the A margin of a sibling box if the two margins are adjoining.
The A and C margins of a box collapse with each other if the two margins are adjoining. (The box is “collapsed through.”)
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.
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]].
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':
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 min ≤ max 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'.
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.
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.
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 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.
inline-start margin + inline-start border + inline-start padding + measure + inline-end padding + inline-end border + inline-end margin = measure of containing block
inline-start margin + inline-start border + inline-start padding + measure + inline-end padding + inline-end border + inline-end margin = width or height of initial containing block
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:
If none of the values is ''auto'', then there are three sub-cases:
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}
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''.”
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?
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.
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.
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:
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.
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.
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.
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.
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:
User agents may treat float as ''none'' on the root element.
(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:
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:
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.
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:
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).
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.
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:
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...]
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.)
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.]
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:
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.
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]]).
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:
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:
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:
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.
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:
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.
A possible rendering of the example.
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 | |
---|---|---|---|---|
tb | top | bottom | top | top |
rl | right | right | left | right |
lr | left | left | left | right |
An element with 'child-align' values other than ''auto'' is a flow root. Content of such a block is formatted as follows:
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.
This section defines the painting order in more detail than described in the rest of the specification.
The bottom of the stack is the furthest from the user, the top of the stack is the nearest to 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:
If the element is a root element:
If the element is a block, list-item, or other block equivalent:
Otherwise, if the element is a block level table:
Stacking contexts formed by positioned descendants with negative z-indices (excluding 0) in z-index order (most negative first) then tree order.
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:
Otherwise, the element is a table:
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.
If the element is an inline element that generates a stacking context, then:
For each line box that the element is in:
Otherwise: first for the element, then for all its in-flow, non-positioned, block-level descendants in tree order:
If the element is a block-level replaced element, then: the replaced content, atomically.
Otherwise, for each line box of that element:
For each box that is a child of that element, in that line box, in tree order:
background color of element.
background image of element.
border of element.
For inline elements:
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:
If this is a run of text, then:
Otherwise, jump to 7.2.1 for that element.
For inline-block and inline-table elements:
For inline-level replaced elements:
Some of the boxes may have been generated by line splitting or the Unicode bidirectional algorithm.
Optionally, the outline of the element (see 10 below).
Optionally, if the element is block-level, the outline of the element (see 10 below).
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.
Stacking contexts formed by positioned descendants with z-indices greater than or equal to 1 in z-index order (smallest first) then tree order.
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.)
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' property defines different ways in which text can wrap around a float.
Could this property be merged with 'wrap-flow' in [[CSS3-EXCLUSIONS]]?
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:
Example of 'float-displace: indent'. Note that the “bar” paragraph has the same indent (green arrow) next to the float as below it .
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 'float-displace: block'
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.
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''.
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.
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 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.)
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.
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.
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
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 |
---|
Line boxes are shortened and/or moved so they don't overlap floats. (This is the only behavior in CSS level 2.)
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>.
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.
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 |/ \| +----+
To do…