aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorOriol Brufau <obrufau@igalia.com>2025-03-13 07:49:08 +0100
committerGitHub <noreply@github.com>2025-03-13 06:49:08 +0000
commitf93006af95dd75a07de2571e6a2edabcc64a46ac (patch)
tree2e356bbe166bf7f918c295c01aebde9ad3e5759e
parent205b97d5edbca6f24b189b564ec5f7129ba40228 (diff)
downloadservo-f93006af95dd75a07de2571e6a2edabcc64a46ac.tar.gz
servo-f93006af95dd75a07de2571e6a2edabcc64a46ac.zip
Improve logic for establishing a stacking context (#35947)
In particular: - `z-index` will now work on unpositioned grid items. - `will-change: z-index` will only establish a stacking context if `z-index` applies, i.e. if the box is positioned or a flex/grid item. - The conditions in `establishes_stacking_context()` are reordered, so that the most likely ones are checked first. Signed-off-by: Oriol Brufau <obrufau@igalia.com>
-rw-r--r--components/layout_2020/flexbox/layout.rs4
-rw-r--r--components/layout_2020/fragment_tree/base_fragment.rs4
-rw-r--r--components/layout_2020/style_ext.rs136
-rw-r--r--components/layout_2020/taffy/layout.rs10
-rw-r--r--tests/wpt/meta/MANIFEST.json39
-rw-r--r--tests/wpt/meta/css/css-grid/grid-items/grid-inline-z-axis-ordering-001.html.ini2
-rw-r--r--tests/wpt/meta/css/css-grid/grid-items/grid-inline-z-axis-ordering-002.html.ini2
-rw-r--r--tests/wpt/meta/css/css-grid/grid-items/grid-inline-z-axis-ordering-003.html.ini2
-rw-r--r--tests/wpt/meta/css/css-grid/grid-items/grid-inline-z-axis-ordering-004.html.ini2
-rw-r--r--tests/wpt/meta/css/css-grid/grid-items/grid-inline-z-axis-ordering-005.html.ini2
-rw-r--r--tests/wpt/meta/css/css-grid/grid-items/grid-inline-z-axis-ordering-overlapped-items-001.html.ini2
-rw-r--r--tests/wpt/meta/css/css-grid/grid-items/grid-inline-z-axis-ordering-overlapped-items-002.html.ini2
-rw-r--r--tests/wpt/meta/css/css-grid/grid-items/grid-inline-z-axis-ordering-overlapped-items-003.html.ini2
-rw-r--r--tests/wpt/meta/css/css-grid/grid-items/grid-inline-z-axis-ordering-overlapped-items-004.html.ini2
-rw-r--r--tests/wpt/meta/css/css-grid/grid-items/grid-inline-z-axis-ordering-overlapped-items-005.html.ini2
-rw-r--r--tests/wpt/meta/css/css-grid/grid-items/grid-inline-z-axis-ordering-overlapped-items-006.html.ini2
-rw-r--r--tests/wpt/meta/css/css-grid/grid-items/grid-layout-z-order-a.html.ini2
-rw-r--r--tests/wpt/meta/css/css-grid/grid-items/grid-layout-z-order-b.html.ini2
-rw-r--r--tests/wpt/meta/css/css-grid/grid-items/grid-z-axis-ordering-001.html.ini2
-rw-r--r--tests/wpt/meta/css/css-grid/grid-items/grid-z-axis-ordering-002.html.ini2
-rw-r--r--tests/wpt/meta/css/css-grid/grid-items/grid-z-axis-ordering-003.html.ini2
-rw-r--r--tests/wpt/meta/css/css-grid/grid-items/grid-z-axis-ordering-004.html.ini2
-rw-r--r--tests/wpt/meta/css/css-grid/grid-items/grid-z-axis-ordering-005.html.ini2
-rw-r--r--tests/wpt/meta/css/css-grid/grid-items/grid-z-axis-ordering-overlapped-items-001.html.ini2
-rw-r--r--tests/wpt/meta/css/css-grid/grid-items/grid-z-axis-ordering-overlapped-items-002.html.ini2
-rw-r--r--tests/wpt/meta/css/css-grid/grid-items/grid-z-axis-ordering-overlapped-items-003.html.ini2
-rw-r--r--tests/wpt/meta/css/css-grid/grid-items/grid-z-axis-ordering-overlapped-items-004.html.ini2
-rw-r--r--tests/wpt/meta/css/css-grid/grid-items/grid-z-axis-ordering-overlapped-items-005.html.ini2
-rw-r--r--tests/wpt/meta/css/css-grid/grid-items/grid-z-axis-ordering-overlapped-items-006.html.ini2
-rw-r--r--tests/wpt/meta/css/css-will-change/will-change-stacking-context-z-index-3.html.ini2
-rw-r--r--tests/wpt/tests/css/css-will-change/will-change-stacking-context-z-index-2.html29
-rw-r--r--tests/wpt/tests/css/css-will-change/will-change-stacking-context-z-index-3.html29
-rw-r--r--tests/wpt/tests/css/css-will-change/will-change-stacking-context-z-index-4.html28
33 files changed, 224 insertions, 105 deletions
diff --git a/components/layout_2020/flexbox/layout.rs b/components/layout_2020/flexbox/layout.rs
index 08cacc14934..7fcf41a269c 100644
--- a/components/layout_2020/flexbox/layout.rs
+++ b/components/layout_2020/flexbox/layout.rs
@@ -257,7 +257,9 @@ impl FlexLineItem<'_> {
}
let mut fragment_info = self.item.box_.base_fragment_info();
- fragment_info.flags.insert(FragmentFlags::IS_FLEX_ITEM);
+ fragment_info
+ .flags
+ .insert(FragmentFlags::IS_FLEX_OR_GRID_ITEM);
if self.item.depends_on_block_constraints {
fragment_info.flags.insert(
FragmentFlags::SIZE_DEPENDS_ON_BLOCK_CONSTRAINTS_AND_CAN_BE_CHILD_OF_FLEX_ITEM,
diff --git a/components/layout_2020/fragment_tree/base_fragment.rs b/components/layout_2020/fragment_tree/base_fragment.rs
index 39d06ca121a..38f4f6ba815 100644
--- a/components/layout_2020/fragment_tree/base_fragment.rs
+++ b/components/layout_2020/fragment_tree/base_fragment.rs
@@ -80,8 +80,8 @@ bitflags! {
const IS_BODY_ELEMENT_OF_HTML_ELEMENT_ROOT = 1 << 0;
/// Whether or not the node that created this Fragment is a `<br>` element.
const IS_BR_ELEMENT = 1 << 1;
- /// Whether or not this Fragment is a flex item.
- const IS_FLEX_ITEM = 1 << 2;
+ /// Whether or not this Fragment is a flex item or a grid item.
+ const IS_FLEX_OR_GRID_ITEM = 1 << 2;
/// Whether or not this Fragment was created to contain a replaced element or is
/// a replaced element.
const IS_REPLACED = 1 << 3;
diff --git a/components/layout_2020/style_ext.rs b/components/layout_2020/style_ext.rs
index e9aff0cf73f..a4fa6600fea 100644
--- a/components/layout_2020/style_ext.rs
+++ b/components/layout_2020/style_ext.rs
@@ -301,6 +301,7 @@ pub(crate) trait ComputedValuesExt {
) -> LogicalSides<LengthPercentageOrAuto<'_>>;
fn is_transformable(&self, fragment_flags: FragmentFlags) -> bool;
fn has_transform_or_perspective(&self, fragment_flags: FragmentFlags) -> bool;
+ fn z_index_applies(&self, fragment_flags: FragmentFlags) -> bool;
fn effective_z_index(&self, fragment_flags: FragmentFlags) -> i32;
fn effective_overflow(&self, fragment_flags: FragmentFlags) -> AxesOverflow;
fn establishes_block_formatting_context(&self, fragment_flags: FragmentFlags) -> bool;
@@ -503,18 +504,35 @@ impl ComputedValuesExt for ComputedValues {
self.get_box().perspective != Perspective::None)
}
+ /// Whether the `z-index` property applies to this fragment.
+ fn z_index_applies(&self, fragment_flags: FragmentFlags) -> bool {
+ // As per CSS 2 § 9.9.1, `z-index` applies to positioned elements.
+ // <http://www.w3.org/TR/CSS2/visuren.html#z-index>
+ if self.get_box().position != ComputedPosition::Static {
+ return true;
+ }
+ // More modern specs also apply it to flex and grid items.
+ // - From <https://www.w3.org/TR/css-flexbox-1/#painting>:
+ // > Flex items paint exactly the same as inline blocks [CSS2], except that order-modified
+ // > document order is used in place of raw document order, and z-index values other than auto
+ // > create a stacking context even if position is static (behaving exactly as if position
+ // > were relative).
+ // - From <https://drafts.csswg.org/css-flexbox/#painting>:
+ // > The painting order of grid items is exactly the same as inline blocks [CSS2], except that
+ // > order-modified document order is used in place of raw document order, and z-index values
+ // > other than auto create a stacking context even if position is static (behaving exactly
+ // > as if position were relative).
+ fragment_flags.contains(FragmentFlags::IS_FLEX_OR_GRID_ITEM)
+ }
+
/// Get the effective z-index of this fragment. Z-indices only apply to positioned elements
/// per CSS 2 9.9.1 (<http://www.w3.org/TR/CSS2/visuren.html#z-index>), so this value may differ
/// from the value specified in the style.
fn effective_z_index(&self, fragment_flags: FragmentFlags) -> i32 {
- // From <https://drafts.csswg.org/css-flexbox/#painting>:
- // > Flex items paint exactly the same as inline blocks [CSS2], except that order-modified
- // > document order is used in place of raw document order, and z-index values other than auto
- // > create a stacking context even if position is static (behaving exactly as if position
- // > were relative).
- match self.get_box().position {
- ComputedPosition::Static if !fragment_flags.contains(FragmentFlags::IS_FLEX_ITEM) => 0,
- _ => self.get_position().z_index.integer_or(0),
+ if self.z_index_applies(fragment_flags) {
+ self.get_position().z_index.integer_or(0)
+ } else {
+ 0
}
}
@@ -617,78 +635,92 @@ impl ComputedValuesExt for ComputedValues {
/// Returns true if this fragment establishes a new stacking context and false otherwise.
fn establishes_stacking_context(&self, fragment_flags: FragmentFlags) -> bool {
- let effects = self.get_effects();
- if effects.opacity != 1.0 {
- return true;
- }
-
- if effects.mix_blend_mode != ComputedMixBlendMode::Normal {
+ // From <https://www.w3.org/TR/css-will-change/#valdef-will-change-custom-ident>:
+ // > If any non-initial value of a property would create a stacking context on the element,
+ // > specifying that property in will-change must create a stacking context on the element.
+ let will_change_bits = self.clone_will_change().bits;
+ if will_change_bits
+ .intersects(WillChangeBits::STACKING_CONTEXT_UNCONDITIONAL | WillChangeBits::OPACITY)
+ {
return true;
}
- if !effects.filter.0.is_empty() {
+ // From <https://www.w3.org/TR/CSS2/visuren.html#z-index>, values different than `auto`
+ // make the box establish a stacking context.
+ if self.z_index_applies(fragment_flags) &&
+ (!self.get_position().z_index.is_auto() ||
+ will_change_bits.intersects(WillChangeBits::Z_INDEX))
+ {
return true;
}
- if self.has_transform_or_perspective(fragment_flags) {
+ // Fixed position and sticky position always create stacking contexts.
+ // Note `will-change: position` is handled above by `STACKING_CONTEXT_UNCONDITIONAL`.
+ if matches!(
+ self.get_box().position,
+ ComputedPosition::Fixed | ComputedPosition::Sticky
+ ) {
return true;
}
- // See <https://drafts.csswg.org/css-transforms-2/#transform-style-property>.
+ // From <https://www.w3.org/TR/css-transforms-1/#transform-rendering>
+ // > For elements whose layout is governed by the CSS box model, any value other than
+ // > `none` for the `transform` property results in the creation of a stacking context.
+ // From <https://www.w3.org/TR/css-transforms-2/#transform-style-property>
+ // > A computed value of `preserve-3d` for `transform-style` on a transformable element
+ // > establishes both a stacking context and a containing block for all descendants.
+ // From <https://www.w3.org/TR/css-transforms-2/#perspective-property>
+ // > any value other than none establishes a stacking context.
+ // TODO: handle individual transform properties (`translate`, `scale` and `rotate`).
+ // <https://www.w3.org/TR/css-transforms-2/#individual-transforms>
if self.is_transformable(fragment_flags) &&
- self.get_box().transform_style == ComputedTransformStyle::Preserve3d
+ (!self.get_box().transform.0.is_empty() ||
+ self.get_box().transform_style == ComputedTransformStyle::Preserve3d ||
+ self.get_box().perspective != Perspective::None ||
+ will_change_bits
+ .intersects(WillChangeBits::TRANSFORM | WillChangeBits::PERSPECTIVE))
{
return true;
}
- if self.get_box().isolation == ComputedIsolation::Isolate {
+ // From <https://www.w3.org/TR/css-color-3/#transparency>
+ // > implementations must create a new stacking context for any element with opacity less than 1.
+ // Note `will-change: opacity` is handled above by `WillChangeBits::OPACITY`.
+ let effects = self.get_effects();
+ if effects.opacity != 1.0 {
return true;
}
- // Fixed position and sticky position always create stacking contexts.
- // TODO(mrobinson): We need to handle sticky positioning here when we support it.
- if self.get_box().position == ComputedPosition::Fixed {
+ // From <https://www.w3.org/TR/filter-effects-1/#FilterProperty>
+ // > A computed value of other than `none` results in the creation of a stacking context
+ // Note `will-change: filter` is handled above by `STACKING_CONTEXT_UNCONDITIONAL`.
+ if !effects.filter.0.is_empty() {
return true;
}
- if self.get_svg().clip_path != ClipPath::None {
+ // From <https://www.w3.org/TR/compositing-1/#mix-blend-mode>
+ // > Applying a blendmode other than `normal` to the element must establish a new stacking context
+ // Note `will-change: mix-blend-mode` is handled above by `STACKING_CONTEXT_UNCONDITIONAL`.
+ if effects.mix_blend_mode != ComputedMixBlendMode::Normal {
return true;
}
- // From <https://www.w3.org/TR/css-will-change/#valdef-will-change-custom-ident>:
- // > If any non-initial value of a property would create a stacking context on the element,
- // > specifying that property in will-change must create a stacking context on the element.
- let will_change_bits = self.clone_will_change().bits;
- if will_change_bits.intersects(
- WillChangeBits::OPACITY |
- WillChangeBits::STACKING_CONTEXT_UNCONDITIONAL |
- WillChangeBits::Z_INDEX,
- ) || (will_change_bits
- .intersects(WillChangeBits::PERSPECTIVE | WillChangeBits::TRANSFORM) &&
- self.is_transformable(fragment_flags))
- {
+ // From <https://www.w3.org/TR/css-masking-1/#the-clip-path>
+ // > A computed value of other than `none` results in the creation of a stacking context.
+ // Note `will-change: clip-path` is handled above by `STACKING_CONTEXT_UNCONDITIONAL`.
+ if self.get_svg().clip_path != ClipPath::None {
return true;
}
- // Statically positioned fragments don't establish stacking contexts if the previous
- // conditions are not fulfilled. Furthermore, z-index doesn't apply to statically
- // positioned fragments (except for flex items, see below).
- //
- // From <https://drafts.csswg.org/css-flexbox/#painting>:
- // > Flex items paint exactly the same as inline blocks [CSS2], except that order-modified
- // > document order is used in place of raw document order, and z-index values other than auto
- // > create a stacking context even if position is static (behaving exactly as if position
- // > were relative).
- if self.get_box().position == ComputedPosition::Static &&
- !fragment_flags.contains(FragmentFlags::IS_FLEX_ITEM)
- {
- return false;
+ // From <https://www.w3.org/TR/compositing-1/#isolation>
+ // > For CSS, setting `isolation` to `isolate` will turn the element into a stacking context.
+ // Note `will-change: isolation` is handled above by `STACKING_CONTEXT_UNCONDITIONAL`.
+ if self.get_box().isolation == ComputedIsolation::Isolate {
+ return true;
}
- // For absolutely and relatively positioned fragments we only establish a stacking
- // context if there is a z-index set.
- // See https://www.w3.org/TR/CSS2/visuren.html#z-index
- !self.get_position().z_index.is_auto()
+ // TODO: We need to handle CSS Contain here.
+ false
}
/// Returns true if this style establishes a containing block for absolute
diff --git a/components/layout_2020/taffy/layout.rs b/components/layout_2020/taffy/layout.rs
index 2bee4c590f8..0d7e34af882 100644
--- a/components/layout_2020/taffy/layout.rs
+++ b/components/layout_2020/taffy/layout.rs
@@ -20,7 +20,9 @@ use crate::formatting_contexts::{
Baselines, IndependentFormattingContext, IndependentFormattingContextContents,
IndependentLayout,
};
-use crate::fragment_tree::{BoxFragment, CollapsedBlockMargins, Fragment, SpecificLayoutInfo};
+use crate::fragment_tree::{
+ BoxFragment, CollapsedBlockMargins, Fragment, FragmentFlags, SpecificLayoutInfo,
+};
use crate::geom::{
LogicalSides, LogicalVec2, PhysicalPoint, PhysicalRect, PhysicalSides, PhysicalSize, Size,
SizeConstraint, Sizes,
@@ -560,8 +562,12 @@ impl TaffyContainer {
match &mut child.taffy_level_box {
TaffyItemBoxInner::InFlowBox(independent_box) => {
+ let mut fragment_info = independent_box.base_fragment_info();
+ fragment_info
+ .flags
+ .insert(FragmentFlags::IS_FLEX_OR_GRID_ITEM);
let mut box_fragment = BoxFragment::new(
- independent_box.base_fragment_info(),
+ fragment_info,
independent_box.style().clone(),
std::mem::take(&mut child.child_fragments),
content_size,
diff --git a/tests/wpt/meta/MANIFEST.json b/tests/wpt/meta/MANIFEST.json
index 79668fb0ad6..e54ddc40d22 100644
--- a/tests/wpt/meta/MANIFEST.json
+++ b/tests/wpt/meta/MANIFEST.json
@@ -307667,6 +307667,45 @@
{}
]
],
+ "will-change-stacking-context-z-index-2.html": [
+ "9379185048a78b031e8ac290bd7bb3e5df24fa5f",
+ [
+ null,
+ [
+ [
+ "/css/reference/ref-filled-green-100px-square.xht",
+ "=="
+ ]
+ ],
+ {}
+ ]
+ ],
+ "will-change-stacking-context-z-index-3.html": [
+ "4ec40ae1a430a095ea6f703c8c27698e04792220",
+ [
+ null,
+ [
+ [
+ "/css/reference/ref-filled-green-100px-square.xht",
+ "=="
+ ]
+ ],
+ {}
+ ]
+ ],
+ "will-change-stacking-context-z-index-4.html": [
+ "d8a87b23415c3c10a6f4875f16cd63301e789152",
+ [
+ null,
+ [
+ [
+ "/css/reference/ref-filled-green-100px-square.xht",
+ "=="
+ ]
+ ],
+ {}
+ ]
+ ],
"will-change-transform-add-content.html": [
"1d8568ee629e48adfe99abab2e2194a73ae1301a",
[
diff --git a/tests/wpt/meta/css/css-grid/grid-items/grid-inline-z-axis-ordering-001.html.ini b/tests/wpt/meta/css/css-grid/grid-items/grid-inline-z-axis-ordering-001.html.ini
deleted file mode 100644
index 45cf6fc0460..00000000000
--- a/tests/wpt/meta/css/css-grid/grid-items/grid-inline-z-axis-ordering-001.html.ini
+++ /dev/null
@@ -1,2 +0,0 @@
-[grid-inline-z-axis-ordering-001.html]
- expected: FAIL
diff --git a/tests/wpt/meta/css/css-grid/grid-items/grid-inline-z-axis-ordering-002.html.ini b/tests/wpt/meta/css/css-grid/grid-items/grid-inline-z-axis-ordering-002.html.ini
deleted file mode 100644
index 4ff1ef0fe2d..00000000000
--- a/tests/wpt/meta/css/css-grid/grid-items/grid-inline-z-axis-ordering-002.html.ini
+++ /dev/null
@@ -1,2 +0,0 @@
-[grid-inline-z-axis-ordering-002.html]
- expected: FAIL
diff --git a/tests/wpt/meta/css/css-grid/grid-items/grid-inline-z-axis-ordering-003.html.ini b/tests/wpt/meta/css/css-grid/grid-items/grid-inline-z-axis-ordering-003.html.ini
deleted file mode 100644
index 837fbd2a8c1..00000000000
--- a/tests/wpt/meta/css/css-grid/grid-items/grid-inline-z-axis-ordering-003.html.ini
+++ /dev/null
@@ -1,2 +0,0 @@
-[grid-inline-z-axis-ordering-003.html]
- expected: FAIL
diff --git a/tests/wpt/meta/css/css-grid/grid-items/grid-inline-z-axis-ordering-004.html.ini b/tests/wpt/meta/css/css-grid/grid-items/grid-inline-z-axis-ordering-004.html.ini
deleted file mode 100644
index fd41d4c1a42..00000000000
--- a/tests/wpt/meta/css/css-grid/grid-items/grid-inline-z-axis-ordering-004.html.ini
+++ /dev/null
@@ -1,2 +0,0 @@
-[grid-inline-z-axis-ordering-004.html]
- expected: FAIL
diff --git a/tests/wpt/meta/css/css-grid/grid-items/grid-inline-z-axis-ordering-005.html.ini b/tests/wpt/meta/css/css-grid/grid-items/grid-inline-z-axis-ordering-005.html.ini
deleted file mode 100644
index 293ed0639f2..00000000000
--- a/tests/wpt/meta/css/css-grid/grid-items/grid-inline-z-axis-ordering-005.html.ini
+++ /dev/null
@@ -1,2 +0,0 @@
-[grid-inline-z-axis-ordering-005.html]
- expected: FAIL
diff --git a/tests/wpt/meta/css/css-grid/grid-items/grid-inline-z-axis-ordering-overlapped-items-001.html.ini b/tests/wpt/meta/css/css-grid/grid-items/grid-inline-z-axis-ordering-overlapped-items-001.html.ini
deleted file mode 100644
index eb2233d3700..00000000000
--- a/tests/wpt/meta/css/css-grid/grid-items/grid-inline-z-axis-ordering-overlapped-items-001.html.ini
+++ /dev/null
@@ -1,2 +0,0 @@
-[grid-inline-z-axis-ordering-overlapped-items-001.html]
- expected: FAIL
diff --git a/tests/wpt/meta/css/css-grid/grid-items/grid-inline-z-axis-ordering-overlapped-items-002.html.ini b/tests/wpt/meta/css/css-grid/grid-items/grid-inline-z-axis-ordering-overlapped-items-002.html.ini
deleted file mode 100644
index cb9905e7a27..00000000000
--- a/tests/wpt/meta/css/css-grid/grid-items/grid-inline-z-axis-ordering-overlapped-items-002.html.ini
+++ /dev/null
@@ -1,2 +0,0 @@
-[grid-inline-z-axis-ordering-overlapped-items-002.html]
- expected: FAIL
diff --git a/tests/wpt/meta/css/css-grid/grid-items/grid-inline-z-axis-ordering-overlapped-items-003.html.ini b/tests/wpt/meta/css/css-grid/grid-items/grid-inline-z-axis-ordering-overlapped-items-003.html.ini
deleted file mode 100644
index f3a786abf7b..00000000000
--- a/tests/wpt/meta/css/css-grid/grid-items/grid-inline-z-axis-ordering-overlapped-items-003.html.ini
+++ /dev/null
@@ -1,2 +0,0 @@
-[grid-inline-z-axis-ordering-overlapped-items-003.html]
- expected: FAIL
diff --git a/tests/wpt/meta/css/css-grid/grid-items/grid-inline-z-axis-ordering-overlapped-items-004.html.ini b/tests/wpt/meta/css/css-grid/grid-items/grid-inline-z-axis-ordering-overlapped-items-004.html.ini
deleted file mode 100644
index 03f883fbceb..00000000000
--- a/tests/wpt/meta/css/css-grid/grid-items/grid-inline-z-axis-ordering-overlapped-items-004.html.ini
+++ /dev/null
@@ -1,2 +0,0 @@
-[grid-inline-z-axis-ordering-overlapped-items-004.html]
- expected: FAIL
diff --git a/tests/wpt/meta/css/css-grid/grid-items/grid-inline-z-axis-ordering-overlapped-items-005.html.ini b/tests/wpt/meta/css/css-grid/grid-items/grid-inline-z-axis-ordering-overlapped-items-005.html.ini
deleted file mode 100644
index f89f4e9cfbe..00000000000
--- a/tests/wpt/meta/css/css-grid/grid-items/grid-inline-z-axis-ordering-overlapped-items-005.html.ini
+++ /dev/null
@@ -1,2 +0,0 @@
-[grid-inline-z-axis-ordering-overlapped-items-005.html]
- expected: FAIL
diff --git a/tests/wpt/meta/css/css-grid/grid-items/grid-inline-z-axis-ordering-overlapped-items-006.html.ini b/tests/wpt/meta/css/css-grid/grid-items/grid-inline-z-axis-ordering-overlapped-items-006.html.ini
deleted file mode 100644
index 479e338b1fd..00000000000
--- a/tests/wpt/meta/css/css-grid/grid-items/grid-inline-z-axis-ordering-overlapped-items-006.html.ini
+++ /dev/null
@@ -1,2 +0,0 @@
-[grid-inline-z-axis-ordering-overlapped-items-006.html]
- expected: FAIL
diff --git a/tests/wpt/meta/css/css-grid/grid-items/grid-layout-z-order-a.html.ini b/tests/wpt/meta/css/css-grid/grid-items/grid-layout-z-order-a.html.ini
deleted file mode 100644
index 64b4b2b480e..00000000000
--- a/tests/wpt/meta/css/css-grid/grid-items/grid-layout-z-order-a.html.ini
+++ /dev/null
@@ -1,2 +0,0 @@
-[grid-layout-z-order-a.html]
- expected: FAIL
diff --git a/tests/wpt/meta/css/css-grid/grid-items/grid-layout-z-order-b.html.ini b/tests/wpt/meta/css/css-grid/grid-items/grid-layout-z-order-b.html.ini
deleted file mode 100644
index 7573aba43fd..00000000000
--- a/tests/wpt/meta/css/css-grid/grid-items/grid-layout-z-order-b.html.ini
+++ /dev/null
@@ -1,2 +0,0 @@
-[grid-layout-z-order-b.html]
- expected: FAIL
diff --git a/tests/wpt/meta/css/css-grid/grid-items/grid-z-axis-ordering-001.html.ini b/tests/wpt/meta/css/css-grid/grid-items/grid-z-axis-ordering-001.html.ini
deleted file mode 100644
index 3a9b399710f..00000000000
--- a/tests/wpt/meta/css/css-grid/grid-items/grid-z-axis-ordering-001.html.ini
+++ /dev/null
@@ -1,2 +0,0 @@
-[grid-z-axis-ordering-001.html]
- expected: FAIL
diff --git a/tests/wpt/meta/css/css-grid/grid-items/grid-z-axis-ordering-002.html.ini b/tests/wpt/meta/css/css-grid/grid-items/grid-z-axis-ordering-002.html.ini
deleted file mode 100644
index 3702bfaad3d..00000000000
--- a/tests/wpt/meta/css/css-grid/grid-items/grid-z-axis-ordering-002.html.ini
+++ /dev/null
@@ -1,2 +0,0 @@
-[grid-z-axis-ordering-002.html]
- expected: FAIL
diff --git a/tests/wpt/meta/css/css-grid/grid-items/grid-z-axis-ordering-003.html.ini b/tests/wpt/meta/css/css-grid/grid-items/grid-z-axis-ordering-003.html.ini
deleted file mode 100644
index 0a3c12ac1bf..00000000000
--- a/tests/wpt/meta/css/css-grid/grid-items/grid-z-axis-ordering-003.html.ini
+++ /dev/null
@@ -1,2 +0,0 @@
-[grid-z-axis-ordering-003.html]
- expected: FAIL
diff --git a/tests/wpt/meta/css/css-grid/grid-items/grid-z-axis-ordering-004.html.ini b/tests/wpt/meta/css/css-grid/grid-items/grid-z-axis-ordering-004.html.ini
deleted file mode 100644
index 221e23ddb98..00000000000
--- a/tests/wpt/meta/css/css-grid/grid-items/grid-z-axis-ordering-004.html.ini
+++ /dev/null
@@ -1,2 +0,0 @@
-[grid-z-axis-ordering-004.html]
- expected: FAIL
diff --git a/tests/wpt/meta/css/css-grid/grid-items/grid-z-axis-ordering-005.html.ini b/tests/wpt/meta/css/css-grid/grid-items/grid-z-axis-ordering-005.html.ini
deleted file mode 100644
index 43014f76ca9..00000000000
--- a/tests/wpt/meta/css/css-grid/grid-items/grid-z-axis-ordering-005.html.ini
+++ /dev/null
@@ -1,2 +0,0 @@
-[grid-z-axis-ordering-005.html]
- expected: FAIL
diff --git a/tests/wpt/meta/css/css-grid/grid-items/grid-z-axis-ordering-overlapped-items-001.html.ini b/tests/wpt/meta/css/css-grid/grid-items/grid-z-axis-ordering-overlapped-items-001.html.ini
deleted file mode 100644
index 98556a4a8ca..00000000000
--- a/tests/wpt/meta/css/css-grid/grid-items/grid-z-axis-ordering-overlapped-items-001.html.ini
+++ /dev/null
@@ -1,2 +0,0 @@
-[grid-z-axis-ordering-overlapped-items-001.html]
- expected: FAIL
diff --git a/tests/wpt/meta/css/css-grid/grid-items/grid-z-axis-ordering-overlapped-items-002.html.ini b/tests/wpt/meta/css/css-grid/grid-items/grid-z-axis-ordering-overlapped-items-002.html.ini
deleted file mode 100644
index c947cd0caf8..00000000000
--- a/tests/wpt/meta/css/css-grid/grid-items/grid-z-axis-ordering-overlapped-items-002.html.ini
+++ /dev/null
@@ -1,2 +0,0 @@
-[grid-z-axis-ordering-overlapped-items-002.html]
- expected: FAIL
diff --git a/tests/wpt/meta/css/css-grid/grid-items/grid-z-axis-ordering-overlapped-items-003.html.ini b/tests/wpt/meta/css/css-grid/grid-items/grid-z-axis-ordering-overlapped-items-003.html.ini
deleted file mode 100644
index 80644b4df38..00000000000
--- a/tests/wpt/meta/css/css-grid/grid-items/grid-z-axis-ordering-overlapped-items-003.html.ini
+++ /dev/null
@@ -1,2 +0,0 @@
-[grid-z-axis-ordering-overlapped-items-003.html]
- expected: FAIL
diff --git a/tests/wpt/meta/css/css-grid/grid-items/grid-z-axis-ordering-overlapped-items-004.html.ini b/tests/wpt/meta/css/css-grid/grid-items/grid-z-axis-ordering-overlapped-items-004.html.ini
deleted file mode 100644
index c6498b7b9c0..00000000000
--- a/tests/wpt/meta/css/css-grid/grid-items/grid-z-axis-ordering-overlapped-items-004.html.ini
+++ /dev/null
@@ -1,2 +0,0 @@
-[grid-z-axis-ordering-overlapped-items-004.html]
- expected: FAIL
diff --git a/tests/wpt/meta/css/css-grid/grid-items/grid-z-axis-ordering-overlapped-items-005.html.ini b/tests/wpt/meta/css/css-grid/grid-items/grid-z-axis-ordering-overlapped-items-005.html.ini
deleted file mode 100644
index c214befe848..00000000000
--- a/tests/wpt/meta/css/css-grid/grid-items/grid-z-axis-ordering-overlapped-items-005.html.ini
+++ /dev/null
@@ -1,2 +0,0 @@
-[grid-z-axis-ordering-overlapped-items-005.html]
- expected: FAIL
diff --git a/tests/wpt/meta/css/css-grid/grid-items/grid-z-axis-ordering-overlapped-items-006.html.ini b/tests/wpt/meta/css/css-grid/grid-items/grid-z-axis-ordering-overlapped-items-006.html.ini
deleted file mode 100644
index b4f85a68692..00000000000
--- a/tests/wpt/meta/css/css-grid/grid-items/grid-z-axis-ordering-overlapped-items-006.html.ini
+++ /dev/null
@@ -1,2 +0,0 @@
-[grid-z-axis-ordering-overlapped-items-006.html]
- expected: FAIL
diff --git a/tests/wpt/meta/css/css-will-change/will-change-stacking-context-z-index-3.html.ini b/tests/wpt/meta/css/css-will-change/will-change-stacking-context-z-index-3.html.ini
new file mode 100644
index 00000000000..d0c021b9dd0
--- /dev/null
+++ b/tests/wpt/meta/css/css-will-change/will-change-stacking-context-z-index-3.html.ini
@@ -0,0 +1,2 @@
+[will-change-stacking-context-z-index-3.html]
+ prefs: ["layout_grid_enabled:true"]
diff --git a/tests/wpt/tests/css/css-will-change/will-change-stacking-context-z-index-2.html b/tests/wpt/tests/css/css-will-change/will-change-stacking-context-z-index-2.html
new file mode 100644
index 00000000000..9379185048a
--- /dev/null
+++ b/tests/wpt/tests/css/css-will-change/will-change-stacking-context-z-index-2.html
@@ -0,0 +1,29 @@
+<!DOCTYPE html>
+<title>CSS Test: `will-change: z-index`</title>
+<link rel="author" title="Oriol Brufau" href="obrufau@igalia.com">
+<link rel="help" href="https://www.w3.org/TR/css-will-change/#valdef-will-change-custom-ident">
+<link rel="help" href="https://www.w3.org/TR/css-flexbox-1/#painting">
+<link rel="help" href="https://github.com/w3c/csswg-drafts/issues/11827">
+<link rel="match" href="../reference/ref-filled-green-100px-square.xht">
+<meta name="assert" content="
+ `will-change: z-index` establishes a stacking context on a flex item.
+">
+<style>
+.test {
+ will-change: z-index;
+ width: 100px;
+ background: red;
+}
+.test::before {
+ content: "";
+ display: block;
+ position: relative;
+ z-index: -1;
+ height: 100px;
+ background: green;
+}
+</style>
+<p>Test passes if there is a filled green square and <strong>no red</strong>.</p>
+<div style="display: flex">
+ <div class="test"></div>
+</div>
diff --git a/tests/wpt/tests/css/css-will-change/will-change-stacking-context-z-index-3.html b/tests/wpt/tests/css/css-will-change/will-change-stacking-context-z-index-3.html
new file mode 100644
index 00000000000..4ec40ae1a43
--- /dev/null
+++ b/tests/wpt/tests/css/css-will-change/will-change-stacking-context-z-index-3.html
@@ -0,0 +1,29 @@
+<!DOCTYPE html>
+<title>CSS Test: `will-change: z-index`</title>
+<link rel="author" title="Oriol Brufau" href="obrufau@igalia.com">
+<link rel="help" href="https://www.w3.org/TR/css-will-change/#valdef-will-change-custom-ident">
+<link rel="help" href="https://www.w3.org/TR/css-grid-2/#z-order">
+<link rel="help" href="https://github.com/w3c/csswg-drafts/issues/11827">
+<link rel="match" href="../reference/ref-filled-green-100px-square.xht">
+<meta name="assert" content="
+ `will-change: z-index` establishes a stacking context on a grid item.
+">
+<style>
+.test {
+ will-change: z-index;
+ width: 100px;
+ background: red;
+}
+.test::before {
+ content: "";
+ display: block;
+ position: relative;
+ z-index: -1;
+ height: 100px;
+ background: green;
+}
+</style>
+<p>Test passes if there is a filled green square and <strong>no red</strong>.</p>
+<div style="display: grid">
+ <div class="test"></div>
+</div>
diff --git a/tests/wpt/tests/css/css-will-change/will-change-stacking-context-z-index-4.html b/tests/wpt/tests/css/css-will-change/will-change-stacking-context-z-index-4.html
new file mode 100644
index 00000000000..d8a87b23415
--- /dev/null
+++ b/tests/wpt/tests/css/css-will-change/will-change-stacking-context-z-index-4.html
@@ -0,0 +1,28 @@
+<!DOCTYPE html>
+<title>CSS Test: `will-change: z-index`</title>
+<link rel="author" title="Oriol Brufau" href="obrufau@igalia.com">
+<link rel="help" href="https://www.w3.org/TR/css-will-change/#valdef-will-change-custom-ident">
+<link rel="help" href="https://www.w3.org/TR/CSS2/visuren.html#z-index">
+<link rel="help" href="https://github.com/w3c/csswg-drafts/issues/11827">
+<link rel="match" href="../reference/ref-filled-green-100px-square.xht">
+<meta name="assert" content="
+ `will-change: z-index` doesn't establish a stacking context on a non-positioned block box,
+ because `z-index` doesn't apply in that case.
+">
+<style>
+.test {
+ will-change: z-index;
+ width: 100px;
+ background: green;
+}
+.test::before {
+ content: "";
+ display: block;
+ position: relative;
+ z-index: -1;
+ height: 100px;
+ background: red;
+}
+</style>
+<p>Test passes if there is a filled green square and <strong>no red</strong>.</p>
+<div class="test"></div>