CSS Stacking Context Module Level 1

Unofficial Proposal Draft,

More details about this document
This version:
https://drafts.csswg.org/css-stacking-context/
Issue Tracking:
CSSWG Issues Repository
Inline In Spec
Editor:
Tab Atkins-Bittner (Google)
Suggest an Edit for this Spec:
GitHub Editor

Abstract

This module defines the painting model for CSS.

CSS is a language for describing the rendering of structured documents (such as HTML and XML) on screen, on paper, etc.

Status of this document

This section describes the status of this document at the time of its publication. A list of current W3C publications and the latest revision of this technical report can be found in the W3C technical reports index at https://www.w3.org/TR/.

Please send feedback by filing issues in GitHub (preferred), including the spec code “css-stacking-context” in the title, like this: “[css-stacking-context] …summary of comment…”. All issues and comments are archived. Alternately, feedback can be sent to the (archived) public mailing list www-style@w3.org.

This document is governed by the 2 November 2021 W3C Process Document.

This document was produced by a group operating under the W3C Patent Policy. W3C maintains a public list of any patent disclosures made in connection with the deliverables of the group; that page also includes instructions for disclosing a patent. An individual who has actual knowledge of a patent which the individual believes contains Essential Claim(s) must disclose the information in accordance with section 6 of the W3C Patent Policy.

1. Introduction

This section is not normative.

Elements on a page can have many overlapping parts. This specification defines the precise order that every part of an element and the surrounding page is painted, so that things render above (or below) other things in a well-defined way.

2. Painting Order

The rendering structure of a document consists of a root canvas, a document layer and any number of additional rendering layers, and within each layer, a list of one or more trees of boxes generated by elements.

A canvas is a theoretically-infinite 2D field of color. The root canvas is the canvas upon which all of the document’s content is rendered. Layers, and elements that generate stacking contexts, first render onto temporary canvases before being composited onto an ancestor canvas (ending with the root canvas for the document).

A rendering layer is an ordered list of boxes, where each layer is rendered fully atop all previous layers, and fully below all following layers. Within the layer, boxes and their descendants can potentially interweave their rendering with each other. The document layer is the layer containing the principal box of the document’s root element; it is below all other rendering layers.

In the following algorithms, a given box or fragment is only painted once, by whatever step attempts to paint it first. (This allows the algorithm to be written much simply, without elaborate guards to check against double-painting.)

This is meant to be a reproduction and elaboration of the CSS2 "Elaborate Description of Stacking Contexts" algorithm, modified to account for where filter/clipping/compositing can happen, the existence of top layers, and the newer element/box/fragment hierarchy. Non-editorial changes beyond the above are unintentional and probably bugs.

