commit 5e0e11d1cf9bed58c00af5f636dd9ceb18c8ea5e
parent 563cf05a5f349835f7c95487efa07c74a44504ba
Author: Steve Kobes <skobes@chromium.org>
Date: Wed, 26 Nov 2025 08:54:29 +0000
Bug 2001679 [wpt PR 56189] - Paint transition pseudos on top of everything else in the scope., a=testonly
Automatic update from web-platform-tests
Paint transition pseudos on top of everything else in the scope.
Since crrev.com/1546589, the ::view-transition pseudo's PaintLayer is a
child of the scope's PaintLayer.
This patch implements custom paint order logic to ensure that the
pseudo tree behaves like an overlay, regardless of any higher z-index
that may be set on the scope's non-participating descendants.
Also test the crash repro from https://crbug.com/445406431#comment3
(self-participating scope with high z-index child also participating).
Bug: 421927605, 445406431
Change-Id: Ifac38969abbb82ea9a4ca67e6b03fffe99d52044
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/7178180
Commit-Queue: Steve Kobes <skobes@chromium.org>
Reviewed-by: Vladimir Levin <vmpstr@chromium.org>
Cr-Commit-Position: refs/heads/main@{#1549132}
--
wpt-commits: 7733484b3e7c79cc8fc6288500d5c30ea52ffa36
wpt-pr: 56189
Diffstat:
3 files changed, 119 insertions(+), 0 deletions(-)
diff --git a/testing/web-platform/tests/css/css-view-transitions/scoped/crashtests/zindex-part.html b/testing/web-platform/tests/css/css-view-transitions/scoped/crashtests/zindex-part.html
@@ -0,0 +1,30 @@
+<!DOCTYPE html>
+<html class="test-wait">
+<head>
+<style>
+
+#scope {
+ position: relative; width: 100px; height: 100px;
+ background: #ddd; contain: strict;
+}
+#part {
+ position: absolute; top: 10px; left: 10px;
+ width: 80px; height: 80px; background: #8cf;
+ z-index: 1; view-transition-name: foo;
+}
+
+</style>
+</head>
+<body>
+<div id=scope><div id=part></div></div>
+<script>
+
+onload = async () => {
+ t = scope.startViewTransition(() => {});
+ await t.finished;
+ document.documentElement.classList.remove('test-wait');
+};
+
+</script>
+</body>
+</html>
diff --git a/testing/web-platform/tests/css/css-view-transitions/scoped/paint-order-ref.html b/testing/web-platform/tests/css/css-view-transitions/scoped/paint-order-ref.html
@@ -0,0 +1,32 @@
+<!DOCTYPE html>
+<style>
+ #scope {
+ position: relative; width: 200px; height: 100px;
+ background: white; contain: strict;
+ }
+ #nonpart1 {
+ position: absolute; top: 40px; left: 20px;
+ width: 50px; height: 50px; background: #a4f;
+ }
+ #nonpart2 {
+ position: absolute; top: 20px; left: 30px;
+ width: 50px; height: 50px; background: #f88;
+ }
+ #vt {
+ position: relative; width: 200px; height: 100px;
+ top: -100px; background: rgba(0, 0, 0, 0.1);
+ will-change: transform;
+ }
+ #part {
+ position: absolute; top: 30px; left: 50px;
+ width: 50px; height: 50px; background: #8cf;
+ }
+
+</style>
+<div id=scope>
+ <div id=nonpart1></div>
+ <div id=nonpart2></div>
+</div>
+<div id=vt>
+ <div id=part></div>
+</div>
diff --git a/testing/web-platform/tests/css/css-view-transitions/scoped/paint-order.html b/testing/web-platform/tests/css/css-view-transitions/scoped/paint-order.html
@@ -0,0 +1,57 @@
+<!DOCTYPE html>
+<html class=reftest-wait>
+<head>
+<link rel="help" href="https://drafts.csswg.org/css-view-transitions-2/">
+<link rel="match" href="paint-order-ref.html">
+<script src="/common/reftest-wait.js"></script>
+<script src="/web-animations/testcommon.js"></script>
+<style>
+
+#scope {
+ position: relative; width: 200px; height: 100px;
+ background: white; contain: strict;
+ view-transition-name: none;
+}
+#part {
+ position: absolute; top: 10px; left: 10px;
+ width: 50px; height: 50px; background: #8cf;
+ z-index: 1; view-transition-name: foo;
+}
+#higher-nonpart {
+ position: absolute; top: 20px; left: 30px;
+ z-index: 2; width: 50px; height: 50px; background: #f88;
+}
+#lower-nonpart {
+ position: absolute; top: 40px; left: 20px;
+ z-index: -1; width: 50px; height: 50px; background: #a4f;
+}
+::view-transition { background: rgba(0, 0, 0, 0.1); }
+::view-transition-group(*) { animation-play-state: paused; }
+::view-transition-new(*) {
+ animation: unset; opacity: 1;
+ transform: translateX(40px) translateY(20px);
+}
+::view-transition-old(*) { animation: unset; opacity: 0; }
+
+</style>
+</head>
+<body>
+<div id=scope>
+ <div id=part></div>
+ <div id=higher-nonpart></div>
+ <div id=lower-nonpart></div>
+</div>
+<script>
+
+const scope = document.querySelector("#scope");
+failIfNot(scope.startViewTransition, "Missing element.startViewTransition");
+
+async function runTest() {
+ await waitForCompositorReady();
+ scope.startViewTransition(() => requestAnimationFrame(takeScreenshot));
+}
+onload = () => runTest();
+
+</script>
+</body>
+</html>