1. Introduction
This section is not normative.
The CSS layout algorithms, by default, size and position boxes in relation to each other so that nothing overlaps.
This specification defines several ways to violate these assumptions when needed, moving elements around in ways that can make them overlap other content:
-
Relative positioning, which visually shifts a box relative to its laid-out location.
-
Sticky positioning, which visually shifts a box relative to its laid-out location in order to keep it visible when a scrollable ancestor would otherwise scroll it out of sight.
-
Absolute positioning, which ignores normal layout entirely, pulling the element out of flow and positioning it relative to its containing block with no regard for other content.
-
Fixed positioning, which absolutely positions the box and affixes it to the viewport or page frame so that it is always visible.
These positioning schemes, controlled by the position property and the inset properties, are powerful but easy to misuse. With appropriate care, they allow many interesting and useful layouts that couldn’t otherwise be achieved with standard layout rules; without, they allow a page to be laid out in an unusable overlapping jumble of content.
1.1. Module Interactions
This module replaces and extends the positioning scheme features defined in [CSS2] sections:
- 9.1.2 Containing blocks
- 9.3 Positioning schemes
- 9.4.3 Relative positioning
- 9.6 Absolute positioning
- 9.7 Relationships between display, position, and float
- 9.8 Comparison of normal flow, floats, and absolute positioning
- 10.1 Definition of "containing block"
- 10.3.7 Absolutely positioned, non-replaced elements
- 10.3.8 Absolutely positioned, replaced elements
- 10.6.4 Absolutely positioned, non-replaced elements
- 10.6.5 Absolutely positioned replaced elements
It also replaces and supersedes the inset* property definitions in [CSS-LOGICAL-1] (CSS Logical Properties 1 § 4.3 Flow-relative Offsets: the inset-block-start, inset-block-end, inset-inline-start, inset-inline-end properties and inset-block, inset-inline, and inset shorthands).
1.2. Value Definitions
This specification follows the CSS property definition conventions from [CSS2] using the value definition syntax from [CSS-VALUES-3]. Value types not defined in this specification are defined in CSS Values & Units [CSS-VALUES-3]. Combination with other CSS modules may expand the definitions of these value types.
In addition to the property-specific values listed in their definitions, all properties defined in this specification also accept the CSS-wide keywords as their property value. For readability they have not been repeated explicitly.
2. Choosing A Positioning Scheme: position property
Name: | position |
---|---|
Value: | static | relative | absolute | sticky | fixed |
Initial: | static |
Applies to: | all elements except table-column-group and table-column |
Inherited: | no |
Percentages: | N/A |
Computed value: | specified keyword |
Canonical order: | per grammar |
Animation type: | discrete |
The position property determines which of the positioning schemes is used to calculate the position of a box. Values other than static make the box a positioned box, and cause it to establish an absolute positioning containing block for its descendants. Values have the following meanings:
- static
- The box is not a positioned box, and is laid out according to the rules of its parent formatting context. The inset properties do not apply.
- relative
- The box is laid out as for static, then offset from the resulting position. This offsetting is a purely visual effect, and, unless otherwise specified, does not affect the size or position of any other non-descendant box except insofar as it increases the scrollable overflow area of its ancestors. This positioning scheme is called relative positioning.
- sticky
- Identical to relative, except that its offsets are automatically adjusted in reference to the nearest ancestor scroll container’s scrollport (as modified by the inset properties) in whichever axes the inset properties are not both auto, to try to keep the box in view within its containing block as the user scrolls. This positioning scheme is called sticky positioning.
- absolute
-
The box is taken out of flow
such that it has no impact on the size or position of its siblings and ancestors,
and does not participate in its parent’s formatting context.
Instead, the box is positioned and sized solely in reference to its absolute positioning containing block, as modified by the box’s inset properties, see § 4 Absolute Positioning Layout Model. It can overlap in-flow content or other absolutely positioned elements, and is included in the scrollable overflow area of the box that generates is containing block. This positioning scheme is called absolute positioning.
- fixed
-
Same as absolute,
except the box is positioned and sized relative to a fixed positioning containing block
(usually the viewport in continuous media, or the page area in paged media).
The box’s position is fixed with respect to this reference rectangle:
when attached to the viewport
it does not move when the document is scrolled,
and when attached to the page area
is replicated on every page when the document is paginated.
This positioning scheme is called
fixed positioning
and is considered a subset of absolute positioning.
Authors may wish to specify fixed in a media-dependent way. For instance, an author may want a box to remain at the top of the viewport on the screen, but not at the top of each printed page. The two specifications may be separated by using an '@media' rule, as in:
@media screen{ h1#first{ position : fixed} } @media print{ h1#first{ position : static} }
A position value of absolute or fixed blockifies the box, causes float to compute to none, and forces the box to establish an independent formatting context.
2.1. Containing Blocks of Positioned Boxes
The containing block of a static, relative, or sticky box is as defined by its formatting context. For fixed and absolute boxes, it is defined as follows:
- If the box has position: absolute:
-
The containing block is established
by the nearest ancestor box that establishes an absolute positioning containing block,
in the following way:
- If the ancestor is not an inline box,
- the containing block is formed by the padding edge of the ancestor, unless otherwise specified (for example, see CSS Grid Layout 1 § 9.1 With a Grid Container as Containing Block).
- If the ancestor is an inline box, using the writing mode of that box,
-
the containing block is formed by forming a rectangle from
the start-most content edges (in both axes) of the first box fragment of the ancestor,
and the end-most content edges of the end-most box fragment(s) of the ancestor in each axis.
If there are multiple fragments on the same line
(e.g. due to bidi reordering),
take the start-most fragment
as the first fragment.
What is a useful containing block to form when the box is fragmented across multiple lines? [Issue #8284]
Note: The containing block formed by a fragmented inline box was undefined in [CSS2].
If no ancestor establishes one, the absolute positioning containing block is the initial containing block.
Note: Properties that can cause a box to establish an absolute positioning containing block include position, transform, will-change, contain…
- If the box has position: fixed:
-
The containing block is established
by the nearest ancestor box that establishes an fixed positioning containing block,
with the bounds of the containing block
determined identically to the absolute positioning containing block.
Note: Properties that can cause a box to establish a fixed positioning containing block include transform, will-change, contain…
If no ancestor establishes one, the fixed positioning containing block is:
-
in continuous media, the layout viewport (whose size matches the dynamic viewport size); as a result, fixed boxes do not move when the document is scrolled.
Note: In this respect, they are similar to fixed background images (background-attachment: fixed).
-
in paged media, the page area of each page; fixed positioned boxes are thus replicated on every page. (They are fixed with respect to the page box only, and are not affected by being seen through a viewport; as in the case of print preview, for example.)
Note: As a result, parts of fixed-positioned boxes that extend outside the layout viewport/page area cannot be scrolled to and will not print.
-
With no positioning, the containing blocks (C.B.) in the following document:
<!DOCTYPE html> < html > < head > < title > Illustration of containing blocks</ title > </ head > < body id = "body" > < div id = "div1" > < p id = "p1" > This is text in the first paragraph...</ p > < p id = "p2" > This is text< em id = "em1" > in the< strong id = "strong1" > second</ strong > paragraph.</ em ></ p > </ div > </ body > </ html >
are established as follows:
For box generated by | C.B. is established by |
---|---|
html | initial C.B. (UA-dependent) |
body | html |
div1 | body |
p1 | div1 |
p2 | div1 |
em1 | p2 |
strong1 | p2 |
If we position "div1":
#div1{ position : absolute; left : 50 px ; top : 50 px }
its containing block is no longer "body"; it becomes the initial containing block (since there are no other positioned ancestor boxes).
If we position "em1" as well:
#div1{ position : absolute; left : 50 px ; top : 50 px } #em1{ position : absolute; left : 100 px ; top : 100 px }
the table of containing blocks becomes:
For box generated by | C.B. is established by |
---|---|
html | initial C.B. (UA-dependent) |
body | html |
div1 | initial C.B. |
p1 | div1 |
p2 | div1 |
em1 | div1 |
strong1 | em1 |
By positioning "em1", its containing block becomes the nearest positioned ancestor box (i.e., that generated by "div1").
2.1.1. Further Adjustments to the Containing Block
Some features can alter the effective containing block rectangle of absolutely positioned boxes. These are applied in the following order, with earlier steps modifying the containing block that later steps see:
-
The grid-placement properties on an absolutely positioned box whose containing block is generated by a grid container can change the containing block rectangle to a specified grid area. See CSS Grid Layout 1 § 9.1 With a Grid Container as Containing Block.
-
The position-area and position-try properties can change the containing block rectangle to a specified area of an position-area grid. See CSS Anchor Positioning § 3.1 The position-area Property.
The element’s original containing block is its containing block before applying any of these effects.
2.2. Painting Order and Stacking Contexts
The z-index property applies to all positioned boxes. When z-index is auto:
-
Fixed and sticky positioned boxes nonetheless form a stacking context.
-
Relative and absolute positioned boxes do not form a stacking context, but are painted as if those elements did generated new stacking contexts, except that their positioned descendants and any would-be child stacking contexts take part in the current stacking context.
Note: The root element always forms a stacking context regardless.
See CSS2 § 9.9 Layered presentation and Appendix E: Elaborate description of Stacking Contexts for details about z-index, stacking contexts, and painting order.
3. Positioning Coordinates
The precise location of a positioned box is controlled by the inset properties: the physical inset properties top, right, bottom, left; the flow-relative inset properties inset-block-start, inset-inline-start, inset-block-end, and inset-inline-end; and their shorthands, inset-block, inset-inline, and inset.
The interpretation of these inset properties varies by positioning scheme:
-
for absolute positioning, they represent insets from the containing block.
-
for relative positioning, they represent insets from the box’s original margin edge.
-
for sticky positioning, they represent insets from the scrollport edge.
3.1. Box Insets: the top, right, bottom, left, inset-block-start, inset-inline-start, inset-block-end, and inset-inline-end properties
Name: | top, right, bottom, left, inset-block-start, inset-inline-start, inset-block-end, inset-inline-end |
---|---|
Value: | auto | <length-percentage> |
Initial: | auto |
Applies to: | positioned elements |
Inherited: | no |
Percentages: | refer to size of containing block; see prose |
Computed value: | the keyword auto or a computed <length-percentage> value |
Canonical order: | per grammar |
Animation type: | by computed value type |
Logical property group: | inset |
These inset properties represent an inward “inset” on the corresponding side of the box (with respect to the box’s own writing mode; see CSS Writing Modes 3 § 6 Abstract Box Terminology). For example, top represents a downward inset of the top edge. The physical and flow-relative properties interact as defined in [CSS-LOGICAL-1]. Values have the following meanings:
- <length>
- The inset is a fixed distance from the reference edge. Negative values are allowed.
- <percentage>
- The inset is a percentage relative to the containing block’s size in the corresponding axis (e.g. width for left or right, height for top and bottom). For sticky positioned boxes, the inset is instead relative to the relevant scrollport’s size. Negative values are allowed.
- auto
- Represents an unconstrained inset; the exact meaning depends on the positioning scheme.
Note: For fixed positioned elements, using large values or negative values can easily move elements outside the viewport and make the contents unreachable through scrolling or other means.
3.2. Box Insets Shorthands: the inset-block, inset-inline, and inset properties
Name: | inset-block, inset-inline |
---|---|
Value: | <'top'>{1,2} |
Initial: | auto |
Applies to: | positioned elements |
Inherited: | no |
Percentages: | see individual properties |
Computed value: | see individual properties |
Canonical order: | per grammar |
Animation type: | by computed value type |
The inset-block and inset-inline properties are shorthand properties for setting inset-block-start + inset-block-end or inset-inline-start + inset-inline-end, respectively, in a single declaration. The first component value sets the start side, the second sets the end; if omitted, the second value defaults to the first.
Name: | inset |
---|---|
Value: | <'top'>{1,4} |
Initial: | auto |
Applies to: | positioned elements |
Inherited: | no |
Percentages: | see individual properties |
Computed value: | see individual properties |
Canonical order: | per grammar |
Animation type: | by computed value type |
The inset property is a shorthand property that sets all of the inset properties in a single declaration, assigning values to the longhands representing each side exactly as the margin property does for its longhands.
By default, the inset property values are assigned to the corresponding physical longhand properties—top, right, bottom, and left—which for historical reasons do not have an inset- prefix. This matches the behavior of other "4 values assigned to sides" properties, such as margin.
Allowing properties such as this to resolve to the flow-relative longhands is under discussion in [CSS-LOGICAL-1].
Yes, we understand it’s a little confusing that inset doesn’t expand to any inset-* properties.
3.3. Relative Positioning
For a relatively positioned box, the inset properties move the box inward from the respective edge, without changing its size. left moves the box to the right, right moves it to the left, etc. Since boxes are not split or stretched as a result of relative positioning opposing used values in a given axis must be negations of each other:
- If opposing inset properties in an axis both compute to auto (their initial values), their used values are zero (i.e., the boxes stay in their original position in that axis).
- If only one is auto, its used value becomes the negation of the other, and the box is shifted by the specified amount.
- If neither is auto, the position is over-constrained; (with respect to the writing mode of its containing block) the computed end side value is ignored, and its used value becomes the negation of the start side.
The following three rules are equivalent, and shift the box 1em to the left:
div.a8{ position : relative; direction : ltr; left : -1 em ; right : auto} div.a8{ position : relative; direction : ltr; left : auto; right : 1 em } div.a8{ position : relative; direction : ltr; left : -1 em ; right : 5 em }
If specified on a table-row-group, table-header-group, table-footer-group, or table-row box the shift affects all the contents of the box, including all table cells that originate in the affected row, but not those that don’t.
Note: Since position does not apply to table-column-group or table-column boxes, they are not affected by relative positioning.
3.4. Sticky positioning
Sticky positioning is similar to relative positioning except the offsets are automatically calculated in reference to the nearest scrollport.
For a sticky positioned box, the inset properties represent insets from the respective edges of the nearest scrollport, defining the sticky view rectangle used to constrain the box’s position. (For this purpose an auto value represents a zero inset.) If this results in a sticky view rectangle size in any axis less than the size of the border box of the sticky box in that axis, then the effective end-edge inset in the affected axis is reduced (possibly becoming negative) to bring the sticky view rectangle’s size up to the size of the border box in that axis (where end is interpreted relative to the writing mode of the containing block).
But if the nearest scrollport were only 100px tall, then the effective bottom-edge inset becomes -120px, resulting in a sticky view rectangle that’s 200px tall, enough to fully contain the margin box of the sticky box.
For each side of the box, if the corresponding inset property is not auto, and the corresponding border edge of the box would be outside the corresponding edge of the sticky view rectangle, then the box must be visually shifted (as for relative positioning) to be inward of that sticky view rectangle edge, insofar as it can while its position box remains contained within its containing block. The position box is its margin box, except that for any side for which the distance between its margin edge and the corresponding edge of its containing block is less than its corresponding margin, that distance is used in place of that margin.
Note: A sticky positioned element with a non-auto top value and an auto bottom value will only ever be pushed down by sticky positioning; it will never be offset upwards.
Note: Multiple sticky positioned boxes in the same container are offset independently, and therefore might overlap.
3.4.1. Scroll Position of Sticky-Positioned Boxes
For the purposes of any operation targeting the scroll position of a sticky positioned element (or one of its descendants), the sticky positioned element must be considered to be at its offsetted position.
3.5. Absolute (and Fixed) Positioning
For an absolutely positioned box, the inset properties effectively reduce the containing block into which it is sized and positioned by the specified amounts. The resulting rectangle is called the inset-modified containing block. (For disambiguation, the actual containing block of an absolutely positioned box can also be called the absolute-position containing block.)
3.5.1. Resolvings Insets for the “Inset-Modified Containing Block”
If only one inset property in a given axis is auto, it is set to zero. If both inset properties in a given axis are auto, then, depending on the box’s self-alignment property in the relevant axis:
- for self-start alignment or its equivalent
- Set its start-edge inset property to the static position, and its end-edge inset property to zero.
- for self-end alignment or its equivalent
- Set its end-edge inset property to the static position, and its start-edge inset property to zero.
- for center alignment
- Let start distance be the distance from the center of its static-position rectangle to the start edge of its containing block, and end distance be the distance from the center of its static-position rectangle to the end edge of its containing block. If start distance is less than or equal to end distance, then set the start-edge inset property to zero, and set the end-edge inset property to (containing block size - 2 × |start distance|); otherwise, set the end-edge inset property to zero and the start-edge inset property to (containing block size - 2 × |end distance|).
For the rules above, ignore overflow alignment, and treat normal as start and any baseline or stretch alignment value as its fallback alignment.
If these adjustments result in an effective containing block size in any axis less than zero, then the weaker inset in the affected axis is reduced (possibly becoming negative) to bring that size up to zero. In the case that only one inset is auto, that is the weaker inset (whose opposite inset is the stronger inset); otherwise the weaker inset is the inset of the end edge (where end is interpreted relative to the writing mode of the containing block).
Note: Sizing and positioning of the absolutely positioned box into this inset-modified containing block is as described in § 4 Absolute Positioning Layout Model.
If its self-alignment property in an axis is normal, then the resolved value of its weaker inset in that axis is the value necessary to match that edge of its inset-modified containing block to the corresponding edge of its margin box after layout. (Otherwise the resolved value is the used value described above.)
3.5.2. Calculating the Static Position and the “Static-Position Rectangle”
When both inset properties in a given axis are auto, they are resolved into a static position by aligning the box into its static-position rectangle, an alignment container derived from the formatting context the box would have participated in if it were position: static (independent of its actual containing block). The