diff --git a/Tests/LibWeb/Ref/reference/box-with-transform-should-be-above-other-boxes-ref.html b/Tests/LibWeb/Ref/reference/box-with-transform-should-be-above-other-boxes-ref.html
new file mode 100644
index 00000000000..c5379e0454b
--- /dev/null
+++ b/Tests/LibWeb/Ref/reference/box-with-transform-should-be-above-other-boxes-ref.html
@@ -0,0 +1,10 @@
+
+
diff --git a/Userland/Libraries/LibWeb/Painting/StackingContext.cpp b/Userland/Libraries/LibWeb/Painting/StackingContext.cpp
index bd199ac98d0..b8f43c67e65 100644
--- a/Userland/Libraries/LibWeb/Painting/StackingContext.cpp
+++ b/Userland/Libraries/LibWeb/Painting/StackingContext.cpp
@@ -133,20 +133,11 @@ void StackingContext::paint_descendants(PaintContext& context, Paintable const&
return IterationDecision::Continue;
}
- if (stacking_context && z_index.value_or(0) != 0)
+ if (stacking_context)
return IterationDecision::Continue;
if (child.is_positioned() && z_index.value_or(0) == 0)
return IterationDecision::Continue;
- if (stacking_context) {
- // FIXME: This may not be fully correct with respect to the paint phases.
- if (phase == StackingContextPaintPhase::Foreground) {
- paint_child(context, *stacking_context);
- }
- // Note: Don't further recurse into descendants as paint_child() will do that.
- return IterationDecision::Continue;
- }
-
bool child_is_inline_or_replaced = child.is_inline() || is(child.layout_node());
switch (phase) {
case StackingContextPaintPhase::BackgroundAndBorders:
@@ -223,7 +214,9 @@ void StackingContext::paint_internal(PaintContext& context) const
// Stacking contexts formed by positioned descendants with negative z-indices (excluding 0) in z-index order
// (most negative first) then tree order. (step 3)
- // NOTE: This doesn't check if a descendant is positioned as modern CSS allows for alternative methods to establish stacking contexts.
+ // Here, we treat non-positioned stacking contexts as if they were positioned, because CSS 2.0 spec does not
+ // account for new properties like `transform` and `opacity` that can create stacking contexts.
+ // https://github.com/w3c/csswg-drafts/issues/2717
for (auto* child : m_children) {
if (child->paintable().computed_values().z_index().has_value() && child->paintable().computed_values().z_index().value() < 0)
paint_child(context, *child);
@@ -239,11 +232,10 @@ void StackingContext::paint_internal(PaintContext& context) const
paint_descendants(context, paintable(), StackingContextPaintPhase::Foreground);
// Draw positioned descendants with z-index `0` or `auto` in tree order. (step 8)
- // FIXME: There's more to this step that we have yet to understand and implement.
- for (auto const& paintable : m_positioned_descendants_with_stack_level_0_and_stacking_contexts) {
- if (!paintable->is_positioned())
- continue;
-
+ // Here, we treat non-positioned stacking contexts as if they were positioned, because CSS 2.0 spec does not
+ // account for new properties like `transform` and `opacity` that can create stacking contexts.
+ // https://github.com/w3c/csswg-drafts/issues/2717
+ for (auto const& paintable : m_positioned_descendants_and_stacking_contexts_with_stack_level_0) {
// At this point, `paintable_box` is a positioned descendant with z-index: auto.
// FIXME: This is basically duplicating logic found elsewhere in this same function. Find a way to make this more elegant.
auto* parent_paintable = paintable->parent();
@@ -260,7 +252,9 @@ void StackingContext::paint_internal(PaintContext& context) const
// Stacking contexts formed by positioned descendants with z-indices greater than or equal to 1 in z-index order
// (smallest first) then tree order. (Step 9)
- // NOTE: This doesn't check if a descendant is positioned as modern CSS allows for alternative methods to establish stacking contexts.
+ // Here, we treat non-positioned stacking contexts as if they were positioned, because CSS 2.0 spec does not
+ // account for new properties like `transform` and `opacity` that can create stacking contexts.
+ // https://github.com/w3c/csswg-drafts/issues/2717
for (auto* child : m_children) {
if (child->paintable().computed_values().z_index().has_value() && child->paintable().computed_values().z_index().value() >= 1)
paint_child(context, *child);
@@ -393,7 +387,7 @@ TraversalDecision StackingContext::hit_test(CSSPixelPoint position, HitTestType
}
// 6. the child stacking contexts with stack level 0 and the positioned descendants with stack level 0.
- for (auto const& paintable : m_positioned_descendants_with_stack_level_0_and_stacking_contexts.in_reverse()) {
+ for (auto const& paintable : m_positioned_descendants_and_stacking_contexts_with_stack_level_0.in_reverse()) {
if (paintable->stacking_context()) {
if (paintable->stacking_context()->hit_test(transformed_position, type, callback) == TraversalDecision::Break)
return TraversalDecision::Break;
diff --git a/Userland/Libraries/LibWeb/Painting/StackingContext.h b/Userland/Libraries/LibWeb/Painting/StackingContext.h
index 8fb9ecb6e88..1801f16f164 100644
--- a/Userland/Libraries/LibWeb/Painting/StackingContext.h
+++ b/Userland/Libraries/LibWeb/Painting/StackingContext.h
@@ -56,7 +56,7 @@ private:
size_t m_index_in_tree_order { 0 };
Optional m_last_paint_generation_id;
- Vector> m_positioned_descendants_with_stack_level_0_and_stacking_contexts;
+ Vector> m_positioned_descendants_and_stacking_contexts_with_stack_level_0;
Vector> m_non_positioned_floating_descendants;
static void paint_child(PaintContext&, StackingContext const&);
diff --git a/Userland/Libraries/LibWeb/Painting/ViewportPaintable.cpp b/Userland/Libraries/LibWeb/Painting/ViewportPaintable.cpp
index b0ff83d16a7..2d0f6cfb4be 100644
--- a/Userland/Libraries/LibWeb/Painting/ViewportPaintable.cpp
+++ b/Userland/Libraries/LibWeb/Painting/ViewportPaintable.cpp
@@ -43,7 +43,7 @@ void ViewportPaintable::build_stacking_context_tree()
auto* parent_context = const_cast(paintable).enclosing_stacking_context();
auto establishes_stacking_context = paintable.layout_node().establishes_stacking_context();
if ((paintable.is_positioned() || establishes_stacking_context) && paintable.computed_values().z_index().value_or(0) == 0)
- parent_context->m_positioned_descendants_with_stack_level_0_and_stacking_contexts.append(paintable);
+ parent_context->m_positioned_descendants_and_stacking_contexts_with_stack_level_0.append(paintable);
if (!paintable.is_positioned() && paintable.is_floating())
parent_context->m_non_positioned_floating_descendants.append(paintable);
if (!establishes_stacking_context) {