To paint a document:
  1. If the document is being painted as part of another document (such as an iframe's document), then the root canvas is initially transparent black everywhere.

    Otherwise, the root canvas is a UA-defined color everywhere. This can be affected by things such as, but not limited to, the color-scheme property.

    Other specifications can define that the root canvas begins as another color in certain circumstances.

  2. Paint the document layer onto the root canvas.

  3. For each additional rendering layer, in order from bottom to top, paint the layer onto the root canvas.

To paint a layer layer onto a root canvas:
  1. Let canvas be a fresh canvas. initially transparent black everywhere.

  2. If layer is the document layer, and the root element generates a box, then the root element propagates its background to canvas: the root element’s background is painted onto canvas, using all of canvas as the background painting area, but continuing to use the root element to determine the background positioning area.

    [CSS-CONTAIN-3] should, apparently, block propagation, but I can’t find that in the spec. Figure out if I missed something, and make it block propagation here.

  3. For each top-level box in layer, paint a stacking context of the box onto canvas.

  4. If the implementation chose not to paint outlines while executing the previous step, paint the outlines of all boxes/fragments in layer to canvas.

  5. Clipping/filtering/etc goes here.

  6. Composite canvas onto root canvas.

    Does only the document layer have non-trivial whole-layer compositing?

To paint a stacking context with a box box onto a canvas root canvas:
  1. Let canvas be a fresh canvas, initially transparent black everywhere.

  2. If box is a block-level box other than a table wrapper box

    If box did not propagate its background, paint box’s background color onto canvas, then background image.

    In all cases, then paint box’s border onto canvas.

    If box if a block-level table wrapper box:

    Paint the following onto canvas, in order:

    1. If box did not propagate its background, paint box’s backgrounds (color, then image) onto canvas.

    2. Paint box’s column group’s backgrounds (color, then image) onto canvas.

    3. Paint box’s column’s backgrounds (color, then image) onto canvas.

    4. Paint box’s row group’s backgrounds (color, then image) onto canvas.

    5. Paint box’s row’s backgrounds (color, then image) onto canvas.

    6. Paint box’s cell’s backgrounds (color, then image) onto canvas.

    7. Paint all of box’s table borders (in tree order, for separated borders) onto canvas.

      I think this needs more detail, and I think [CSS-TABLES-3] provides it.

  3. For each stacking context descendant of box with strictly negative z-indexes, in z-index order (most negative first), then tree order, paint a stacking context for the descendant onto canvas.

  4. For each in-flow, non-positioned, block-level descendant of box, in tree order:

    If the descendant is not a table wrapper box

    Paint its background color, then background image, then border onto canvas.

    If the descendant is a table wrapper box
    1. Paint its backgrounds (color, then image) onto canvas.

    2. Paint its column group’s backgrounds (color, then image) onto canvas.

    3. Paint its column’s backgrounds (color, then image) onto canvas.

    4. Paint its row group’s backgrounds (color, then image) onto canvas.

    5. Paint its row’s backgrounds (color, then image) onto canvas.

    6. Paint its cell’s backgrounds (color, then image) onto canvas.

    7. Paint all of box’s table borders (in tree order, for separated borders) onto canvas.

  5. For each non-positioned, floating descendant d of box, in tree order, paint a stacking context from d onto canvas, skipping any positioned descendants of d and any descendants of d that actually create new stacking contexts. (They are, instead, painted as part of box in other steps.)

  6. If box is inline-level and generates a stacking context, then for each line box that box is in, paint an inline run from box’s fragments in that line box onto canvas.

  7. Otherwise (if it did not match Step 6’s condition), then first for box, then for all its in-flow, non-positioned, block-level descendants d, in tree order:

    1. If d is a block-level replaced element, paint the replaced content onto canvas, atomically.

    2. Otherwise, for each line box of d, for each box child of d that generates fragments in that line box, paint an inline run from those fragments onto canvas.

    3. Optionally, if d is block-level, paint the outline of d onto canvas.

  8. For each positioned descendant d of box with zero or auto z-index, in tree order, paint a stacking context for d onto canvas. If d is z-index: auto, skip any positioned descendants of d and any descendants of d that actually create new stacking contexts. (They are, instead, painted as part of box.)

  9. For each stacking context descendant of box with strictly positive z-indexes, in z-index order (least positive first), then tree order, paint a stacking context for the descendant onto canvas.

  10. Filter/clip/etc here

  11. Composite canvas onto root canvas.

To paint an inline run of a list of fragments frags that are all in the same line box, onto a canvas canvas:
  1. For each fragment frag of frags:

    1. Paint the background color, then background image, then border of frag onto canvas.

    2. If frag was generated by an inline box

      For all descendant fragments of frag that were generated by an in-flow, non-positioned, inline-level box, or that were generated by a text run:

      If the fragment was generated by a text run
      1. Paint any underlining affecting the text of the fragment, in tree order of the elements applying the underlining (such that the deepest element’s underline, if any, if painted topmost and the root element’s underlining, if any, is painted bottommost), onto canvas.

      2. Paint any overlining affecting the text of the fragment, in the same order as underlines, onto canvas.

      3. Paint the text onto canvas.

      4. Paint any line-through affecting the text of the fragment, in the same order as underlines, onto canvas.

      Otherwise

      Paint an inline run from frag onto canvas.

      If frag was generated by an inline-level block or table wrapper box

      Paint a stacking context from frag’s generating box onto canvas, skipping any positioned descendants of the box and any descendants of the box that actually create new stacking contexts. (They are, instead, painted as part of their nearest ancestor stacking context.)

      If frag was generated by an inline-level replaced box

      Paint the replaced content, atomically, onto canvas.

  2. Optionally, paint the outline of frag onto canvas.

Note: Some of the fragments in frags might have been generated by line splitting or the Unicode bidirectional algorithm.

Figure out if filtering/clipping/compositing can take place at this step, and if so, exactly how to phrase it since this step potentially paints from multiple elements.

While the backgrounds of bidirectional inlines are painted in tree order, they are positioned in visual order. Is the positioning of inline backgrounds still undefined?

Conformance

Document conventions

Conformance requirements are expressed with a combination of descriptive assertions and RFC 2119 terminology. The key words “MUST”, “MUST NOT”, “REQUIRED”, “SHALL”, “SHALL NOT”, “SHOULD”, “SHOULD NOT”, “RECOMMENDED”, “MAY”, and “OPTIONAL” in the normative parts of this document are to be interpreted as described in RFC 2119. However, for readability, these words do not appear in all uppercase letters in this specification.

All of the text of this specification is normative except sections explicitly marked as non-normative, examples, and notes. [RFC2119]

Examples in this specification are introduced with the words “for example” or are set apart from the normative text with class="example", like this:

This is an example of an informative example.

Informative notes begin with the word “Note” and are set apart from the normative text with class="note", like this:

Note, this is an informative note.

Advisements are normative sections styled to evoke special attention and are set apart from other normative text with <strong class="advisement">, like this: UAs MUST provide an accessible alternative.

Conformance classes

Conformance to this specification is defined for three conformance classes:

style sheet
A CSS style sheet.
renderer
A UA that interprets the semantics of a style sheet and renders documents that use them.
authoring tool
A UA that writes a style sheet.

A style sheet is conformant to this specification if all of its statements that use syntax defined in this module are valid according to the generic CSS grammar and the individual grammars of each feature defined in this module.

A renderer is conformant to this specification if, in addition to interpreting the style sheet as defined by the appropriate specifications, it supports all the features defined by this specification by parsing them correctly and rendering the document accordingly. However, the inability of a UA to correctly render a document due to limitations of the device does not make the UA non-conformant. (For example, a UA is not required to render color on a monochrome monitor.)

An authoring tool is conformant to this specification if it writes style sheets that are syntactically correct according to the generic CSS grammar and the individual grammars of each feature in this module, and meet all other conformance requirements of style sheets as described in this module.

Partial implementations

So that authors can exploit the forward-compatible parsing rules to assign fallback values, CSS renderers must treat as invalid (and ignore as appropriate) any at-rules, properties, property values, keywords, and other syntactic constructs for which they have no usable level of support. In particular, user agents must not selectively ignore unsupported component values and honor supported values in a single multi-value property declaration: if any value is considered invalid (as unsupported values must be), CSS requires that the entire declaration be ignored.

Implementations of Unstable and Proprietary Features

To avoid clashes with future stable CSS features, the CSSWG recommends following best practices for the implementation of unstable features and proprietary extensions to CSS.

Non-experimental implementations

Once a specification reaches the Candidate Recommendation stage, non-experimental implementations are possible, and implementors should release an unprefixed implementation of any CR-level feature they can demonstrate to be correctly implemented according to spec.

To establish and maintain the interoperability of CSS across implementations, the CSS Working Group requests that non-experimental CSS renderers submit an implementation report (and, if necessary, the testcases used for that implementation report) to the W3C before releasing an unprefixed implementation of any CSS features. Testcases submitted to W3C are subject to review and correction by the CSS Working Group.

Further information on submitting testcases and implementation reports can be found from on the CSS Working Group’s website at http://www.w3.org/Style/CSS/Test/. Questions should be directed to the public-css-testsuite@w3.org mailing list.

Index

Terms defined by this specification

Terms defined by reference

References

Normative References

[CSS-BACKGROUNDS-3]
Bert Bos; Elika Etemad; Brad Kemper. CSS Backgrounds and Borders Module Level 3. 26 July 2021. CR. URL: https://www.w3.org/TR/css-backgrounds-3/
[CSS-BREAK-4]
Rossen Atanassov; Elika Etemad. CSS Fragmentation Module Level 4. 18 December 2018. WD. URL: https://www.w3.org/TR/css-break-4/
[CSS-COLOR-4]
Tab Atkins Jr.; Chris Lilley; Lea Verou. CSS Color Module Level 4. 15 December 2021. WD. URL: https://www.w3.org/TR/css-color-4/
[CSS-COLOR-ADJUST-1]
Elika Etemad; et al. CSS Color Adjustment Module Level 1. 10 February 2022. CR. URL: https://www.w3.org/TR/css-color-adjust-1/
[CSS-DISPLAY-3]
Tab Atkins Jr.; Elika Etemad. CSS Display Module Level 3. 3 September 2021. CR. URL: https://www.w3.org/TR/css-display-3/
[CSS-INLINE-3]
Dave Cramer; Elika Etemad; Steve Zilles. CSS Inline Layout Module Level 3. 27 August 2020. WD. URL: https://www.w3.org/TR/css-inline-3/
[CSS-PAGE-FLOATS-3]
Johannes Wilm. CSS Page Floats. 15 September 2015. WD. URL: https://www.w3.org/TR/css-page-floats-3/
[CSS-POSITION-3]
Elika Etemad; Tab Atkins Jr.. CSS Positioned Layout Module Level 3. 16 December 2021. WD. URL: https://www.w3.org/TR/css-position-3/
[CSS-TABLES-3]
François Remy; Greg Whitworth; David Baron. CSS Table Module Level 3. 27 July 2019. WD. URL: https://www.w3.org/TR/css-tables-3/
[CSS21]
Bert Bos; et al. Cascading Style Sheets Level 2 Revision 1 (CSS 2.1) Specification. 7 June 2011. REC. URL: https://www.w3.org/TR/CSS21/
[DOM]
Anne van Kesteren. DOM Standard. Living Standard. URL: https://dom.spec.whatwg.org/
[HTML]
Anne van Kesteren; et al. HTML Standard. Living Standard. URL: https://html.spec.whatwg.org/multipage/
[INFRA]
Anne van Kesteren; Domenic Denicola. Infra Standard. Living Standard. URL: https://infra.spec.whatwg.org/
[RFC2119]
S. Bradner. Key words for use in RFCs to Indicate Requirement Levels. March 1997. Best Current Practice. URL: https://datatracker.ietf.org/doc/html/rfc2119
[SVG2]
Amelia Bellamy-Royds; et al. Scalable Vector Graphics (SVG) 2. 4 October 2018. CR. URL: https://www.w3.org/TR/SVG2/

Informative References

[CSS-CONTAIN-3]
Tab Atkins Jr.; Florian Rivoal; Miriam Suzanne. CSS Containment Module Level 3. 21 December 2021. WD. URL: https://www.w3.org/TR/css-contain-3/

Issues Index

This is meant to be a reproduction and elaboration of the CSS2 "Elaborate Description of Stacking Contexts" algorithm, modified to account for where filter/clipping/compositing can happen, the existence of top layers, and the newer element/box/fragment hierarchy. Non-editorial changes beyond the above are unintentional and probably bugs.
[CSS-CONTAIN-3] should, apparently, block propagation, but I can’t find that in the spec. Figure out if I missed something, and make it block propagation here.
Clipping/filtering/etc goes here.
Does only the document layer have non-trivial whole-layer compositing?
I think this needs more detail, and I think [CSS-TABLES-3] provides it.
Figure out if filtering/clipping/compositing can take place at this step, and if so, exactly how to phrase it since this step potentially paints from multiple elements.
While the backgrounds of bidirectional inlines are painted in tree order, they are positioned in visual order. Is the positioning of inline backgrounds still undefined?