diff --git a/Tests/LibWeb/Ref/grid-items-painting-order-ref.html b/Tests/LibWeb/Ref/grid-items-painting-order-ref.html
new file mode 100644
index 0000000000..c80af531c3
--- /dev/null
+++ b/Tests/LibWeb/Ref/grid-items-painting-order-ref.html
@@ -0,0 +1,8 @@
+
bar
diff --git a/Tests/LibWeb/Ref/grid-items-painting-order.html b/Tests/LibWeb/Ref/grid-items-painting-order.html
new file mode 100644
index 0000000000..a37803df2a
--- /dev/null
+++ b/Tests/LibWeb/Ref/grid-items-painting-order.html
@@ -0,0 +1,12 @@
+foo
bar
diff --git a/Tests/LibWeb/Ref/manifest.json b/Tests/LibWeb/Ref/manifest.json
index aad9eb7542..e76350ab57 100644
--- a/Tests/LibWeb/Ref/manifest.json
+++ b/Tests/LibWeb/Ref/manifest.json
@@ -1,5 +1,6 @@
{
"img-srcset-viewport-relative-sizes.html": "img-srcset-viewport-relative-sizes-ref.html",
+ "grid-items-painting-order.html": "grid-items-painting-order-ref.html",
"square-flex.html": "square-ref.html",
"separate-borders-inline-table.html": "separate-borders-ref.html",
"opacity-stacking.html": "opacity-stacking-ref.html",
diff --git a/Tests/LibWeb/Text/expected/hit_testing/grid.txt b/Tests/LibWeb/Text/expected/hit_testing/grid.txt
new file mode 100644
index 0000000000..cbe03600fd
--- /dev/null
+++ b/Tests/LibWeb/Text/expected/hit_testing/grid.txt
@@ -0,0 +1 @@
+ true
diff --git a/Tests/LibWeb/Text/input/hit_testing/grid.html b/Tests/LibWeb/Text/input/hit_testing/grid.html
new file mode 100644
index 0000000000..9028cf3800
--- /dev/null
+++ b/Tests/LibWeb/Text/input/hit_testing/grid.html
@@ -0,0 +1,23 @@
+
+
+
+
diff --git a/Userland/Libraries/LibWeb/Painting/StackingContext.cpp b/Userland/Libraries/LibWeb/Painting/StackingContext.cpp
index 24374add45..8035d8461d 100644
--- a/Userland/Libraries/LibWeb/Painting/StackingContext.cpp
+++ b/Userland/Libraries/LibWeb/Painting/StackingContext.cpp
@@ -72,6 +72,20 @@ static PaintPhase to_paint_phase(StackingContext::StackingContextPaintPhase phas
}
}
+void StackingContext::paint_node_as_stacking_context(Paintable const& paintable, PaintContext& context) const
+{
+ paint_node(paintable, context, PaintPhase::Background);
+ paint_node(paintable, context, PaintPhase::Border);
+ paint_descendants(context, paintable, StackingContextPaintPhase::BackgroundAndBorders);
+ paint_descendants(context, paintable, StackingContextPaintPhase::Floats);
+ paint_descendants(context, paintable, StackingContextPaintPhase::BackgroundAndBordersForInlineLevelAndReplaced);
+ paint_node(paintable, context, PaintPhase::Foreground);
+ paint_descendants(context, paintable, StackingContextPaintPhase::Foreground);
+ paint_node(paintable, context, PaintPhase::Outline);
+ paint_node(paintable, context, PaintPhase::Overlay);
+ paint_descendants(context, paintable, StackingContextPaintPhase::FocusAndOverlay);
+}
+
void StackingContext::paint_descendants(PaintContext& context, Paintable const& paintable, StackingContextPaintPhase phase) const
{
paintable.before_children_paint(context, to_paint_phase(phase));
@@ -99,6 +113,19 @@ void StackingContext::paint_descendants(PaintContext& context, Paintable const&
return;
}
+ // NOTE: Grid specification https://www.w3.org/TR/css-grid-2/#z-order says that grid items should be treated
+ // the same way as CSS2 defines for inline-blocks:
+ // "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."
+ auto should_be_treated_as_stacking_context = child.layout_node().is_grid_item();
+ if (should_be_treated_as_stacking_context) {
+ // FIXME: This may not be fully correct with respect to the paint phases.
+ if (phase == StackingContextPaintPhase::Foreground)
+ paint_node_as_stacking_context(child, context);
+ return;
+ }
+
bool child_is_inline_or_replaced = child.is_inline() || is(child);
switch (phase) {
case StackingContextPaintPhase::BackgroundAndBorders:
@@ -214,16 +241,7 @@ void StackingContext::paint_internal(PaintContext& context) const
paint_child(context, *child);
return TraversalDecision::SkipChildrenAndContinue;
} else {
- paint_node(paintable, context, PaintPhase::Background);
- paint_node(paintable, context, PaintPhase::Border);
- paint_descendants(context, paintable, StackingContextPaintPhase::BackgroundAndBorders);
- paint_descendants(context, paintable, StackingContextPaintPhase::Floats);
- paint_descendants(context, paintable, StackingContextPaintPhase::BackgroundAndBordersForInlineLevelAndReplaced);
- paint_node(paintable, context, PaintPhase::Foreground);
- paint_descendants(context, paintable, StackingContextPaintPhase::Foreground);
- paint_node(paintable, context, PaintPhase::Outline);
- paint_node(paintable, context, PaintPhase::Overlay);
- paint_descendants(context, paintable, StackingContextPaintPhase::FocusAndOverlay);
+ paint_node_as_stacking_context(paintable, context);
}
if (parent_paintable)
parent_paintable->after_children_paint(context, PaintPhase::Foreground);
diff --git a/Userland/Libraries/LibWeb/Painting/StackingContext.h b/Userland/Libraries/LibWeb/Painting/StackingContext.h
index a79a888415..62739124b2 100644
--- a/Userland/Libraries/LibWeb/Painting/StackingContext.h
+++ b/Userland/Libraries/LibWeb/Painting/StackingContext.h
@@ -29,6 +29,7 @@ public:
FocusAndOverlay,
};
+ void paint_node_as_stacking_context(Paintable const&, PaintContext&) const;
void paint_descendants(PaintContext&, Paintable const&, StackingContextPaintPhase) const;
void paint(PaintContext&) const;
Optional hit_test(CSSPixelPoint, HitTestType) const;