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.
-
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.
-
Paint the document layer onto the root canvas.
-
For each additional rendering layer, in order from bottom to top, paint the layer onto the root canvas.
-
Let canvas be a fresh canvas. initially transparent black everywhere.
-
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.
-
For each top-level box in layer, paint a stacking context of the box onto canvas.
-
If the implementation chose not to paint outlines while executing the previous step, paint the outlines of all boxes/fragments in layer to canvas.
-
Composite canvas onto root canvas.
Does only the document layer have non-trivial whole-layer compositing?
-
Let canvas be a fresh canvas, initially transparent black everywhere.
-
- 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:
-
If box did not propagate its background, paint box’s backgrounds (color, then image) onto canvas.
-
Paint box’s column group’s backgrounds (color, then image) onto canvas.
-
Paint box’s column’s backgrounds (color, then image) onto canvas.
-
Paint box’s row group’s backgrounds (color, then image) onto canvas.
-
Paint box’s row’s backgrounds (color, then image) onto canvas.
-
Paint box’s cell’s backgrounds (color, then image) onto canvas.
-
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.
-
-
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.
-
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
-
-
Paint its backgrounds (color, then image) onto canvas.
-
Paint its column group’s backgrounds (color, then image) onto canvas.
-
Paint its column’s backgrounds (color, then image) onto canvas.
-
Paint its row group’s backgrounds (color, then image) onto canvas.
-
Paint its row’s backgrounds (color, then image) onto canvas.
-
Paint its cell’s backgrounds (color, then image) onto canvas.
-
Paint all of box’s table borders (in tree order, for separated borders) onto canvas.
-
-
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.)
-
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.
-
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:
-
If d is a block-level replaced element, paint the replaced content onto canvas, atomically.
-
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.
-
Optionally, if d is block-level, paint the outline of d onto canvas.
-
-
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.)
-
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.
-
Filter/clip/etc here
-
Composite canvas onto root canvas.
-
For each fragment frag of frags:
-
Paint the background color, then background image, then border of frag onto canvas.
-
- 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
-
-
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.
-
Paint any overlining affecting the text of the fragment, in the same order as underlines, onto canvas.
-
Paint the text onto canvas.
-
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.
-
-
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?