summaryrefslogtreecommitdiffstats
path: root/testing/web-platform/tests/css/css-view-transitions
diff options
context:
space:
mode:
Diffstat (limited to 'testing/web-platform/tests/css/css-view-transitions')
-rw-r--r--testing/web-platform/tests/css/css-view-transitions/3d-transform-incoming-ref.html28
-rw-r--r--testing/web-platform/tests/css/css-view-transitions/3d-transform-incoming.html65
-rw-r--r--testing/web-platform/tests/css/css-view-transitions/3d-transform-outgoing-ref.html21
-rw-r--r--testing/web-platform/tests/css/css-view-transitions/3d-transform-outgoing.html66
-rw-r--r--testing/web-platform/tests/css/css-view-transitions/break-inside-avoid-child-ref.html26
-rw-r--r--testing/web-platform/tests/css/css-view-transitions/break-inside-avoid-child.html61
-rw-r--r--testing/web-platform/tests/css/css-view-transitions/content-object-fit-fill-ref.html32
-rw-r--r--testing/web-platform/tests/css/css-view-transitions/content-object-fit-none-ref.html22
-rw-r--r--testing/web-platform/tests/css/css-view-transitions/content-smaller-than-box-size-ref.html23
-rw-r--r--testing/web-platform/tests/css/css-view-transitions/content-smaller-than-box-size.html55
-rw-r--r--testing/web-platform/tests/css/css-view-transitions/content-visibility-auto-shared-element-ref.html31
-rw-r--r--testing/web-platform/tests/css/css-view-transitions/content-visibility-auto-shared-element.html81
-rw-r--r--testing/web-platform/tests/css/css-view-transitions/content-with-clip-max-texture-size-ref.html41
-rw-r--r--testing/web-platform/tests/css/css-view-transitions/content-with-clip-max-texture-size.html70
-rw-r--r--testing/web-platform/tests/css/css-view-transitions/content-with-clip-ref.html30
-rw-r--r--testing/web-platform/tests/css/css-view-transitions/content-with-clip-root-ref.html36
-rw-r--r--testing/web-platform/tests/css/css-view-transitions/content-with-clip-root.html79
-rw-r--r--testing/web-platform/tests/css/css-view-transitions/content-with-clip.html73
-rw-r--r--testing/web-platform/tests/css/css-view-transitions/content-with-inline-child-ref.html32
-rw-r--r--testing/web-platform/tests/css/css-view-transitions/content-with-inline-child.html71
-rw-r--r--testing/web-platform/tests/css/css-view-transitions/content-with-overflow-ref.html28
-rw-r--r--testing/web-platform/tests/css/css-view-transitions/content-with-overflow-zoomed-ref.html33
-rw-r--r--testing/web-platform/tests/css/css-view-transitions/content-with-transform-new-image.html59
-rw-r--r--testing/web-platform/tests/css/css-view-transitions/content-with-transform-old-image.html60
-rw-r--r--testing/web-platform/tests/css/css-view-transitions/content-with-transform-ref.html24
-rw-r--r--testing/web-platform/tests/css/css-view-transitions/css-tags-paint-order-ref.html34
-rw-r--r--testing/web-platform/tests/css/css-view-transitions/css-tags-paint-order-with-entry-ref.html40
-rw-r--r--testing/web-platform/tests/css/css-view-transitions/css-tags-paint-order-with-entry.html111
-rw-r--r--testing/web-platform/tests/css/css-view-transitions/css-tags-paint-order.html93
-rw-r--r--testing/web-platform/tests/css/css-view-transitions/css-tags-shared-element-ref.html28
-rw-r--r--testing/web-platform/tests/css/css-view-transitions/css-tags-shared-element.html79
-rw-r--r--testing/web-platform/tests/css/css-view-transitions/dialog-in-top-layer-during-transition-new.html71
-rw-r--r--testing/web-platform/tests/css/css-view-transitions/dialog-in-top-layer-during-transition-old.html72
-rw-r--r--testing/web-platform/tests/css/css-view-transitions/dialog-in-top-layer-during-transition-ref.html28
-rw-r--r--testing/web-platform/tests/css/css-view-transitions/duplicate-tag-rejects-capture.html48
-rw-r--r--testing/web-platform/tests/css/css-view-transitions/duplicate-tag-rejects-start.html50
-rw-r--r--testing/web-platform/tests/css/css-view-transitions/element-with-overflow-ref.html41
-rw-r--r--testing/web-platform/tests/css/css-view-transitions/element-with-overflow.html72
-rw-r--r--testing/web-platform/tests/css/css-view-transitions/event-pseudo-name.html54
-rw-r--r--testing/web-platform/tests/css/css-view-transitions/far-away-capture-ref.html31
-rw-r--r--testing/web-platform/tests/css/css-view-transitions/far-away-capture.html84
-rw-r--r--testing/web-platform/tests/css/css-view-transitions/get-computed-style-crash.html16
-rw-r--r--testing/web-platform/tests/css/css-view-transitions/hit-test-unpainted-element-from-point.html72
-rw-r--r--testing/web-platform/tests/css/css-view-transitions/hit-test-unpainted-element-ref.html17
-rw-r--r--testing/web-platform/tests/css/css-view-transitions/hit-test-unpainted-element.html69
-rw-r--r--testing/web-platform/tests/css/css-view-transitions/hit-test-unrelated-element-ref.html27
-rw-r--r--testing/web-platform/tests/css/css-view-transitions/hit-test-unrelated-element.html73
-rw-r--r--testing/web-platform/tests/css/css-view-transitions/iframe-transition-ref.html22
-rw-r--r--testing/web-platform/tests/css/css-view-transitions/iframe-transition.sub.html21
-rw-r--r--testing/web-platform/tests/css/css-view-transitions/inline-child-with-filter-ref.html29
-rw-r--r--testing/web-platform/tests/css/css-view-transitions/inline-child-with-filter.html52
-rw-r--r--testing/web-platform/tests/css/css-view-transitions/input-blocked-when-rendering-suppressed.html75
-rw-r--r--testing/web-platform/tests/css/css-view-transitions/intrinsic-aspect-ratio-ref.html31
-rw-r--r--testing/web-platform/tests/css/css-view-transitions/japanese-tag-ref.html25
-rw-r--r--testing/web-platform/tests/css/css-view-transitions/japanese-tag.html95
-rw-r--r--testing/web-platform/tests/css/css-view-transitions/mix-blend-mode-only-on-transition.html46
-rw-r--r--testing/web-platform/tests/css/css-view-transitions/new-and-old-sizes-match-ref.html48
-rw-r--r--testing/web-platform/tests/css/css-view-transitions/new-and-old-sizes-match.html50
-rw-r--r--testing/web-platform/tests/css/css-view-transitions/new-content-captures-clip-path-ref.html23
-rw-r--r--testing/web-platform/tests/css/css-view-transitions/new-content-captures-clip-path.html48
-rw-r--r--testing/web-platform/tests/css/css-view-transitions/new-content-captures-different-size-ref.html36
-rw-r--r--testing/web-platform/tests/css/css-view-transitions/new-content-captures-different-size.html64
-rw-r--r--testing/web-platform/tests/css/css-view-transitions/new-content-captures-opacity-ref.html24
-rw-r--r--testing/web-platform/tests/css/css-view-transitions/new-content-captures-opacity.html47
-rw-r--r--testing/web-platform/tests/css/css-view-transitions/new-content-captures-root-ref.html20
-rw-r--r--testing/web-platform/tests/css/css-view-transitions/new-content-captures-root.html53
-rw-r--r--testing/web-platform/tests/css/css-view-transitions/new-content-container-writing-modes-ref.html23
-rw-r--r--testing/web-platform/tests/css/css-view-transitions/new-content-container-writing-modes.html89
-rw-r--r--testing/web-platform/tests/css/css-view-transitions/new-content-element-writing-modes-ref.html24
-rw-r--r--testing/web-platform/tests/css/css-view-transitions/new-content-element-writing-modes.html94
-rw-r--r--testing/web-platform/tests/css/css-view-transitions/new-content-has-scrollbars-ref.html27
-rw-r--r--testing/web-platform/tests/css/css-view-transitions/new-content-has-scrollbars.html62
-rw-r--r--testing/web-platform/tests/css/css-view-transitions/new-content-intrinsic-aspect-ratio.html67
-rw-r--r--testing/web-platform/tests/css/css-view-transitions/new-content-is-empty-div-ref.html19
-rw-r--r--testing/web-platform/tests/css/css-view-transitions/new-content-is-empty-div.html61
-rw-r--r--testing/web-platform/tests/css/css-view-transitions/new-content-object-fit-fill.html77
-rw-r--r--testing/web-platform/tests/css/css-view-transitions/new-content-object-fit-none.html70
-rw-r--r--testing/web-platform/tests/css/css-view-transitions/new-content-object-view-box-clip-path-ref.html46
-rw-r--r--testing/web-platform/tests/css/css-view-transitions/new-content-object-view-box-clip-path-reference-ref.html57
-rw-r--r--testing/web-platform/tests/css/css-view-transitions/new-content-object-view-box-clip-path-reference.html93
-rw-r--r--testing/web-platform/tests/css/css-view-transitions/new-content-object-view-box-clip-path.html82
-rw-r--r--testing/web-platform/tests/css/css-view-transitions/new-content-object-view-box-overflow-clipped-ref.html38
-rw-r--r--testing/web-platform/tests/css/css-view-transitions/new-content-object-view-box-overflow-clipped.html67
-rw-r--r--testing/web-platform/tests/css/css-view-transitions/new-content-object-view-box-overflow-ref.html38
-rw-r--r--testing/web-platform/tests/css/css-view-transitions/new-content-object-view-box-overflow.html67
-rw-r--r--testing/web-platform/tests/css/css-view-transitions/new-content-scaling-ref.html21
-rw-r--r--testing/web-platform/tests/css/css-view-transitions/new-content-scaling.html63
-rw-r--r--testing/web-platform/tests/css/css-view-transitions/new-content-with-overflow-zoomed.html56
-rw-r--r--testing/web-platform/tests/css/css-view-transitions/new-content-with-overflow.html51
-rw-r--r--testing/web-platform/tests/css/css-view-transitions/new-element-on-start-ref.html19
-rw-r--r--testing/web-platform/tests/css/css-view-transitions/new-element-on-start.html69
-rw-r--r--testing/web-platform/tests/css/css-view-transitions/new-root-vertical-writing-mode-ref.html22
-rw-r--r--testing/web-platform/tests/css/css-view-transitions/new-root-vertical-writing-mode.html73
-rw-r--r--testing/web-platform/tests/css/css-view-transitions/no-containment-on-new-element-mid-transition.html38
-rw-r--r--testing/web-platform/tests/css/css-view-transitions/no-containment-on-new-element.html47
-rw-r--r--testing/web-platform/tests/css/css-view-transitions/no-containment-on-old-element.html46
-rw-r--r--testing/web-platform/tests/css/css-view-transitions/no-crash-set-exception.html45
-rw-r--r--testing/web-platform/tests/css/css-view-transitions/no-css-animation-while-render-blocked.html59
-rw-r--r--testing/web-platform/tests/css/css-view-transitions/no-raf-while-render-blocked.html48
-rw-r--r--testing/web-platform/tests/css/css-view-transitions/no-root-capture-ref.html28
-rw-r--r--testing/web-platform/tests/css/css-view-transitions/no-root-capture.html54
-rw-r--r--testing/web-platform/tests/css/css-view-transitions/nothing-captured-ref.html28
-rw-r--r--testing/web-platform/tests/css/css-view-transitions/nothing-captured.html47
-rw-r--r--testing/web-platform/tests/css/css-view-transitions/object-view-box-new-image.html70
-rw-r--r--testing/web-platform/tests/css/css-view-transitions/object-view-box-old-image.html72
-rw-r--r--testing/web-platform/tests/css/css-view-transitions/object-view-box-ref.html25
-rw-r--r--testing/web-platform/tests/css/css-view-transitions/old-content-captures-clip-path-ref.html22
-rw-r--r--testing/web-platform/tests/css/css-view-transitions/old-content-captures-clip-path.html46
-rw-r--r--testing/web-platform/tests/css/css-view-transitions/old-content-captures-different-size-ref.html35
-rw-r--r--testing/web-platform/tests/css/css-view-transitions/old-content-captures-different-size.html64
-rw-r--r--testing/web-platform/tests/css/css-view-transitions/old-content-captures-opacity-ref.html24
-rw-r--r--testing/web-platform/tests/css/css-view-transitions/old-content-captures-opacity.html48
-rw-r--r--testing/web-platform/tests/css/css-view-transitions/old-content-captures-root-ref.html19
-rw-r--r--testing/web-platform/tests/css/css-view-transitions/old-content-captures-root.html51
-rw-r--r--testing/web-platform/tests/css/css-view-transitions/old-content-container-writing-modes-ref.html24
-rw-r--r--testing/web-platform/tests/css/css-view-transitions/old-content-container-writing-modes.html94
-rw-r--r--testing/web-platform/tests/css/css-view-transitions/old-content-element-writing-modes-ref.html25
-rw-r--r--testing/web-platform/tests/css/css-view-transitions/old-content-element-writing-modes.html95
-rw-r--r--testing/web-platform/tests/css/css-view-transitions/old-content-has-scrollbars-ref.html30
-rw-r--r--testing/web-platform/tests/css/css-view-transitions/old-content-has-scrollbars.html60
-rw-r--r--testing/web-platform/tests/css/css-view-transitions/old-content-intrinsic-aspect-ratio.html67
-rw-r--r--testing/web-platform/tests/css/css-view-transitions/old-content-is-empty-div-ref.html19
-rw-r--r--testing/web-platform/tests/css/css-view-transitions/old-content-is-empty-div.html60
-rw-r--r--testing/web-platform/tests/css/css-view-transitions/old-content-object-fit-fill.html77
-rw-r--r--testing/web-platform/tests/css/css-view-transitions/old-content-object-fit-none.html70
-rw-r--r--testing/web-platform/tests/css/css-view-transitions/old-content-object-view-box-clip-path-ref.html46
-rw-r--r--testing/web-platform/tests/css/css-view-transitions/old-content-object-view-box-clip-path-reference-ref.html57
-rw-r--r--testing/web-platform/tests/css/css-view-transitions/old-content-object-view-box-clip-path-reference.html94
-rw-r--r--testing/web-platform/tests/css/css-view-transitions/old-content-object-view-box-clip-path.html83
-rw-r--r--testing/web-platform/tests/css/css-view-transitions/old-content-object-view-box-overflow-ref.html38
-rw-r--r--testing/web-platform/tests/css/css-view-transitions/old-content-object-view-box-overflow.html66
-rw-r--r--testing/web-platform/tests/css/css-view-transitions/old-content-with-overflow-zoomed.html56
-rw-r--r--testing/web-platform/tests/css/css-view-transitions/old-content-with-overflow.html51
-rw-r--r--testing/web-platform/tests/css/css-view-transitions/old-root-vertical-writing-mode-ref.html24
-rw-r--r--testing/web-platform/tests/css/css-view-transitions/old-root-vertical-writing-mode.html76
-rw-r--r--testing/web-platform/tests/css/css-view-transitions/only-child-group.html100
-rw-r--r--testing/web-platform/tests/css/css-view-transitions/only-child-image-pair.html33
-rw-r--r--testing/web-platform/tests/css/css-view-transitions/only-child-new.html153
-rw-r--r--testing/web-platform/tests/css/css-view-transitions/only-child-no-transition.html39
-rw-r--r--testing/web-platform/tests/css/css-view-transitions/only-child-old.html153
-rw-r--r--testing/web-platform/tests/css/css-view-transitions/only-child-view-transition.html33
-rw-r--r--testing/web-platform/tests/css/css-view-transitions/parsing/view-transition-name-computed.html24
-rw-r--r--testing/web-platform/tests/css/css-view-transitions/parsing/view-transition-name-valid.html21
-rw-r--r--testing/web-platform/tests/css/css-view-transitions/pseudo-computed-style-stays-in-sync-with-new-element.html42
-rw-r--r--testing/web-platform/tests/css/css-view-transitions/pseudo-get-computed-style.html94
-rw-r--r--testing/web-platform/tests/css/css-view-transitions/ready_resolves_after_dom_before_raf.html51
-rw-r--r--testing/web-platform/tests/css/css-view-transitions/root-captured-as-different-tag-ref.html19
-rw-r--r--testing/web-platform/tests/css/css-view-transitions/root-captured-as-different-tag.html56
-rw-r--r--testing/web-platform/tests/css/css-view-transitions/root-scrollbar-with-fixed-background-ref.html33
-rw-r--r--testing/web-platform/tests/css/css-view-transitions/root-scrollbar-with-fixed-background.html67
-rw-r--r--testing/web-platform/tests/css/css-view-transitions/root-style-change-during-animation-ref.html20
-rw-r--r--testing/web-platform/tests/css/css-view-transitions/root-style-change-during-animation.html65
-rw-r--r--testing/web-platform/tests/css/css-view-transitions/root-to-shared-animation-end-ref.html26
-rw-r--r--testing/web-platform/tests/css/css-view-transitions/root-to-shared-animation-end.html53
-rw-r--r--testing/web-platform/tests/css/css-view-transitions/root-to-shared-animation-incoming-ref.html13
-rw-r--r--testing/web-platform/tests/css/css-view-transitions/root-to-shared-animation-incoming.html44
-rw-r--r--testing/web-platform/tests/css/css-view-transitions/root-to-shared-animation-start-ref.html21
-rw-r--r--testing/web-platform/tests/css/css-view-transitions/root-to-shared-animation-start.html44
-rw-r--r--testing/web-platform/tests/css/css-view-transitions/scroller-child-abspos-ref.html40
-rw-r--r--testing/web-platform/tests/css/css-view-transitions/scroller-child-abspos.html61
-rw-r--r--testing/web-platform/tests/css/css-view-transitions/scroller-child-ref.html38
-rw-r--r--testing/web-platform/tests/css/css-view-transitions/scroller-child.html59
-rw-r--r--testing/web-platform/tests/css/css-view-transitions/scroller-ref.html31
-rw-r--r--testing/web-platform/tests/css/css-view-transitions/scroller.html52
-rw-r--r--testing/web-platform/tests/css/css-view-transitions/set-current-time-ref.html15
-rw-r--r--testing/web-platform/tests/css/css-view-transitions/set-current-time-transform-ref.html40
-rw-r--r--testing/web-platform/tests/css/css-view-transitions/set-current-time-transform.html61
-rw-r--r--testing/web-platform/tests/css/css-view-transitions/set-current-time.html47
-rw-r--r--testing/web-platform/tests/css/css-view-transitions/set-universal-specificity-ref.html17
-rw-r--r--testing/web-platform/tests/css/css-view-transitions/set-universal-specificity.html45
-rw-r--r--testing/web-platform/tests/css/css-view-transitions/shared-transition-author-style.manual.html94
-rw-r--r--testing/web-platform/tests/css/css-view-transitions/shared-transition-half.manual.html60
-rw-r--r--testing/web-platform/tests/css/css-view-transitions/shared-transition-shapes.manual.html80
-rw-r--r--testing/web-platform/tests/css/css-view-transitions/style-inheritance.html56
-rw-r--r--testing/web-platform/tests/css/css-view-transitions/support/frame-helper.html25
-rw-r--r--testing/web-platform/tests/css/css-view-transitions/synchronous-callback-skipped-before-run.html37
-rw-r--r--testing/web-platform/tests/css/css-view-transitions/transition-skipped-after-animation-started.html37
-rw-r--r--testing/web-platform/tests/css/css-view-transitions/transition-skipped-from-invalid-callback.html46
-rw-r--r--testing/web-platform/tests/css/css-view-transitions/unset-and-initial-view-transition-name.html50
-rw-r--r--testing/web-platform/tests/css/css-view-transitions/view-transition-name-on-added-element.html37
-rw-r--r--testing/web-platform/tests/css/css-view-transitions/view-transition-name-on-removed-element.html36
-rw-r--r--testing/web-platform/tests/css/css-view-transitions/web-animations-api-ref.html26
-rw-r--r--testing/web-platform/tests/css/css-view-transitions/web-animations-api.html53
183 files changed, 9116 insertions, 0 deletions
diff --git a/testing/web-platform/tests/css/css-view-transitions/3d-transform-incoming-ref.html b/testing/web-platform/tests/css/css-view-transitions/3d-transform-incoming-ref.html
new file mode 100644
index 0000000000..a789b706ef
--- /dev/null
+++ b/testing/web-platform/tests/css/css-view-transitions/3d-transform-incoming-ref.html
@@ -0,0 +1,28 @@
+<!DOCTYPE html>
+<title>Shared transitions: 3d transform ref</title>
+<link rel="help" href="https://github.com/WICG/view-transitions">
+<link rel="author" href="mailto:vmpstr@chromium.org">
+<style>
+div { box-sizing: border-box; will-change: transform }
+.wrap_perspective {
+ perspective: 100px;
+ width: max-content;
+ transform: translate(200px);
+}
+.rotatex {
+ transform-style: preserve-3d;
+ transform: rotateX(20deg);
+ background: blue;
+}
+.shared {
+ contain: layout;
+ width: 100px;
+ height: 100px;
+}
+body { background: pink }
+
+</style>
+
+<div class="wrap_perspective"><div class="rotatex shared"></div></div>
+
+
diff --git a/testing/web-platform/tests/css/css-view-transitions/3d-transform-incoming.html b/testing/web-platform/tests/css/css-view-transitions/3d-transform-incoming.html
new file mode 100644
index 0000000000..d852108ffa
--- /dev/null
+++ b/testing/web-platform/tests/css/css-view-transitions/3d-transform-incoming.html
@@ -0,0 +1,65 @@
+<!DOCTYPE html>
+<html class=reftest-wait>
+<title>Shared transitions: 3d transform</title>
+<link rel="help" href="https://github.com/WICG/view-transitions">
+<link rel="author" href="mailto:vmpstr@chromium.org">
+<link rel="match" href="3d-transform-incoming-ref.html">
+<meta name=fuzzy content="3d-transform-incoming-ref.html:0-80;0-500">
+<script src="/common/reftest-wait.js"></script>
+<style>
+div { box-sizing: border-box; will-change: transform }
+.rotate3d {
+ transform: translate(20px, 100px) rotate3d(1, 1, 1, 45deg);
+ background: blue;
+}
+
+.wrap_perspective {
+ perspective: 100px;
+ width: max-content;
+ transform: translate(200px);
+}
+.rotatex {
+ transform-style: preserve-3d;
+ transform: rotateX(20deg);
+ background: green;
+}
+.shared {
+ view-transition-name: shared;
+ contain: layout;
+ width: 100px;
+ height: 100px;
+}
+#hidden {
+ view-transition-name: hidden;
+ width: 10px;
+ height: 10px;
+ background: red;
+ contain: layout;
+}
+
+::view-transition-group(hidden) { animation-duration: 300s; }
+::view-transition-image-pair(hidden) { visibility: hidden; }
+::view-transition-group(root) { visibility: hidden; }
+::view-transition { background: pink; }
+::view-transition-group(*) { animation-delay: 300s; }
+::view-transition-new(*) { animation: unset; opacity: 1; }
+::view-transition-old(*) { animation: unset; opacity: 0; }
+</style>
+
+<div id=wrapper class=wrap_perspective><div id=target class="shared rotatex"></div></div>
+<div id=hidden></div>
+
+<script>
+failIfNot(document.startViewTransition, "Missing document.startViewTransition");
+
+function runTest() {
+ document.startViewTransition(() => {
+ wrapper.classList.toggle("wrap_perspective");
+ target.classList.toggle("rotatex");
+ target.classList.toggle("rotate3d");
+ requestAnimationFrame(() => requestAnimationFrame(takeScreenshot));
+ });
+}
+
+onload = requestAnimationFrame(() => requestAnimationFrame(runTest));
+</script>
diff --git a/testing/web-platform/tests/css/css-view-transitions/3d-transform-outgoing-ref.html b/testing/web-platform/tests/css/css-view-transitions/3d-transform-outgoing-ref.html
new file mode 100644
index 0000000000..0554cd3f4d
--- /dev/null
+++ b/testing/web-platform/tests/css/css-view-transitions/3d-transform-outgoing-ref.html
@@ -0,0 +1,21 @@
+<!DOCTYPE html>
+<title>Shared transitions: 3d transform ref</title>
+<link rel="help" href="https://github.com/WICG/view-transitions">
+<link rel="author" href="mailto:vmpstr@chromium.org">
+<style>
+div { box-sizing: border-box; will-change: transform }
+.rotate3d {
+ transform: translate(20px, 100px) rotate3d(1, 1, 1, 45deg);
+ background: green;
+}
+.shared {
+ contain: layout;
+ width: 100px;
+ height: 100px;
+}
+body { background: pink }
+
+</style>
+
+<div class="rotate3d shared"></div>
+
diff --git a/testing/web-platform/tests/css/css-view-transitions/3d-transform-outgoing.html b/testing/web-platform/tests/css/css-view-transitions/3d-transform-outgoing.html
new file mode 100644
index 0000000000..3cb29527c4
--- /dev/null
+++ b/testing/web-platform/tests/css/css-view-transitions/3d-transform-outgoing.html
@@ -0,0 +1,66 @@
+<!DOCTYPE html>
+<html class=reftest-wait>
+<title>Shared transitions: 3d transform</title>
+<link rel="help" href="https://github.com/WICG/view-transitions">
+<link rel="author" href="mailto:vmpstr@chromium.org">
+<link rel="match" href="3d-transform-outgoing-ref.html">
+<meta name=fuzzy content="3d-transform-outgoing-ref.html:0-255;0-1200">
+<script src="/common/reftest-wait.js"></script>
+
+<style>
+div { box-sizing: border-box; will-change: transform }
+.rotate3d {
+ transform: translate(20px, 100px) rotate3d(1, 1, 1, 45deg);
+ background: blue;
+}
+
+.wrap_perspective {
+ perspective: 100px;
+ width: max-content;
+ transform: translate(200px);
+}
+.rotatex {
+ transform-style: preserve-3d;
+ transform: rotateX(20deg);
+ background: green;
+}
+.shared {
+ view-transition-name: shared;
+ contain: layout;
+ width: 100px;
+ height: 100px;
+}
+#hidden {
+ view-transition-name: hidden;
+ width: 10px;
+ height: 10px;
+ background: red;
+ contain: layout;
+}
+
+::view-transition-group(hidden) { animation-duration: 300s; }
+::view-transition-image-pair(hidden) { visibility: hidden; }
+::view-transition-group(root) { visibility: hidden; }
+::view-transition { background: pink; }
+::view-transition-group(*) { animation-duration: 0s; }
+::view-transition-new(*) { animation: unset; opacity: 0; }
+::view-transition-old(*) { animation: unset; opacity: 1; }
+</style>
+
+<div id=wrapper class=wrap_perspective><div id=target class="shared rotatex"></div></div>
+<div id=hidden></div>
+
+<script>
+failIfNot(document.startViewTransition, "Missing document.startViewTransition");
+
+function runTest() {
+ document.startViewTransition(() => {
+ wrapper.classList.toggle("wrap_perspective");
+ target.classList.toggle("rotatex");
+ target.classList.toggle("rotate3d");
+ requestAnimationFrame(() => requestAnimationFrame(takeScreenshot));
+ });
+}
+
+onload = requestAnimationFrame(() => requestAnimationFrame(runTest));
+</script>
diff --git a/testing/web-platform/tests/css/css-view-transitions/break-inside-avoid-child-ref.html b/testing/web-platform/tests/css/css-view-transitions/break-inside-avoid-child-ref.html
new file mode 100644
index 0000000000..859abdfb5f
--- /dev/null
+++ b/testing/web-platform/tests/css/css-view-transitions/break-inside-avoid-child-ref.html
@@ -0,0 +1,26 @@
+<!DOCTYPE html>
+<title>View transitions: break-inside: avoid child (ref)</title>
+<link rel="help" href="https://www.w3.org/TR/css-view-transitions-1/">
+<link rel="author" href="mailto:vmpstr@chromium.org">
+
+<style>
+.columns {
+ columns: 2;
+ contain: layout;
+ border: 1px solid black;
+}
+
+.inner {
+ break-inside: avoid;
+ position: relative;
+ top: 300px;
+ left: 0;
+ background: lightblue;
+ width: 300px;
+ height: 300px;
+}
+</style>
+
+<div class="columns">
+ <div class="inner"></div>
+</div>
diff --git a/testing/web-platform/tests/css/css-view-transitions/break-inside-avoid-child.html b/testing/web-platform/tests/css/css-view-transitions/break-inside-avoid-child.html
new file mode 100644
index 0000000000..29afa0424f
--- /dev/null
+++ b/testing/web-platform/tests/css/css-view-transitions/break-inside-avoid-child.html
@@ -0,0 +1,61 @@
+<!DOCTYPE html>
+<html class=reftest-wait>
+<title>View transitions: break-inside: avoid child</title>
+<link rel="help" href="https://www.w3.org/TR/css-view-transitions-1/">
+<link rel="author" href="mailto:vmpstr@chromium.org">
+<link rel="match" href="break-inside-avoid-child-ref.html">
+<meta name="fuzzy" content="break-inside-avoid-child-ref.html:0-5;0-1600">
+<script src="/common/reftest-wait.js"></script>
+
+<style>
+.old {
+ position: relative;
+ top: 300px;
+ left: 0;
+ background: lightblue;
+}
+.new {
+ position: relative;
+ top: 0;
+ left: 0;
+ background: green;
+}
+.columns {
+ columns: 2;
+ contain: layout;
+ border: 1px solid black;
+ view-transition-name: target;
+}
+
+.inner {
+ break-inside: avoid;
+ width: 300px;
+ height: 300px;
+}
+
+html::view-transition-container(root) { animation-duration: 300s; }
+html::view-transition-old(target) {
+ animation: unset;
+ opacity: 1;
+}
+html::view-transition-new(target) {
+ animation: unset;
+ opacity: 0;
+}
+</style>
+
+<div class="columns">
+ <div id="inner" class="inner old"></div>
+</div>
+
+<script>
+function runTest() {
+ let transition = document.startViewTransition(() => {
+ inner.classList.replace("old", "new");
+ });
+ transition.ready.then(() => requestAnimationFrame(takeScreenshot));
+}
+
+onload = () => requestAnimationFrame(() => requestAnimationFrame(runTest));
+</script>
+
diff --git a/testing/web-platform/tests/css/css-view-transitions/content-object-fit-fill-ref.html b/testing/web-platform/tests/css/css-view-transitions/content-object-fit-fill-ref.html
new file mode 100644
index 0000000000..c8ba2ae154
--- /dev/null
+++ b/testing/web-platform/tests/css/css-view-transitions/content-object-fit-fill-ref.html
@@ -0,0 +1,32 @@
+<!DOCTYPE html>
+<title>Shared transitions: display content in a pseudo with object-fit: none (ref)</title>
+<link rel="help" href="https://github.com/WICG/view-transitions">
+<link rel="author" href="mailto:vmpstr@chromium.org">
+<style>
+#container {
+ width: 50px;
+ height: 50px;
+ position: absolute;
+ top: 10px;
+ left: 10px;
+ overflow: hidden;
+}
+#content {
+ background: lightblue;
+ width: 100px;
+ height: 100px;
+ transform-origin: top left;
+ transform: scale(0.5);
+}
+#inner {
+ width: 10px;
+ height: 10px;
+ background: green;
+ top: 5px;
+ left: 10px;
+}
+
+html { background: lightpink; }
+</style>
+
+<div id=container><div id=content><div id=inner></div></div></div>
diff --git a/testing/web-platform/tests/css/css-view-transitions/content-object-fit-none-ref.html b/testing/web-platform/tests/css/css-view-transitions/content-object-fit-none-ref.html
new file mode 100644
index 0000000000..61ef73f28c
--- /dev/null
+++ b/testing/web-platform/tests/css/css-view-transitions/content-object-fit-none-ref.html
@@ -0,0 +1,22 @@
+<!DOCTYPE html>
+<title>Shared transitions: display content in a pseudo with object-fit: none (ref)</title>
+<link rel="help" href="https://github.com/WICG/view-transitions">
+<link rel="author" href="mailto:vmpstr@chromium.org">
+<style>
+#container {
+ width: 50px;
+ height: 50px;
+ position: absolute;
+ top: 10px;
+ left: 10px;
+}
+#content {
+ background: lightblue;
+ width: 100px;
+ height: 100px;
+}
+
+html { background: lightpink; }
+</style>
+
+<div id=container><div id=content>This is text</div></div>
diff --git a/testing/web-platform/tests/css/css-view-transitions/content-smaller-than-box-size-ref.html b/testing/web-platform/tests/css/css-view-transitions/content-smaller-than-box-size-ref.html
new file mode 100644
index 0000000000..836f6cf3ab
--- /dev/null
+++ b/testing/web-platform/tests/css/css-view-transitions/content-smaller-than-box-size-ref.html
@@ -0,0 +1,23 @@
+<!DOCTYPE html>
+<title>Shared transitions: element with content less than box size (ref)</title>
+<link rel="help" href="https://github.com/WICG/view-transitions">
+<link rel="author" href="mailto:khushalsagar@chromium.org">
+
+<style>
+#target {
+ width: 100px;
+ height: 100px;
+}
+#inner {
+ width: 10px;
+ height: 10px;
+ background: blue;
+ position: relative;
+ top: 10px;
+ left: 10px;
+}
+</style>
+
+<div id=target>
+ <div id=inner></div>
+</div>
diff --git a/testing/web-platform/tests/css/css-view-transitions/content-smaller-than-box-size.html b/testing/web-platform/tests/css/css-view-transitions/content-smaller-than-box-size.html
new file mode 100644
index 0000000000..8cd5bc412d
--- /dev/null
+++ b/testing/web-platform/tests/css/css-view-transitions/content-smaller-than-box-size.html
@@ -0,0 +1,55 @@
+<!DOCTYPE html>
+<html class=reftest-wait>
+<title>Shared transitions: element with content less than box size</title>
+<link rel="help" href="https://github.com/WICG/view-transitions">
+<link rel="author" href="mailto:khushalsagar@chromium.org">
+<link rel="match" href="content-smaller-than-box-size-ref.html">
+
+<script src="/common/reftest-wait.js"></script>
+<style>
+div { contain: paint; }
+#target {
+ width: 100px;
+ height: 100px;
+ view-transition-name: target;
+}
+#inner {
+ width: 10px;
+ height: 10px;
+ background: blue;
+ position: relative;
+ top: 10px;
+ left: 10px;
+}
+
+.hidden {
+ background: pink;
+ width: 10px;
+ height: 10px;
+ view-transition-name: hidden;
+}
+
+html::view-transition-group(hidden) { animation-duration: 300s; }
+html::view-transition-image-pair(hidden) { animation: unset; opacity: 0; }
+
+html::view-transition-new(target) { animation: unset; opacity: 0; }
+html::view-transition-old(target) { animation: unset; opacity: 1; }
+
+</style>
+
+<div id=target>
+ <div id=inner></div>
+</div>
+<div id=hidden class=hidden></div>
+
+<script>
+failIfNot(document.startViewTransition, "Missing document.startViewTransition");
+
+async function runTest() {
+ document.startViewTransition(() => {
+ requestAnimationFrame(takeScreenshot);
+ });
+}
+onload = () => requestAnimationFrame(runTest);
+</script>
+
diff --git a/testing/web-platform/tests/css/css-view-transitions/content-visibility-auto-shared-element-ref.html b/testing/web-platform/tests/css/css-view-transitions/content-visibility-auto-shared-element-ref.html
new file mode 100644
index 0000000000..36e07d4167
--- /dev/null
+++ b/testing/web-platform/tests/css/css-view-transitions/content-visibility-auto-shared-element-ref.html
@@ -0,0 +1,31 @@
+<!DOCTYPE html>
+<html>
+<title>Shared transitions: offscreen content</title>
+<link rel="help" href="https://github.com/WICG/view-transitions">
+<link rel="author" href="mailto:vmpstr@chromium.org">
+<style>
+body { background: pink }
+.flex {
+ display: flex;
+ flex-direction: row;
+ justify-content: flex-start;
+ align-items: flex-start;
+}
+.box {
+ width: 100px;
+ height: 500px;
+ contain: paint;
+ background: green;
+ border: 1px solid black;
+ box-sizing: border-box;
+}
+.hidden {
+ visibility: hidden;
+}
+</style>
+
+<div class=flex>
+ <div class="box hidden">ancestor c-v</div>
+ <div class=box>self c-v</div>
+ <div class=box>descendant c-v</div>
+</div>
diff --git a/testing/web-platform/tests/css/css-view-transitions/content-visibility-auto-shared-element.html b/testing/web-platform/tests/css/css-view-transitions/content-visibility-auto-shared-element.html
new file mode 100644
index 0000000000..b678f485f6
--- /dev/null
+++ b/testing/web-platform/tests/css/css-view-transitions/content-visibility-auto-shared-element.html
@@ -0,0 +1,81 @@
+<!DOCTYPE html>
+<html class=reftest-wait>
+<title>Shared transitions: offscreen content with content-visibility auto</title>
+<link rel="help" href="https://github.com/WICG/view-transitions">
+<link rel="author" href="mailto:vmpstr@chromium.org">
+<link rel="match" href="content-visibility-auto-shared-element-ref.html">
+<script src="/common/reftest-wait.js"></script>
+<style>
+body {
+ overflow: hidden;
+}
+.flex {
+ display: flex;
+ flex-direction: row;
+ justify-content: flex-start;
+ align-items: flex-start;
+}
+.box {
+ width: 100px;
+ height: 500px;
+ contain: paint;
+}
+.shared {
+ background: green;
+ border: 1px solid black;
+ box-sizing: border-box;
+}
+.spacer {
+ height: 3000px;
+}
+#hidden {
+ width: 10px;
+ height: 10px;
+ background: red;
+ contain: paint;
+ view-transition-name: hidden;
+}
+.locked {
+ content-visibility: auto;
+ contain-intrinsic-size: 500px;
+}
+
+html::view-transition-group(hidden) { animation-duration: 300s; }
+html::view-transition-image-pair(hidden) { visibility: hidden; }
+
+html::view-transition-group(*) { animation-duration: 0s; }
+html::view-transition-new(*) { animation: unset; opacity: 0; }
+html::view-transition-old(*) { animation: unset; opacity: 1; }
+html::view-transition-group(root) { display: none; }
+html::view-transition { background: pink }
+
+</style>
+
+<div class=flex>
+ <div id=dst1 class=box></div>
+ <div id=dst2 class=box></div>
+ <div id=dst3 class=box></div>
+</div>
+<div id=hidden></div>
+<div class=spacer></div>
+<div id=content>
+ <div id=lockme><div id=src1 class="box shared" style="view-transition-name: one">ancestor c-v</div></div>
+ <div id=src2 class="box shared locked" style="view-transition-name: two">self c-v</div>
+ <div id=src3 class="box shared" style="view-transition-name: three"><div class=locked>descendant c-v</div></div>
+</div>
+
+<script>
+failIfNot(document.startViewTransition, "Missing document.startViewTransition");
+
+async function runTest() {
+ lockme.classList.add("locked");
+ document.startViewTransition(() => {
+ content.remove();
+ dst1.style = "view-transition-name: one";
+ dst2.style = "view-transition-name: two";
+ dst3.style = "view-transition-name: three";
+ requestAnimationFrame(() => requestAnimationFrame(takeScreenshot));
+ });
+}
+onload = () => requestAnimationFrame(() => requestAnimationFrame(runTest));
+</script>
diff --git a/testing/web-platform/tests/css/css-view-transitions/content-with-clip-max-texture-size-ref.html b/testing/web-platform/tests/css/css-view-transitions/content-with-clip-max-texture-size-ref.html
new file mode 100644
index 0000000000..3c66ddbfe7
--- /dev/null
+++ b/testing/web-platform/tests/css/css-view-transitions/content-with-clip-max-texture-size-ref.html
@@ -0,0 +1,41 @@
+<!DOCTYPE html>
+<title>Shared transitions: element with clip max texture size (ref)</title>
+<link rel="help" href="https://github.com/WICG/view-transitions">
+<link rel="author" href="mailto:khushalsagar@chromium.org">
+<style>
+.target {
+ contain: paint;
+ width: 100px;
+ height: 8000px;
+}
+
+.green {
+ width: 100%;
+ height: 7900px;
+ background: green
+}
+
+.blue {
+ width: 100%;
+ height: 100px;
+ background: blue;
+}
+
+.hidden {
+ contain: paint;
+ width: 10px;
+ height: 10px;
+ background: grey;
+ visibility: hidden;
+}
+</style>
+<body>
+<div id="target1" class="target">
+ <div class="green"></div>
+ <div id="scrollblue" class="blue"></div>
+</div>
+<div id=hidden class=hidden></div>
+</body>
+<script>
+ scrollblue.scrollIntoView();
+</script>
diff --git a/testing/web-platform/tests/css/css-view-transitions/content-with-clip-max-texture-size.html b/testing/web-platform/tests/css/css-view-transitions/content-with-clip-max-texture-size.html
new file mode 100644
index 0000000000..b1c9638281
--- /dev/null
+++ b/testing/web-platform/tests/css/css-view-transitions/content-with-clip-max-texture-size.html
@@ -0,0 +1,70 @@
+<!DOCTYPE html>
+<html class=reftest-wait>
+<title>Shared transitions: element with clip max texture size</title>
+<link rel="help" href="https://github.com/WICG/view-transitions">
+<link rel="author" href="mailto:khushalsagar@chromium.org">
+<link rel="match" href="content-with-clip-max-texture-size-ref.html">
+<meta name=fuzzy content="maxDifference=10;totalPixels=200">
+
+<script src="/common/reftest-wait.js"></script>
+<style>
+.target {
+ contain: paint;
+ width: 100px;
+ height: 8000px;
+}
+
+.green {
+ width: 100%;
+ height: 7900px;
+ background: green
+}
+
+.blue {
+ width: 100%;
+ height: 100px;
+ background: blue;
+}
+
+.hidden {
+ contain: paint;
+ width: 10px;
+ height: 10px;
+ background: grey;
+ view-transition-name: hidden;
+}
+#target1 { view-transition-name: target1; }
+
+html::view-transition-group(hidden) { animation-duration: 300s; }
+html::view-transition-image-pair(hidden) { animation: unset; opacity: 0; }
+
+html::view-transition-old(*), html::view-transition-new(*) {
+ object-fit: none;
+}
+
+html::view-transition-old(target1) { animation: unset; opacity: 0; }
+html::view-transition-new(target1) { animation: unset; opacity: 1; }
+
+</style>
+
+<div id="target1" class="target">
+ <div class="green"></div>
+ <div id="scrollblue" class="blue"></div>
+</div>
+<div id=hidden class=hidden></div>
+
+<script>
+failIfNot(document.startViewTransition, "Missing document.startViewTransition");
+
+async function runTest() {
+ scrollblue.scrollIntoView();
+
+ document.startViewTransition(() => {
+ requestAnimationFrame(() => requestAnimationFrame(() =>
+ requestAnimationFrame(() => requestAnimationFrame(takeScreenshot))
+ ));
+ });
+}
+onload = () => requestAnimationFrame(() => requestAnimationFrame(runTest));
+</script>
+
diff --git a/testing/web-platform/tests/css/css-view-transitions/content-with-clip-ref.html b/testing/web-platform/tests/css/css-view-transitions/content-with-clip-ref.html
new file mode 100644
index 0000000000..b265afabc5
--- /dev/null
+++ b/testing/web-platform/tests/css/css-view-transitions/content-with-clip-ref.html
@@ -0,0 +1,30 @@
+<!DOCTYPE html>
+<title>Shared transitions: element with clip (ref)</title>
+<link rel="help" href="https://github.com/WICG/view-transitions">
+<link rel="author" href="mailto:vmpstr@chromium.org">
+<style>
+.target {
+ contain: paint;
+ width: 100px;
+ height: 100vh;
+ display: inline-block;
+}
+
+.embedded {
+ width: 100%;
+ height: 50%;
+}
+
+body {
+ height: 150vh;
+}
+</style>
+<div id="target1" class="target">
+ <div class="embedded" style="background: green;"></div>
+ <div class="embedded" style="background: blue"></div>
+</div>
+<div id="target2" class="target">
+ <div class="embedded" style="background: green;"></div>
+ <div class="embedded" style="background: blue"></div>
+</div>
+
diff --git a/testing/web-platform/tests/css/css-view-transitions/content-with-clip-root-ref.html b/testing/web-platform/tests/css/css-view-transitions/content-with-clip-root-ref.html
new file mode 100644
index 0000000000..1da6940c90
--- /dev/null
+++ b/testing/web-platform/tests/css/css-view-transitions/content-with-clip-root-ref.html
@@ -0,0 +1,36 @@
+<!DOCTYPE html>
+<title>Shared transitions: element with clip (ref)</title>
+<link rel="help" href="https://github.com/WICG/view-transitions">
+<link rel="author" href="mailto:vmpstr@chromium.org">
+<style>
+.container {
+ width: 100vw;
+ height: 100vh;
+ position: fixed;
+ top: -50vh;
+ left: 0px;
+ overflow: auto;
+}
+.target {
+ contain: paint;
+ width: 100px;
+ height: 100vh;
+ display: inline-block;
+}
+
+.embedded {
+ width: 100%;
+ height: 50%;
+}
+
+body {
+ margin: 0px;
+ height: 150vh;
+}
+</style>
+<div id="container">
+<div id="target1" class="target">
+ <div class="embedded" style="background: green;"></div>
+</div>
+</div>
+
diff --git a/testing/web-platform/tests/css/css-view-transitions/content-with-clip-root.html b/testing/web-platform/tests/css/css-view-transitions/content-with-clip-root.html
new file mode 100644
index 0000000000..805610bb07
--- /dev/null
+++ b/testing/web-platform/tests/css/css-view-transitions/content-with-clip-root.html
@@ -0,0 +1,79 @@
+<!DOCTYPE html>
+<html class=reftest-wait>
+<title>Shared transitions: root element with clip</title>
+<link rel="help" href="https://github.com/WICG/view-transitions">
+<link rel="author" href="mailto:khushalsagar@chromium.org">
+<link rel="match" href="content-with-clip-root-ref.html">
+
+<script src="/common/reftest-wait.js"></script>
+<style>
+.target {
+ contain: paint;
+ width: 100px;
+ height: 100vh;
+ position: relative;
+ top: 50vh;
+ display: inline-block;
+}
+
+.embedded {
+ width: 100%;
+ height: 50%;
+}
+
+.hidden {
+ contain: paint;
+ width: 10px;
+ height: 10px;
+ background: grey;
+ view-transition-name: hidden;
+}
+
+body {
+ margin: 0px;
+}
+
+html::view-transition-group(hidden) { animation-duration: 300s; }
+html::view-transition-image-pair(hidden) { animation: unset; opacity: 0; }
+
+html::view-transition-group(target2) {
+ opacity: 0;
+}
+
+html::view-transition-group(root) {
+ top: -50vh;
+ bottom: 50vh;
+}
+
+html::view-transition-old(root) { animation: unset; opacity: 0; height: 100%; }
+html::view-transition-new(root) { animation: unset; opacity: 1; height: 100%; }
+
+</style>
+
+<div id="target1" class="target">
+ <div class="embedded" style="background: green;"></div>
+ <div class="embedded" style="background: blue"></div>
+</div>
+<div id="target2" class="target">
+ <div class="embedded" style="background: green;"></div>
+ <div class="embedded" style="background: blue"></div>
+</div>
+<div id=hidden class=hidden></div>
+
+<script>
+failIfNot(document.startViewTransition, "Missing document.startViewTransition");
+
+async function runTest() {
+ document.startViewTransition(() => {
+ // Add a shared element to ensure its bounds don't expand the root snapshot
+ // size.
+ target2.style = "view-transition-name: target2";
+
+ requestAnimationFrame(() => requestAnimationFrame(() =>
+ requestAnimationFrame(() => requestAnimationFrame(takeScreenshot))
+ ));
+ });
+}
+onload = () => requestAnimationFrame(() => requestAnimationFrame(runTest));
+</script>
+
diff --git a/testing/web-platform/tests/css/css-view-transitions/content-with-clip.html b/testing/web-platform/tests/css/css-view-transitions/content-with-clip.html
new file mode 100644
index 0000000000..7354125b30
--- /dev/null
+++ b/testing/web-platform/tests/css/css-view-transitions/content-with-clip.html
@@ -0,0 +1,73 @@
+<!DOCTYPE html>
+<html class=reftest-wait>
+<title>Shared transitions: element with clip</title>
+<link rel="help" href="https://github.com/WICG/view-transitions">
+<link rel="author" href="mailto:khushalsagar@chromium.org">
+<link rel="match" href="content-with-clip-ref.html">
+
+<script src="/common/reftest-wait.js"></script>
+<style>
+.target {
+ contain: paint;
+ width: 100px;
+ height: 100vh;
+ position: relative;
+ top: 50vh;
+ display: inline-block;
+}
+
+.embedded {
+ width: 100%;
+ height: 50%;
+}
+
+.hidden {
+ contain: paint;
+ width: 10px;
+ height: 10px;
+ background: grey;
+ view-transition-name: hidden;
+}
+
+/* Makes sure the viewport height is consistent for scrollbars to align */
+body {
+ height: 150vh;
+}
+
+html::view-transition-group(hidden) { animation-duration: 300s; }
+html::view-transition-image-pair(hidden) { animation: unset; opacity: 0; }
+
+html::view-transition-group(target1), html::view-transition-group(target2) {
+ position: absolute;
+ top: -50vh;
+}
+html::view-transition-old(target1) { animation: unset; opacity: 1; }
+html::view-transition-new(target2) { animation: unset; opacity: 1; }
+
+</style>
+
+<div id="target1" class="target" style="view-transition-name: target1">
+ <div class="embedded" style="background: green;"></div>
+ <div class="embedded" style="background: blue"></div>
+</div>
+<div id="target2" class="target">
+ <div class="embedded" style="background: green;"></div>
+ <div class="embedded" style="background: blue"></div>
+</div>
+<div id=hidden class=hidden></div>
+
+<script>
+failIfNot(document.startViewTransition, "Missing document.startViewTransition");
+
+async function runTest() {
+ document.startViewTransition(() => {
+ target1.style = "";
+ target2.style = "view-transition-name: target2";
+ requestAnimationFrame(() => requestAnimationFrame(() =>
+ requestAnimationFrame(() => requestAnimationFrame(takeScreenshot))
+ ));
+ });
+}
+onload = () => requestAnimationFrame(() => requestAnimationFrame(runTest));
+</script>
+
diff --git a/testing/web-platform/tests/css/css-view-transitions/content-with-inline-child-ref.html b/testing/web-platform/tests/css/css-view-transitions/content-with-inline-child-ref.html
new file mode 100644
index 0000000000..a805aac64b
--- /dev/null
+++ b/testing/web-platform/tests/css/css-view-transitions/content-with-inline-child-ref.html
@@ -0,0 +1,32 @@
+<!DOCTYPE html>
+<title>Shared transitions: element with inline child (ref)</title>
+<link rel="help" href="https://github.com/WICG/view-transitions">
+<link rel="stylesheet" href="/fonts/ahem.css">
+<link rel="author" href="mailto:bokan@chromium.org">
+<style>
+#target {
+ width: 100px;
+ height: 100px;
+ overflow-clip-margin: 500px;
+ contain: paint;
+ view-transition-name: target;
+ background-color: grey;
+}
+
+#child {
+ position: relative;
+ left: 100px;
+ top: 100px;
+ color: lightgreen;
+ background-color: darkgreen;
+}
+
+#innerchild {
+ position: relative;
+ left: 100px;
+}
+</style>
+
+<div id="target" style="font: 25px/1 Ahem">
+ <span id="child">INLINE<br><span id="innerchild">BOX</span></span>
+</div>
diff --git a/testing/web-platform/tests/css/css-view-transitions/content-with-inline-child.html b/testing/web-platform/tests/css/css-view-transitions/content-with-inline-child.html
new file mode 100644
index 0000000000..6bae020b8d
--- /dev/null
+++ b/testing/web-platform/tests/css/css-view-transitions/content-with-inline-child.html
@@ -0,0 +1,71 @@
+<!DOCTYPE html>
+<html class=reftest-wait>
+<title>Shared transitions: element with inline child</title>
+<link rel="help" href="https://github.com/WICG/view-transitions">
+<link rel="stylesheet" href="/fonts/ahem.css">
+<link rel="author" href="mailto:bokan@chromium.org">
+<link rel="match" href="content-with-inline-child-ref.html">
+<meta name="flags" content="ahem">
+
+<script src="/common/reftest-wait.js"></script>
+<style>
+
+#target {
+ width: 100px;
+ height: 100px;
+ overflow-clip-margin: 500px;
+ contain: paint;
+ view-transition-name: target;
+ background-color: grey;
+}
+
+#child {
+ position: relative;
+ left: 100px;
+ top: 100px;
+ color: lightgreen;
+ background-color: darkgreen;
+}
+
+#innerchild {
+ position: relative;
+ left: 100px;
+}
+
+html::view-transition-new(root) {
+ opacity: 0;
+}
+html::view-transition-old(root) {
+ opacity: 0;
+}
+
+html::view-transition-old(target) {
+ animation-duration: 3s;
+ animation-timing-function: steps(1, end);
+ opacity: 1;
+}
+html::view-transition-new(target) { animation: unset; opacity: 0; }
+
+</style>
+
+<div id="target" style="font: 25px/1 Ahem">
+ <span id="child">INLINE<br><span id="innerchild">BOX</span></span>
+</div>
+
+<script>
+failIfNot(document.startViewTransition, "Missing document.startViewTransition");
+
+async function runTest() {
+ document.startViewTransition(() => {
+ // Remove the target to ensure the ref is compared against the snapshot.
+ document.getElementById("target").remove();
+
+ requestAnimationFrame(
+ () => requestAnimationFrame(
+ () => requestAnimationFrame(
+ () => requestAnimationFrame(takeScreenshot))));
+ });
+}
+onload = () => requestAnimationFrame(() => requestAnimationFrame(runTest));
+</script>
+
diff --git a/testing/web-platform/tests/css/css-view-transitions/content-with-overflow-ref.html b/testing/web-platform/tests/css/css-view-transitions/content-with-overflow-ref.html
new file mode 100644
index 0000000000..62282bd326
--- /dev/null
+++ b/testing/web-platform/tests/css/css-view-transitions/content-with-overflow-ref.html
@@ -0,0 +1,28 @@
+<!DOCTYPE html>
+<title>Shared transitions: shared element with overflow (ref)</title>
+<link rel="help" href="https://github.com/WICG/view-transitions">
+<link rel="author" href="mailto:khushalsagar@chromium.org">
+<style>
+.target {
+ width: 100px;
+ height: 100px;
+ contain: paint;
+ background: blue;
+ overflow-clip-margin: 50px;
+ view-transition-name: target;
+}
+.child {
+ width: 200px;
+ height: 200px;
+ position: relative;
+ top: 50px;
+ left: 50px;
+ background: green;
+}
+body { background: lightpink; }
+</style>
+
+<div class=target>
+ <div class=child>
+ </div>
+</div>
diff --git a/testing/web-platform/tests/css/css-view-transitions/content-with-overflow-zoomed-ref.html b/testing/web-platform/tests/css/css-view-transitions/content-with-overflow-zoomed-ref.html
new file mode 100644
index 0000000000..a55fa30937
--- /dev/null
+++ b/testing/web-platform/tests/css/css-view-transitions/content-with-overflow-zoomed-ref.html
@@ -0,0 +1,33 @@
+<!DOCTYPE html>
+<title>Shared transitions: shared element with overflow (ref)</title>
+<link rel="help" href="https://github.com/WICG/view-transitions">
+<link rel="author" href="mailto:khushalsagar@chromium.org">
+<style>
+.target {
+ width: 80px;
+ height: 80px;
+ contain: paint;
+ background: blue;
+ overflow-clip-margin: 50px;
+ view-transition-name: target;
+ zoom: 1.5;
+ border: 2px solid black;
+}
+.child {
+ width: 200px;
+ height: 200px;
+ position: relative;
+ top: 50px;
+ left: 50px;
+ background: green;
+ zoom: 1.2;
+}
+body { background: lightpink; }
+</style>
+
+<div class=ancestor>
+ <div class=target>
+ <div class=child>
+ </div>
+ </div>
+</div>
diff --git a/testing/web-platform/tests/css/css-view-transitions/content-with-transform-new-image.html b/testing/web-platform/tests/css/css-view-transitions/content-with-transform-new-image.html
new file mode 100644
index 0000000000..f459742cd0
--- /dev/null
+++ b/testing/web-platform/tests/css/css-view-transitions/content-with-transform-new-image.html
@@ -0,0 +1,59 @@
+<!DOCTYPE html>
+<html class=reftest-wait>
+<title>Shared transitions: object-view-box</title>
+<link rel="help" href="https://github.com/WICG/view-transitions">
+<link rel="author" href="mailto:khushalsagar@chromium.org">
+<link rel="match" href="content-with-transform-ref.html">
+<meta name="fuzzy" content="content-with-transform-ref.html:0-1;0-500">
+
+<script src="/common/reftest-wait.js"></script>
+<style>
+.target {
+ contain: paint;
+ width: 100px;
+ height: 100px;
+ transform: scale(2.0, 3.0);
+ view-transition-name: target;
+}
+
+.embedded {
+ width: 100px;
+ height: 50px;
+}
+
+.hidden {
+ contain: paint;
+ width: 10px;
+ height: 10px;
+ background: grey;
+ view-transition-name: hidden;
+}
+
+html::view-transition-group(hidden) { animation-duration: 300s; }
+html::view-transition-image-pair(hidden) { animation: unset; opacity: 0; }
+
+html::view-transition-new(target) {
+ animation: unset;
+ opacity: 1;
+}
+html::view-transition-old(target) { animation: unset; opacity: 0; }
+
+</style>
+
+<div id="target" class="target">
+ <div class="embedded" style="background: green;">Shared</div>
+ <div class="embedded" style="background: blue">Element</div>
+</div>
+<div id=hidden class=hidden></div>
+
+<script>
+failIfNot(document.startViewTransition, "Missing document.startViewTransition");
+
+async function runTest() {
+ let t = document.startViewTransition(() => {
+ requestAnimationFrame(() => requestAnimationFrame(takeScreenshot));
+ });
+}
+onload = () => requestAnimationFrame(runTest);
+</script>
+
diff --git a/testing/web-platform/tests/css/css-view-transitions/content-with-transform-old-image.html b/testing/web-platform/tests/css/css-view-transitions/content-with-transform-old-image.html
new file mode 100644
index 0000000000..a31a2745a6
--- /dev/null
+++ b/testing/web-platform/tests/css/css-view-transitions/content-with-transform-old-image.html
@@ -0,0 +1,60 @@
+<!DOCTYPE html>
+<meta name="timeout" content="long">
+<html class=reftest-wait>
+<title>Shared transitions: object-view-box</title>
+<link rel="help" href="https://github.com/WICG/view-transitions">
+<link rel="author" href="mailto:khushalsagar@chromium.org">
+<link rel="match" href="content-with-transform-ref.html">
+<meta name="fuzzy" content="content-with-transform-ref.html:0-1;0-400">
+
+<script src="/common/reftest-wait.js"></script>
+<style>
+.target {
+ contain: paint;
+ width: 100px;
+ height: 100px;
+ transform: scale(2.0, 3.0);
+ view-transition-name: target;
+}
+
+.embedded {
+ width: 100px;
+ height: 50px;
+}
+
+.hidden {
+ contain: paint;
+ width: 10px;
+ height: 10px;
+ background: grey;
+ view-transition-name: hidden;
+}
+
+html::view-transition-group(hidden) { animation-duration: 300s; }
+html::view-transition-image-pair(hidden) { animation: unset; opacity: 0; }
+
+html::view-transition-old(target) {
+ animation: unset;
+ opacity: 1;
+}
+html::view-transition-new(target) { animation: unset; opacity: 0; }
+
+</style>
+
+<div id="target" class="target">
+ <div class="embedded" style="background: green;">Shared</div>
+ <div class="embedded" style="background: blue">Element</div>
+</div>
+<div id=hidden class=hidden></div>
+
+<script>
+failIfNot(document.startViewTransition, "Missing document.startViewTransition");
+
+async function runTest() {
+ document.startViewTransition(() => {
+ requestAnimationFrame(() => requestAnimationFrame(takeScreenshot));
+ });
+}
+onload = () => requestAnimationFrame(runTest);
+</script>
+
diff --git a/testing/web-platform/tests/css/css-view-transitions/content-with-transform-ref.html b/testing/web-platform/tests/css/css-view-transitions/content-with-transform-ref.html
new file mode 100644
index 0000000000..629c8f0cc9
--- /dev/null
+++ b/testing/web-platform/tests/css/css-view-transitions/content-with-transform-ref.html
@@ -0,0 +1,24 @@
+<!DOCTYPE html>
+<title>Shared transitions: object-view-box (ref)</title>
+<link rel="help" href="https://github.com/WICG/view-transitions">
+<link rel="author" href="mailto:vmpstr@chromium.org">
+<style>
+.target {
+ contain: paint;
+ width: 100px;
+ height: 100px;
+ transform: scale(2.0, 3.0);
+}
+
+.embedded {
+ width: 100px;
+ height: 50px;
+}
+
+</style>
+<div id="target" class="target">
+ <div class="embedded" style="background: green;">Shared</div>
+ <div class="embedded" style="background: blue">Element</div>
+</div>
+</div>
+
diff --git a/testing/web-platform/tests/css/css-view-transitions/css-tags-paint-order-ref.html b/testing/web-platform/tests/css/css-view-transitions/css-tags-paint-order-ref.html
new file mode 100644
index 0000000000..98f26c06df
--- /dev/null
+++ b/testing/web-platform/tests/css/css-view-transitions/css-tags-paint-order-ref.html
@@ -0,0 +1,34 @@
+<!DOCTYPE html>
+<title>Shared transitions: css tags generate pseudo elements in paint order (ref)</title>
+<link rel="help" href="https://github.com/WICG/view-transitions">
+<link rel="author" href="mailto:vmpstr@chromium.org">
+
+<style>
+div {
+ contain: layout;
+ position: absolute;
+ top: 50px;
+ width: 100px;
+ height: 100px;
+}
+#one {
+ background: green;
+ left: 50px;
+ z-index: 1;
+}
+#two {
+ background: yellow;
+ left: 125px;
+ z-index: -1;
+}
+#three {
+ background: blue;
+ left: 200px;
+ z-index: 0;
+}
+body { background: lightpink; }
+</style>
+
+<div id=one></div>
+<div id=two></div>
+<div id=three></div>
diff --git a/testing/web-platform/tests/css/css-view-transitions/css-tags-paint-order-with-entry-ref.html b/testing/web-platform/tests/css/css-view-transitions/css-tags-paint-order-with-entry-ref.html
new file mode 100644
index 0000000000..6a50ecbebf
--- /dev/null
+++ b/testing/web-platform/tests/css/css-view-transitions/css-tags-paint-order-with-entry-ref.html
@@ -0,0 +1,40 @@
+<!DOCTYPE html>
+<title>Shared transitions: css tags generate pseudo elements in paint order (ref)</title>
+<link rel="help" href="https://github.com/WICG/view-transitions">
+<link rel="author" href="mailto:vmpstr@chromium.org">
+
+<style>
+div {
+ contain: paint;
+ position: absolute;
+ top: 50px;
+ width: 100px;
+ height: 100px;
+}
+#one {
+ background: green;
+ left: 50px;
+ z-index: 1;
+}
+#two {
+ background: yellow;
+ left: 125px;
+ z-index: -1;
+}
+#three {
+ background: blue;
+ left: 200px;
+ z-index: 0;
+}
+#four {
+ background: lightgreen;
+ left: 275px;
+ z-index: 0;
+}
+body { background: lightpink; }
+</style>
+
+<div id=one></div>
+<div id=two></div>
+<div id=three></div>
+<div id=four></div>
diff --git a/testing/web-platform/tests/css/css-view-transitions/css-tags-paint-order-with-entry.html b/testing/web-platform/tests/css/css-view-transitions/css-tags-paint-order-with-entry.html
new file mode 100644
index 0000000000..9f79ba25e0
--- /dev/null
+++ b/testing/web-platform/tests/css/css-view-transitions/css-tags-paint-order-with-entry.html
@@ -0,0 +1,111 @@
+<!DOCTYPE html>
+<html class=reftest-wait>
+<title>Shared transitions: css tags generate pseudo elements in paint order</title>
+<link rel="help" href="https://github.com/WICG/view-transitions">
+<link rel="author" href="mailto:vmpstr@chromium.org">
+<link rel="match" href="css-tags-paint-order-with-entry-ref.html">
+<meta name="fuzzy" content="css-tags-paint-order-with-entry-ref.html:0-120;0-300">
+
+<script src="/common/reftest-wait.js"></script>
+<style>
+div { contain: paint; }
+#one {
+ background: green;
+ width: 100px;
+ height: 100px;
+ position: relative;
+ z-index: 1;
+ view-transition-name: one;
+}
+#two {
+ background: yellow;
+ width: 100px;
+ height: 100px;
+ view-transition-name: two;
+}
+#three {
+ background: blue;
+ width: 100px;
+ height: 100px;
+ view-transition-name: three;
+}
+#four {
+ position: absolute;
+ background: lightgreen;
+ width: 100px;
+ height: 100px;
+ top: 50px;
+ left: 275px;
+ view-transition-name: four;
+}
+
+.hidden {
+ background: pink;
+ width: 10px;
+ height: 10px;
+ view-transition-name: hidden;
+}
+
+html::view-transition-group(hidden) { animation-duration: 300s; }
+html::view-transition-image-pair(hidden) { animation: unset; opacity: 0; }
+
+html::view-transition-group(one) {
+ animation: unset;
+ transform: unset;
+ position: absolute;
+ top: 50px;
+ left: 50px;
+}
+html::view-transition-group(two) {
+ animation: unset;
+ transform: unset;
+ position: absolute;
+ top: 50px;
+ left: 125px;
+}
+html::view-transition-group(three) {
+ animation: unset;
+ transform: unset;
+ position: absolute;
+ top: 50px;
+ left: 200px;
+}
+html::view-transition-new(four) {
+ animation: unset;
+ opacity: 1;
+}
+
+html::view-transition-new(one),
+html::view-transition-new(two),
+html::view-transition-new(three) { animation: unset; opacity: 0; }
+
+html::view-transition-old(one),
+html::view-transition-old(two),
+html::view-transition-old(three) { animation: unset; opacity: 1; }
+
+html::view-transition-group(root) { animation: unset; opacity: 0; }
+html::view-transition { background: lightpink; }
+
+</style>
+
+<div id=one></div>
+<div id=two></div>
+<div id=three></div>
+
+<div id=hidden class=hidden></div>
+
+<script>
+failIfNot(document.startViewTransition, "Missing document.startViewTransition");
+
+async function runTest() {
+ document.startViewTransition(() => {
+ const f = document.createElement("div");
+ f.id = "four";
+ document.body.appendChild(f);
+
+ requestAnimationFrame(() => requestAnimationFrame(takeScreenshot));
+ });
+}
+onload = () => requestAnimationFrame(() => requestAnimationFrame(runTest));
+</script>
+
diff --git a/testing/web-platform/tests/css/css-view-transitions/css-tags-paint-order.html b/testing/web-platform/tests/css/css-view-transitions/css-tags-paint-order.html
new file mode 100644
index 0000000000..2f71a701ee
--- /dev/null
+++ b/testing/web-platform/tests/css/css-view-transitions/css-tags-paint-order.html
@@ -0,0 +1,93 @@
+<!DOCTYPE html>
+<html class=reftest-wait>
+<title>Shared transitions: css tags generate pseudo elements in paint order</title>
+<link rel="help" href="https://github.com/WICG/view-transitions">
+<link rel="author" href="mailto:vmpstr@chromium.org">
+<link rel="match" href="css-tags-paint-order-ref.html">
+
+<script src="/common/reftest-wait.js"></script>
+<style>
+div { contain: layout; }
+#one {
+ background: green;
+ width: 100px;
+ height: 100px;
+ position: relative;
+ z-index: 1;
+ view-transition-name: one;
+}
+#two {
+ background: yellow;
+ width: 100px;
+ height: 100px;
+ view-transition-name: two;
+}
+#three {
+ background: blue;
+ width: 100px;
+ height: 100px;
+ view-transition-name: three;
+}
+
+.hidden {
+ background: pink;
+ width: 10px;
+ height: 10px;
+ view-transition-name: hidden;
+}
+
+html::view-transition-group(hidden) { animation-duration: 300s; }
+html::view-transition-image-pair(hidden) { animation: unset; opacity: 0; }
+
+html::view-transition-group(one) {
+ animation: unset;
+ transform: unset;
+ position: absolute;
+ top: 50px;
+ left: 50px;
+}
+html::view-transition-group(two) {
+ animation: unset;
+ transform: unset;
+ position: absolute;
+ top: 50px;
+ left: 125px;
+}
+html::view-transition-group(three) {
+ animation: unset;
+ transform: unset;
+ position: absolute;
+ top: 50px;
+ left: 200px;
+}
+
+html::view-transition-new(one),
+html::view-transition-new(two),
+html::view-transition-new(three) { animation: unset; opacity: 0; }
+
+html::view-transition-old(one),
+html::view-transition-old(two),
+html::view-transition-old(three) { animation: unset; opacity: 1; }
+
+html::view-transition-group(root) { animation: unset; opacity: 0; }
+html::view-transition { background: lightpink; }
+
+</style>
+
+<div id=one></div>
+<div id=two></div>
+<div id=three></div>
+
+<div id=hidden class=hidden></div>
+
+<script>
+failIfNot(document.startViewTransition, "Missing document.startViewTransition");
+
+async function runTest() {
+ document.startViewTransition(() => {
+ requestAnimationFrame(() => requestAnimationFrame(takeScreenshot));
+ });
+}
+onload = () => requestAnimationFrame(() => requestAnimationFrame(runTest));
+</script>
+
diff --git a/testing/web-platform/tests/css/css-view-transitions/css-tags-shared-element-ref.html b/testing/web-platform/tests/css/css-view-transitions/css-tags-shared-element-ref.html
new file mode 100644
index 0000000000..659d1d5278
--- /dev/null
+++ b/testing/web-platform/tests/css/css-view-transitions/css-tags-shared-element-ref.html
@@ -0,0 +1,28 @@
+<!DOCTYPE html>
+<title>Shared transitions: use css tags for shared elements (ref)</title>
+<link rel="help" href="https://github.com/WICG/view-transitions">
+<link rel="author" href="mailto:vmpstr@chromium.org">
+
+<style>
+div { contain: paint; }
+#left {
+ background: blue;
+ width: 100px;
+ height: 100px;
+ position: absolute;
+ top: 50px;
+ left: 50px;
+}
+#right {
+ width: 50px;
+ height: 50px;
+ background: green;
+ position: absolute;
+ top: 50px;
+ left: 250px;
+}
+body { background: lightpink; }
+</style>
+
+<div id=left></div>
+<div id=right></div>
diff --git a/testing/web-platform/tests/css/css-view-transitions/css-tags-shared-element.html b/testing/web-platform/tests/css/css-view-transitions/css-tags-shared-element.html
new file mode 100644
index 0000000000..fad0d3763d
--- /dev/null
+++ b/testing/web-platform/tests/css/css-view-transitions/css-tags-shared-element.html
@@ -0,0 +1,79 @@
+<!DOCTYPE html>
+<html class=reftest-wait>
+<title>Shared transitions: use css tags for shared elements</title>
+<link rel="help" href="https://github.com/WICG/view-transitions">
+<link rel="author" href="mailto:vmpstr@chromium.org">
+<link rel="match" href="css-tags-shared-element-ref.html">
+
+<script src="/common/reftest-wait.js"></script>
+<style>
+div { contain: paint; }
+#left {
+ background: green;
+ width: 100px;
+ height: 100px;
+ position: absolute;
+ top: 50px;
+ left: 50px;
+}
+#right {
+ width: 50px;
+ height: 50px;
+ background: blue;
+ position: absolute;
+ top: 50px;
+ left: 250px;
+}
+.left-tag {
+ view-transition-name: left-element;
+}
+.right-tag {
+ view-transition-name: right-element;
+}
+
+.hidden {
+ background: pink;
+ width: 10px;
+ height: 10px;
+ view-transition-name: hidden;
+}
+
+html::view-transition-group(hidden) { animation-duration: 300s; }
+html::view-transition-image-pair(hidden) { animation: unset; opacity: 0; }
+
+html::view-transition-group(left-element),
+html::view-transition-group(right-element) { animation-duration: 0s; }
+
+html::view-transition-new(left-element),
+html::view-transition-new(right-element) { animation: unset; opacity: 0; }
+
+html::view-transition-old(left-element),
+html::view-transition-old(right-element) { animation: unset; opacity: 1; }
+
+html::view-transition-group(root) { animation: unset; opacity: 0; }
+html::view-transition { background: lightpink; }
+
+</style>
+
+<div id=left class="left-tag"></div>
+<div id=right class="right-tag"></div>
+
+<div id=hidden class=hidden></div>
+
+<script>
+failIfNot(document.startViewTransition, "Missing document.startViewTransition");
+
+async function runTest() {
+ document.startViewTransition(() => {
+ left.classList.remove("left-tag");
+ left.classList.add("right-tag");
+
+ right.classList.remove("right-tag");
+ right.classList.add("left-tag");
+
+ requestAnimationFrame(() => requestAnimationFrame(takeScreenshot))
+ });
+}
+onload = () => requestAnimationFrame(() => requestAnimationFrame(runTest));
+</script>
+
diff --git a/testing/web-platform/tests/css/css-view-transitions/dialog-in-top-layer-during-transition-new.html b/testing/web-platform/tests/css/css-view-transitions/dialog-in-top-layer-during-transition-new.html
new file mode 100644
index 0000000000..e84167a248
--- /dev/null
+++ b/testing/web-platform/tests/css/css-view-transitions/dialog-in-top-layer-during-transition-new.html
@@ -0,0 +1,71 @@
+<!DOCTYPE html>
+<html class=reftest-wait>
+<title>View transitions: element in top layer during transition</title>
+<link rel="help" href="https://github.com/WICG/view-transitions">
+<link rel="author" href="mailto:khushalsagar@chromium.org">
+<link rel="match" href="dialog-in-top-layer-during-transition-ref.html">
+
+<script src="/common/reftest-wait.js"></script>
+<style>
+#target {
+ width: 100px;
+ height: 100px;
+ background: lightblue;
+
+ border: unset;
+ margin: 0;
+ padding: 0;
+
+ view-transition-name: dialog;
+ contain: layout;
+}
+
+#target::backdrop {
+ width: 100px;
+ height: 100px;
+ background: grey;
+
+ view-transition-name: backdrop;
+ contain: layout;
+}
+
+.hidden {
+ contain: paint;
+ width: 10px;
+ height: 10px;
+ background: grey;
+ view-transition-name: hidden;
+}
+
+html::view-transition-group(hidden) { animation-duration: 300s; }
+html::view-transition-image-pair(hidden) { animation: unset; opacity: 0; }
+
+html::view-transition-group(backdrop) {
+ position: fixed;
+ top: 120px;
+ left: 0;
+}
+
+html::view-transition-new(backdrop), html::view-transition-new(dialog) {
+ opacity: 1;
+ animation: unset;
+}
+</style>
+
+<dialog id="target"></dialog>
+<div id=hidden class=hidden></div>
+
+<script>
+failIfNot(document.startViewTransition, "Missing document.startViewTransition");
+
+async function runTest() {
+ const transition = document.startViewTransition(() => {
+ target.showModal();
+ target.style.background = "lightgreen";
+ });
+ await transition.ready;
+ takeScreenshot();
+}
+onload = () => requestAnimationFrame(() => requestAnimationFrame(runTest));
+</script>
+
diff --git a/testing/web-platform/tests/css/css-view-transitions/dialog-in-top-layer-during-transition-old.html b/testing/web-platform/tests/css/css-view-transitions/dialog-in-top-layer-during-transition-old.html
new file mode 100644
index 0000000000..672295cd3b
--- /dev/null
+++ b/testing/web-platform/tests/css/css-view-transitions/dialog-in-top-layer-during-transition-old.html
@@ -0,0 +1,72 @@
+<!DOCTYPE html>
+<html class=reftest-wait>
+<title>View transitions: element in top layer during transition</title>
+<link rel="help" href="https://github.com/WICG/view-transitions">
+<link rel="author" href="mailto:khushalsagar@chromium.org">
+<link rel="match" href="dialog-in-top-layer-during-transition-ref.html">
+
+<script src="/common/reftest-wait.js"></script>
+<style>
+#target {
+ width: 100px;
+ height: 100px;
+ background: lightgreen;
+
+ border: unset;
+ margin: 0;
+ padding: 0;
+
+ view-transition-name: dialog;
+ contain: layout;
+}
+
+#target::backdrop {
+ width: 100px;
+ height: 100px;
+ background: grey;
+
+ view-transition-name: backdrop;
+ contain: layout;
+}
+
+.hidden {
+ contain: paint;
+ width: 10px;
+ height: 10px;
+ background: grey;
+ view-transition-name: hidden;
+}
+
+html::view-transition-group(hidden) { animation-duration: 300s; }
+html::view-transition-image-pair(hidden) { animation: unset; opacity: 0; }
+
+html::view-transition-group(backdrop) {
+ position: fixed;
+ top: 120px;
+ left: 0;
+}
+
+html::view-transition-old(backdrop), html::view-transition-old(dialog) {
+ opacity: 1;
+ animation: unset;
+}
+</style>
+
+<dialog id="target"></dialog>
+<div id=hidden class=hidden></div>
+
+<script>
+failIfNot(document.startViewTransition, "Missing document.startViewTransition");
+
+async function runTest() {
+ target.showModal();
+ const transition = document.startViewTransition(() => {
+ target.close();
+ target.style.background = "lightblue";
+ });
+ await transition.ready;
+ takeScreenshot();
+}
+onload = () => requestAnimationFrame(() => requestAnimationFrame(runTest));
+</script>
+
diff --git a/testing/web-platform/tests/css/css-view-transitions/dialog-in-top-layer-during-transition-ref.html b/testing/web-platform/tests/css/css-view-transitions/dialog-in-top-layer-during-transition-ref.html
new file mode 100644
index 0000000000..41467678a3
--- /dev/null
+++ b/testing/web-platform/tests/css/css-view-transitions/dialog-in-top-layer-during-transition-ref.html
@@ -0,0 +1,28 @@
+<!DOCTYPE html>
+<html>
+<title>View transitions: element in top layer during transition (ref)</title>
+<link rel="help" href="https://github.com/WICG/view-transitions">
+<link rel="author" href="mailto:khushalsagar@chromium.org">
+
+<style>
+div {
+ position: fixed;
+ top: 0;
+ left: 0;
+ width: 100px;
+ height: 100px;
+}
+
+.dialog {
+ background: lightgreen;
+}
+
+.backdrop {
+ background: grey;
+ top: 120px;
+}
+
+</style>
+<div class="dialog"></div>
+<div class="backdrop"></div>
+
diff --git a/testing/web-platform/tests/css/css-view-transitions/duplicate-tag-rejects-capture.html b/testing/web-platform/tests/css/css-view-transitions/duplicate-tag-rejects-capture.html
new file mode 100644
index 0000000000..da340deccb
--- /dev/null
+++ b/testing/web-platform/tests/css/css-view-transitions/duplicate-tag-rejects-capture.html
@@ -0,0 +1,48 @@
+<!DOCTYPE html>
+<html>
+<title>View transitions: duplicate tags in the old DOM skip the transition</title>
+<link rel="help" href="https://www.w3.org/TR/css-view-transitions-1/">
+<link rel="author" href="mailto:khushalsagar@chromium.org">
+
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+
+<style>
+div {
+ width: 100px;
+ height: 100px;
+ background: blue;
+ contain: paint;
+}
+</style>
+
+<div id=first></div>
+<div id=second></div>
+
+<script>
+promise_test(async t => {
+ assert_implements(document.startViewTransition, "Missing document.startViewTransition");
+ return new Promise((resolve, reject) => {
+ first.style = "view-transition-name: target";
+ second.style = "view-transition-name: target";
+ let transition = document.startViewTransition();
+
+ // Ready rejected first since invoking the dom callback is an async task.
+ let readyRejected = false;
+ transition.ready.then(reject, () => {readyRejected = true;});
+
+ // The domUpdate promise resolves (since there is no callback).
+ let domUpdatedResolved = false;
+ transition.domUpdated.then(() => {
+ assert_true(readyRejected, "ready not rejected before domUpdated");
+ domUpdatedResolved = true;
+ }, reject);
+
+ // Finally finish resolves.
+ transition.finished.then(() => {
+ assert_true(domUpdatedResolved, "domUpdated not resolved before finish");
+ resolve();
+ }, reject);
+ });
+}, "Two different elements with the same name in the old DOM should skip the transition");
+</script>
diff --git a/testing/web-platform/tests/css/css-view-transitions/duplicate-tag-rejects-start.html b/testing/web-platform/tests/css/css-view-transitions/duplicate-tag-rejects-start.html
new file mode 100644
index 0000000000..f34c337e0c
--- /dev/null
+++ b/testing/web-platform/tests/css/css-view-transitions/duplicate-tag-rejects-start.html
@@ -0,0 +1,50 @@
+<!DOCTYPE html>
+<html>
+<title>View transitions: duplicate tags in the new DOM skip the transition</title>
+<link rel="help" href="https://www.w3.org/TR/css-view-transitions-1/">
+<link rel="author" href="mailto:khushalsagar@chromium.org">
+
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+
+<style>
+div {
+ width: 100px;
+ height: 100px;
+ background: blue;
+ contain: paint;
+}
+</style>
+
+<div id=first></div>
+<div id=second></div>
+
+<script>
+promise_test(async t => {
+ assert_implements(document.startViewTransition, "Missing document.startViewTransition");
+ return new Promise((resolve, reject) => {
+ first.style = "view-transition-name: target";
+ let transition = document.startViewTransition(() => {
+ first.style = "view-transition-name: target";
+ second.style = "view-transition-name: target";
+ });
+
+ // First domUpdated resolves since the callback runs successfully.
+ let domUpdatedResolved = false;
+ transition.domUpdated.then(() => { domUpdatedResolved = true; }, reject);
+
+ // Then finished resolves since domUpdated was already resolved.
+ let finishResolved = false;
+ transition.domUpdated.then(() => {
+ assert_true(domUpdatedResolved, "domUpdated not resolved before finish");
+ finishResolved = true;
+ }, reject);
+
+ // Finally ready rejects.
+ transition.ready.then(reject, () => {
+ assert_true(finishResolved, "finish not resolved before ready");
+ resolve();
+ });
+ });
+}, "Two different elements with the same name in the new DOM should skip the transition");
+</script>
diff --git a/testing/web-platform/tests/css/css-view-transitions/element-with-overflow-ref.html b/testing/web-platform/tests/css/css-view-transitions/element-with-overflow-ref.html
new file mode 100644
index 0000000000..523c8616a6
--- /dev/null
+++ b/testing/web-platform/tests/css/css-view-transitions/element-with-overflow-ref.html
@@ -0,0 +1,41 @@
+<!DOCTYPE html>
+<html>
+<title>View transitions: element with overflow ref</title>
+<link rel="help" href="https://github.com/WICG/view-transitions">
+<link rel="author" href="mailto:khushalsagar@chromium.org">
+<style>
+ .old_target {
+ position: fixed;
+ top: 0px;
+ left: 0px;
+ width: 100px;
+ height: 100px;
+ background: lightblue;
+ transform: translate(8px, 8px);
+ }
+
+ .new_target {
+ position: fixed;
+ top: 200px;
+ left: 0;
+ width: 100px;
+ height: 100px;
+ background: lightgreen;
+ transform: translate(8px, 8px);
+ }
+
+ .inner {
+ width: 100px;
+ height: 100px;
+ position: relative;
+ top: 50px;
+ left: 50px;
+ border: 5px solid black;
+ }
+</style>
+<div class="old_target">
+ <div class="inner"></div>
+</div>
+<div class="new_target">
+ <div class="inner" style="border:5px solid blue"></div>
+</div>
diff --git a/testing/web-platform/tests/css/css-view-transitions/element-with-overflow.html b/testing/web-platform/tests/css/css-view-transitions/element-with-overflow.html
new file mode 100644
index 0000000000..b600bcec27
--- /dev/null
+++ b/testing/web-platform/tests/css/css-view-transitions/element-with-overflow.html
@@ -0,0 +1,72 @@
+<!DOCTYPE html>
+<html class=reftest-wait>
+<title>View transitions: element with overflow</title>
+<link rel="help" href="https://github.com/WICG/view-transitions">
+<link rel="author" href="mailto:khushalsagar@chromium.org">
+<link rel="match" href="element-with-overflow-ref.html">
+
+<script src="/common/reftest-wait.js"></script>
+<style>
+ .hidden {
+ width: 10px;
+ height: 10px;
+ view-transition-name: hidden;
+ background: green;
+ contain: layout;
+ }
+
+ .target {
+ width: 100px;
+ height: 100px;
+ background: lightblue;
+ contain: layout;
+ view-transition-name: target;
+ }
+ .inner {
+ width: 100px;
+ height: 100px;
+ position: relative;
+ top: 50px;
+ left: 50px;
+ border: 5px solid black;
+ }
+
+ html::view-transition-group(hidden) { animation-duration: 300s; }
+ html::view-transition-image-pair(hidden) { animation: unset; opacity: 0; }
+
+ html::view-transition-new(*), html::view-transition-old(*) {
+ opacity: 1;
+ animation: unset;
+ }
+
+ html::view-transition-old(target) {
+ top: 0px;
+ left: 0px;
+ }
+
+ html::view-transition-new(target) {
+ top: 200px;
+ left: 0px;
+ }
+</style>
+
+<div class="target">
+ <div class="inner"></div>
+</div>
+<div class="hidden"></div>
+
+<script>
+failIfNot(document.startViewTransition, "Missing document.startViewTransition");
+
+async function runTest() {
+ document.startViewTransition(() => {
+ document.getElementsByClassName("target")[0].style.background="lightgreen";
+ document.getElementsByClassName("inner")[0].style.border="5px solid blue";
+ requestAnimationFrame(() => requestAnimationFrame(() =>
+ requestAnimationFrame(() => requestAnimationFrame(takeScreenshot))
+ ));
+ });
+}
+onload = () => requestAnimationFrame(() => requestAnimationFrame(runTest));
+</script>
+
diff --git a/testing/web-platform/tests/css/css-view-transitions/event-pseudo-name.html b/testing/web-platform/tests/css/css-view-transitions/event-pseudo-name.html
new file mode 100644
index 0000000000..b49cde3208
--- /dev/null
+++ b/testing/web-platform/tests/css/css-view-transitions/event-pseudo-name.html
@@ -0,0 +1,54 @@
+<!DOCTYPE html>
+<title>Shared transitions: event pseudo name</title>
+<link rel="help" href="https://github.com/WICG/view-transitions">
+<link rel="author" href="mailto:vmpstr@chromium.org">
+<link rel="match" href="web-animations-api-ref.html">
+
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+
+<style>
+:root { view-transition-name: none; }
+#first {
+ background: blue;
+ width: 100px;
+ height: 100px;
+ contain: paint;
+ view-transition-name: shared;
+}
+
+html::view-transition-group(*),
+html::view-transition-image-pair(*),
+html::view-transition-new(*),
+html::view-transition-old(*) {
+ animation-duration: 600s;
+}
+
+@keyframes fade-in {
+ from { opacity: 0; }
+}
+html::view-transition-image-pair(*) {
+ animation: fade-in 600s both;
+}
+
+</style>
+<div id=first></div>
+<script>
+async_test(t => {
+ assert_implements(document.startViewTransition, "Missing document.startViewTransition");
+ let names = [];
+ document.documentElement.addEventListener("animationstart", (e) => {
+ names.push(e.pseudoElement);
+ if (names.length == 4) {
+ t.step(() => assert_true(names.includes("::view-transition-group(shared)")));
+ t.step(() => assert_true(names.includes("::view-transition-image-pair(shared)")));
+ t.step(() => assert_true(names.includes("::view-transition-new(shared)")));
+ t.step(() => assert_true(names.includes("::view-transition-old(shared)")));
+ t.done();
+ }
+ });
+ document.startViewTransition();
+}, "verifies pseudo name includes a tag");
+
+</script>
+
diff --git a/testing/web-platform/tests/css/css-view-transitions/far-away-capture-ref.html b/testing/web-platform/tests/css/css-view-transitions/far-away-capture-ref.html
new file mode 100644
index 0000000000..f5a034328f
--- /dev/null
+++ b/testing/web-platform/tests/css/css-view-transitions/far-away-capture-ref.html
@@ -0,0 +1,31 @@
+<!DOCTYPE html>
+<html>
+<title>Shared transitions: offscreen content</title>
+<link rel="help" href="https://github.com/WICG/view-transitions">
+<link rel="author" href="mailto:vmpstr@chromium.org">
+<style>
+body { background: pink }
+.flex {
+ display: flex;
+ flex-direction: row;
+ justify-content: flex-start;
+ align-items: flex-start;
+}
+.box {
+ width: 100px;
+ height: 500px;
+ contain: paint;
+ background: green;
+ border: 1px solid black;
+ box-sizing: border-box;
+}
+</style>
+
+<div class=flex>
+ <div class=box>500</div>
+ <div class=box>2000</div>
+ <div class=box>3500</div>
+ <div class=box>5000</div>
+ <div class=box>6500</div>
+</div>
+
diff --git a/testing/web-platform/tests/css/css-view-transitions/far-away-capture.html b/testing/web-platform/tests/css/css-view-transitions/far-away-capture.html
new file mode 100644
index 0000000000..f95ec96c78
--- /dev/null
+++ b/testing/web-platform/tests/css/css-view-transitions/far-away-capture.html
@@ -0,0 +1,84 @@
+<!DOCTYPE html>
+<html class=reftest-wait>
+<title>Shared transitions: offscreen content</title>
+<link rel="help" href="https://github.com/WICG/view-transitions">
+<link rel="author" href="mailto:vmpstr@chromium.org">
+<link rel="match" href="far-away-capture-ref.html">
+<meta name="fuzzy" content="far-away-capture-ref.html:0-1;0-5">
+<script src="/common/reftest-wait.js"></script>
+<style>
+.flex {
+ display: flex;
+ flex-direction: row;
+ justify-content: flex-start;
+ align-items: flex-start;
+}
+.box {
+ width: 100px;
+ height: 500px;
+ contain: paint;
+}
+.shared {
+ background: green;
+ border: 1px solid black;
+ box-sizing: border-box;
+}
+.spacer {
+ height: 1000px;
+}
+#hidden {
+ width: 10px;
+ height: 10px;
+ background: red;
+ contain: paint;
+ view-transition-name: hidden;
+}
+
+html::view-transition-group(hidden) { animation-duration: 300s; }
+html::view-transition-image-pair(hidden) { visibility: hidden; }
+
+html::view-transition-group(*) { animation-duration: 0s; }
+html::view-transition-new(*) { animation: unset; opacity: 0; }
+html::view-transition-old(*) { animation: unset; opacity: 1; }
+html::view-transition-group(root) { display: none; }
+html::view-transition { background: pink }
+
+</style>
+
+<div class=flex>
+ <div id=dst1 class=box></div>
+ <div id=dst2 class=box></div>
+ <div id=dst3 class=box></div>
+ <div id=dst4 class=box></div>
+ <div id=dst5 class=box></div>
+</div>
+<div id=hidden></div>
+<div id=content>
+ <div id=src1 class="box shared" style="view-transition-name: one">500</div>
+ <div class=spacer></div>
+ <div id=src2 class="box shared" style="view-transition-name: two">2000</div>
+ <div class=spacer></div>
+ <div id=src3 class="box shared" style="view-transition-name: three">3500</div>
+ <div class=spacer></div>
+ <div id=src4 class="box shared" style="view-transition-name: four">5000</div>
+ <div class=spacer></div>
+ <div id=src5 class="box shared" style="view-transition-name: five">6500</div>
+</div>
+
+<script>
+failIfNot(document.startViewTransition, "Missing document.startViewTransition");
+
+async function runTest() {
+ document.startViewTransition(() => {
+ content.remove();
+ dst1.style = "view-transition-name: one";
+ dst2.style = "view-transition-name: two";
+ dst3.style = "view-transition-name: three";
+ dst4.style = "view-transition-name: four";
+ dst5.style = "view-transition-name: five";
+ requestAnimationFrame(() => requestAnimationFrame(takeScreenshot));
+ });
+}
+onload = () => requestAnimationFrame(() => requestAnimationFrame(runTest));
+</script>
+
diff --git a/testing/web-platform/tests/css/css-view-transitions/get-computed-style-crash.html b/testing/web-platform/tests/css/css-view-transitions/get-computed-style-crash.html
new file mode 100644
index 0000000000..38cd5af7f8
--- /dev/null
+++ b/testing/web-platform/tests/css/css-view-transitions/get-computed-style-crash.html
@@ -0,0 +1,16 @@
+<!DOCTYPE html>
+<title>getComputedStyle without transition should not crash</title>
+<link rel="help" href="https://drafts.csswg.org/css-view-transitions-1">
+<link rel="author" href="mailto:vmpstr@chromium.org">
+
+<body onload="start();">
+
+<script>
+async function start() {
+ var el = document.createElement(undefined);
+ document.body.appendChild(el);
+
+ var style = self.getComputedStyle(el, ':view-transition');
+ style.getPropertyValue("--child");
+}
+</script>
diff --git a/testing/web-platform/tests/css/css-view-transitions/hit-test-unpainted-element-from-point.html b/testing/web-platform/tests/css/css-view-transitions/hit-test-unpainted-element-from-point.html
new file mode 100644
index 0000000000..ec5e407260
--- /dev/null
+++ b/testing/web-platform/tests/css/css-view-transitions/hit-test-unpainted-element-from-point.html
@@ -0,0 +1,72 @@
+<!DOCTYPE html>
+<title>Shared transitions: hit test shared element at the real dom location</title>
+<link rel="help" href="https://github.com/WICG/view-transitions">
+<link rel="author" href="mailto:vmpstr@chromium.org">
+<link rel="match" href="hit-test-unpainted-element-ref.html">
+
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+
+<style>
+html { view-transition-name: none }
+#target {
+ width: 100px;
+ height: 100px;
+ contain: paint;
+ view-transition-name: shared;
+ position: relative;
+ z-index: 1;
+}
+.before {
+ background: yellow;
+ left: 200px;
+}
+.after {
+ background: green;
+}
+.after:hover {
+ background: red;
+}
+#unrelated {
+ width: 50px;
+ height: 50px;
+ position: relative;
+ top: -50px;
+ background: blue;
+}
+
+html::view-transition-group(shared) {
+ animation-delay: 300s;
+}
+html::view-transition-old(shared) {
+ animation: unset;
+ opacity: 1;
+}
+html::view-transition-new(shared) {
+ display: none;
+}
+</style>
+
+<div id=target class=before></div>
+<div id=unrelated></div>
+
+<script>
+async_test(t => {
+ assert_implements(document.startViewTransition, "Missing document.startViewTransition");
+ document.startViewTransition(() => {
+ target.classList.toggle("before");
+ target.classList.toggle("after");
+ requestAnimationFrame(async () => {
+ // Check the old location of the element, we should get body.
+ t.step(() => assert_equals(document.elementFromPoint(20, 20), document.body));
+ // Check the new location of the pseudo element, we should get documentElement,
+ // which is the originating element for the pseudo element.
+ t.step(() => assert_equals(document.elementFromPoint(220, 20), document.documentElement));
+ // Check the spot that used to be covered by the element but now has
+ // unrelated element, which is what we expect to get.
+ t.step(() => assert_equals(document.elementFromPoint(20, 70), unrelated));
+ t.done();
+ });
+ });
+}, "hit test should not hit unpainted element, but does hit pseudo and unrelated elements");
+</script>
diff --git a/testing/web-platform/tests/css/css-view-transitions/hit-test-unpainted-element-ref.html b/testing/web-platform/tests/css/css-view-transitions/hit-test-unpainted-element-ref.html
new file mode 100644
index 0000000000..fb73bb91fb
--- /dev/null
+++ b/testing/web-platform/tests/css/css-view-transitions/hit-test-unpainted-element-ref.html
@@ -0,0 +1,17 @@
+<!DOCTYPE html>
+<title>Shared transitions: hit test shared element at the real dom location (ref)</title>
+<link rel="help" href="https://github.com/WICG/view-transitions">
+<link rel="author" href="mailto:vmpstr@chromium.org">
+
+<style>
+div {
+ width: 100px;
+ height: 100px;
+ contain: paint;
+ position: relative;
+ background: green;
+ left: 200px;
+}
+</style>
+
+<div></div>
diff --git a/testing/web-platform/tests/css/css-view-transitions/hit-test-unpainted-element.html b/testing/web-platform/tests/css/css-view-transitions/hit-test-unpainted-element.html
new file mode 100644
index 0000000000..ef4bc6613a
--- /dev/null
+++ b/testing/web-platform/tests/css/css-view-transitions/hit-test-unpainted-element.html
@@ -0,0 +1,69 @@
+<!DOCTYPE html>
+<html class=reftest-wait>
+<title>Shared transitions: hit test shared element at the real dom location</title>
+<link rel="help" href="https://github.com/WICG/view-transitions">
+<link rel="author" href="mailto:vmpstr@chromium.org">
+<link rel="match" href="hit-test-unpainted-element-ref.html">
+
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-actions.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+<script src="/common/reftest-wait.js"></script>
+
+<style>
+html { view-transition-name: none }
+div {
+ width: 100px;
+ height: 100px;
+ contain: paint;
+ view-transition-name: shared;
+}
+.before {
+ position: relative;
+ background: yellow;
+ left: 200px;
+}
+.after {
+ background: green;
+}
+.after:hover {
+ background: red;
+}
+
+html::view-transition-group(shared) {
+ animation-delay: 300s;
+}
+html::view-transition-old(shared) {
+ animation: unset;
+ opacity: 0;
+}
+html::view-transition-new(shared) {
+ animation: unset;
+ opacity: 1;
+}
+</style>
+
+<div id=target class=before></div>
+
+<script>
+failIfNot(document.startViewTransition, "Missing document.startViewTransition");
+
+function mouseMoveToTarget(x, y) {
+ return new test_driver.Actions().pointerMove(x, y).send();
+}
+
+async function runTest() {
+ document.startViewTransition(() => {
+ target.classList.toggle("before");
+ target.classList.toggle("after");
+ // Ensure that we exit the capture phase before doing the rest of the test,
+ // since we want the animating phase to do hit-testing.
+ requestAnimationFrame(async () => {
+ await mouseMoveToTarget(10, 10);
+ requestAnimationFrame(takeScreenshot);
+ });
+ });
+}
+
+onload = () => requestAnimationFrame(() => requestAnimationFrame(runTest));
+</script>
diff --git a/testing/web-platform/tests/css/css-view-transitions/hit-test-unrelated-element-ref.html b/testing/web-platform/tests/css/css-view-transitions/hit-test-unrelated-element-ref.html
new file mode 100644
index 0000000000..9d236466d6
--- /dev/null
+++ b/testing/web-platform/tests/css/css-view-transitions/hit-test-unrelated-element-ref.html
@@ -0,0 +1,27 @@
+<!DOCTYPE html>
+<title>Shared transitions: hit test shared element at the real dom location (ref)</title>
+<link rel="help" href="https://github.com/WICG/view-transitions">
+<link rel="author" href="mailto:vmpstr@chromium.org">
+
+<style>
+#target {
+ width: 100px;
+ height: 100px;
+ contain: paint;
+ background: blue;
+ position: relative;
+ left: 200px;
+}
+#unrelated {
+ width: 100px;
+ height: 100px;
+ background: green;
+ position: relative;
+ top: 200px;
+ left: 200px;
+}
+
+</style>
+
+<div id=target></div>
+<div id=unrelated></div>
diff --git a/testing/web-platform/tests/css/css-view-transitions/hit-test-unrelated-element.html b/testing/web-platform/tests/css/css-view-transitions/hit-test-unrelated-element.html
new file mode 100644
index 0000000000..188521d588
--- /dev/null
+++ b/testing/web-platform/tests/css/css-view-transitions/hit-test-unrelated-element.html
@@ -0,0 +1,73 @@
+<!DOCTYPE html>
+<html class=reftest-wait>
+<title>Shared transitions: hit test shared element at the real dom location</title>
+<link rel="help" href="https://github.com/WICG/view-transitions">
+<link rel="author" href="mailto:vmpstr@chromium.org">
+<link rel="match" href="hit-test-unrelated-element-ref.html">
+
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-actions.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+<script src="/common/reftest-wait.js"></script>
+
+<style>
+html { view-transition-name: none }
+#target {
+ width: 100px;
+ height: 100px;
+ contain: paint;
+ background: blue;
+ view-transition-name: shared;
+}
+#target.before {
+ position: relative;
+ left: 200px;
+}
+
+#unrelated {
+ width: 100px;
+ height: 100px;
+ background: red;
+ position: relative;
+ top: 200px;
+ left: 200px;
+}
+#unrelated:hover {
+ background: green;
+}
+
+html::view-transition-group(shared) {
+ animation-delay: 300s;
+}
+html::view-transition-old(shared) {
+ animation: unset;
+ opacity: 0;
+}
+html::view-transition-new(shared) {
+ animation: unset;
+ opacity: 1;
+}
+</style>
+
+<div id=target class=before></div>
+<div id=unrelated></div>
+
+<script>
+failIfNot(document.startViewTransition, "Missing document.startViewTransition");
+
+function mouseMoveToTarget(x, y) {
+ return new test_driver.Actions().pointerMove(x, y).send();
+}
+
+async function runTest() {
+ document.startViewTransition(() => {
+ target.classList.toggle("before");
+ requestAnimationFrame(async () => {
+ await mouseMoveToTarget(210, 310);
+ requestAnimationFrame(takeScreenshot);
+ });
+ });
+}
+
+onload = () => requestAnimationFrame(() => requestAnimationFrame(runTest));
+</script>
diff --git a/testing/web-platform/tests/css/css-view-transitions/iframe-transition-ref.html b/testing/web-platform/tests/css/css-view-transitions/iframe-transition-ref.html
new file mode 100644
index 0000000000..da1821e1d8
--- /dev/null
+++ b/testing/web-platform/tests/css/css-view-transitions/iframe-transition-ref.html
@@ -0,0 +1,22 @@
+<!DOCTYPE html>
+<title>Shared transitions: iframe</title>
+<link rel="help" href="https://github.com/WICG/view-transitions">
+<link rel="author" href="mailto:vmpstr@chromium.org">
+<style>
+iframe { width: 500px; height: 500px }
+</style>
+
+<iframe srcdoc="
+<style>
+div {
+ width: 100px;
+ height: 100px;
+ background: green;
+}
+html { height: 50%; }
+</style>
+
+<div></div>
+"></iframe>
+
+
diff --git a/testing/web-platform/tests/css/css-view-transitions/iframe-transition.sub.html b/testing/web-platform/tests/css/css-view-transitions/iframe-transition.sub.html
new file mode 100644
index 0000000000..914db87a9e
--- /dev/null
+++ b/testing/web-platform/tests/css/css-view-transitions/iframe-transition.sub.html
@@ -0,0 +1,21 @@
+<!DOCTYPE html>
+<html class=reftest-wait>
+<title>Shared transitions: iframe</title>
+<meta name="timeout" content="long">
+<link rel="help" href="https://github.com/WICG/view-transitions">
+<link rel="author" href="mailto:vmpstr@chromium.org">
+<link rel="match" href="iframe-transition-ref.html">
+<meta name="assert" content="Ensure that iframe root capture is sized and displayed correctly">
+<meta name=fuzzy content="iframe-transition-ref.html:0-200;0-200">
+<script src="/common/reftest-wait.js"></script>
+<style>
+iframe { width: 500px; height: 500px }
+</style>
+
+<script>
+failIfNot(document.startViewTransition, "Missing document.startViewTransition");
+
+addEventListener("message", takeScreenshot);
+</script>
+
+<iframe id=frame src="http://{{domains[www]}}:{{ports[http][0]}}/css/css-view-transitions/support/frame-helper.html"></iframe>
diff --git a/testing/web-platform/tests/css/css-view-transitions/inline-child-with-filter-ref.html b/testing/web-platform/tests/css/css-view-transitions/inline-child-with-filter-ref.html
new file mode 100644
index 0000000000..44a41f1bf9
--- /dev/null
+++ b/testing/web-platform/tests/css/css-view-transitions/inline-child-with-filter-ref.html
@@ -0,0 +1,29 @@
+<!DOCTYPE html>
+<title>View transitions: inline child with filter (ref)</title>
+<link rel="help" href="https://www.w3.org/TR/css-view-transitions-1/">
+<link rel="author" href="mailto:vmpstr@chromium.org">
+
+<style>
+body { margin : 0; }
+#target {
+ width: 100px;
+ height: 100px;
+ background-color: grey;
+ overflow-clip-margin: 40px;
+ contain: paint;
+ view-transition-name: target;
+}
+
+#child {
+ position: relative;
+ left: 100px;
+ top: 100px;
+ color: lightgreen;
+ background-color: darkgreen;
+ filter: blur(30px);
+}
+</style>
+
+<div id="target">
+ <span id="child">INLINEBOX</span>
+</div>
diff --git a/testing/web-platform/tests/css/css-view-transitions/inline-child-with-filter.html b/testing/web-platform/tests/css/css-view-transitions/inline-child-with-filter.html
new file mode 100644
index 0000000000..fbacc33246
--- /dev/null
+++ b/testing/web-platform/tests/css/css-view-transitions/inline-child-with-filter.html
@@ -0,0 +1,52 @@
+<!DOCTYPE html>
+<html class=reftest-wait>
+<title>View transitions: inline child with filter</title>
+<link rel="help" href="https://www.w3.org/TR/css-view-transitions-1/">
+<link rel="author" href="mailto:vmpstr@chromium.org">
+<link rel="match" href="inline-child-with-filter-ref.html">
+<script src="/common/reftest-wait.js"></script>
+
+<style>
+body { margin : 0; }
+#target {
+ width: 100px;
+ height: 100px;
+ background-color: grey;
+ overflow-clip-margin: 40px;
+ contain: paint;
+ view-transition-name: target;
+}
+
+#child {
+ position: relative;
+ left: 100px;
+ top: 100px;
+ color: lightgreen;
+ background-color: darkgreen;
+ filter: blur(30px);
+}
+
+html::view-transition-container(root) { animation-duration: 300s; }
+html::view-transition-old(target) {
+ animation: unset;
+ opacity: 1;
+}
+html::view-transition-new(target) {
+ animation: unset;
+ opacity: 0;
+}
+</style>
+
+<div id="target">
+ <span id="child">INLINEBOX</span>
+</div>
+
+<script>
+async function runTest() {
+ let transition = document.startViewTransition(async () => {
+ document.getElementById("target").remove();
+ });
+ transition.ready.then(() => requestAnimationFrame(takeScreenshot));
+}
+onclick = requestAnimationFrame(() => requestAnimationFrame(runTest));
+</script>
diff --git a/testing/web-platform/tests/css/css-view-transitions/input-blocked-when-rendering-suppressed.html b/testing/web-platform/tests/css/css-view-transitions/input-blocked-when-rendering-suppressed.html
new file mode 100644
index 0000000000..7f550c8655
--- /dev/null
+++ b/testing/web-platform/tests/css/css-view-transitions/input-blocked-when-rendering-suppressed.html
@@ -0,0 +1,75 @@
+<!DOCTYPE html>
+<html>
+<title>Shared transitions: ensure input is discarded when rendering is suppressed</title>
+<link rel="help" href="https://github.com/WICG/view-transitions">
+<link rel="author" href="mailto:khushalsagar@chromium.org">
+
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-actions.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+
+<style>
+div {
+ width: 100px;
+ height: 100px;
+ background: blue;
+ contain: paint;
+}
+</style>
+
+<div id=first></div>
+
+<script>
+async function runTest(resolve, reject) {
+ window.addEventListener('mousedown', (event) => {
+ let point = event.clientX + "," + event.clientY;
+ if (event.clientX == 20 && event.clientY == 20)
+ resolve();
+ else
+ reject(point);
+ });
+
+ let transition = document.startViewTransition(() => {
+ return new Promise(async (inner_resolve) => {
+ new test_driver.Actions()
+ .setContext(window)
+ .addPointer("finger1", "touch")
+ .pointerMove(10, 10, {origin: "viewport", sourceName: "finger1"})
+ .pointerDown({sourceName: "finger1"})
+ .pointerUp({sourceName: "finger1"})
+ .send();
+
+ // Use a timeout to ensure the input has been queued up. await
+ // times out because the event is discarded.
+ step_timeout(inner_resolve, 1000);
+ });
+ });
+ await transition.finished;
+
+ await new test_driver.Actions()
+ .setContext(window)
+ .addPointer("finger1", "touch")
+ .pointerMove(20, 20, {origin: "viewport", sourceName: "finger1"})
+ .pointerDown({sourceName: "finger1"})
+ .pointerUp({sourceName: "finger1"})
+ .send();
+}
+
+promise_test(async t => {
+ assert_implements(document.startViewTransition, "Missing document.startViewTransition");
+ return new Promise(async (resolve, reject) => {
+ // Dispatch an event before starting the test to finish init logic in
+ // synthetic input dispatch.
+ await new test_driver.Actions()
+ .setContext(window)
+ .addPointer("finger1", "touch")
+ .pointerMove(0, 0, {origin: "viewport", sourceName: "finger1"})
+ .pointerDown({sourceName: "finger1"})
+ .pointerUp({sourceName: "finger1"})
+ .send();
+ runTest(resolve, reject);
+ });
+}, "Input when rendering suppressed is ignored");
+</script>
diff --git a/testing/web-platform/tests/css/css-view-transitions/intrinsic-aspect-ratio-ref.html b/testing/web-platform/tests/css/css-view-transitions/intrinsic-aspect-ratio-ref.html
new file mode 100644
index 0000000000..b2f63928e4
--- /dev/null
+++ b/testing/web-platform/tests/css/css-view-transitions/intrinsic-aspect-ratio-ref.html
@@ -0,0 +1,31 @@
+<!DOCTYPE html>
+<html>
+<title>Shared transitions: different width container should keep aspect ratio (by default)</title>
+<link rel="help" href="https://github.com/WICG/view-transitions">
+<link rel="author" href="mailto:vmpstr@chromium.org">
+<style>
+.spacer {
+ /* 10px - border from above and below */
+ height: 6px;
+}
+.smallbox {
+ width: 50px;
+ height: 50px;
+ background: blue;
+}
+.bigbox {
+ width: 200px;
+ height: 200px;
+ background: blue;
+}
+
+body { background: lightpink; }
+</style>
+
+<div style="width: 50px; height: 100px; border: 2px solid black">
+ <div style="height: 50px; background: blue"></div>
+</div>
+<div class=spacer></div>
+<div style="width: 200px; height: 100px; border: 2px solid black">
+ <div style="height: 200px; background: blue"></div>
+</div>
diff --git a/testing/web-platform/tests/css/css-view-transitions/japanese-tag-ref.html b/testing/web-platform/tests/css/css-view-transitions/japanese-tag-ref.html
new file mode 100644
index 0000000000..8b351feaed
--- /dev/null
+++ b/testing/web-platform/tests/css/css-view-transitions/japanese-tag-ref.html
@@ -0,0 +1,25 @@
+<!DOCTYPE html>
+<title>Shared transitions: shared element writing-modes (ref)</title>
+<link rel="help" href="https://github.com/WICG/view-transitions">
+<link rel="author" href="mailto:vmpstr@chromium.org">
+
+<style>
+.tb { writing-mode: horizontal-tb; }
+.lr { writing-mode: vertical-lr; }
+.rl { writing-mode: vertical-rl; }
+.shared {
+ margin: 2px;
+ width: 100px;
+ height: 50px;
+ background: green;
+ contain: paint;
+ border: 1px solid black;
+}
+html { background: lightpink; }
+</style>
+
+<div id=one class="tb shared">T</div>
+<div id=two class="lr shared">T</div>
+<div id=three class="rl shared">T</div>
+
+
diff --git a/testing/web-platform/tests/css/css-view-transitions/japanese-tag.html b/testing/web-platform/tests/css/css-view-transitions/japanese-tag.html
new file mode 100644
index 0000000000..6d04155813
--- /dev/null
+++ b/testing/web-platform/tests/css/css-view-transitions/japanese-tag.html
@@ -0,0 +1,95 @@
+<!DOCTYPE html>
+<html class=reftest-wait>
+<title>Shared transitions: shared element writing-modes</title>
+<link rel="help" href="https://github.com/WICG/view-transitions">
+<link rel="author" href="mailto:vmpstr@chromium.org">
+<link rel="match" href="japanese-tag-ref.html">
+<script src="/common/reftest-wait.js"></script>
+<style>
+#hidden {
+ width: 100px;
+ height: 100px;
+ background: red;
+ position: absolute;
+ top: 0;
+ left: 0;
+ contain: paint;
+ view-transition-name: 隠れた;
+}
+.tb { writing-mode: horizontal-tb; }
+.lr { writing-mode: vertical-lr; }
+.rl { writing-mode: vertical-rl; }
+.shared {
+ margin: 2px;
+ width: 100px;
+ height: 50px;
+ background: green;
+ contain: paint;
+ border: 1px solid black;
+}
+#target1, #target2, #target3 {
+ background: red;
+ position: absolute;
+ top: 50px;
+ left: 50px;
+ width: 100px;
+ height: 500px;
+ contain: paint;
+}
+#one { view-transition-name: 第一; }
+#two { view-transition-name: 第二; }
+#three { view-transition-name: 第三; }
+
+html::view-transition-group(隠れた) { animation-duration: 300s; }
+html::view-transition-image-pair(隠れた) { animation: unset; opacity: 0; }
+
+html::view-transition-group(第一),
+html::view-transition-group(第二),
+html::view-transition-group(第三) {
+ animation-delay: 300s;
+ animation-fill-mode: both;
+}
+
+html::view-transition-new(第一),
+html::view-transition-new(第二),
+html::view-transition-new(第三) { animation: unset; opacity: 0; }
+
+html::view-transition-old(第一),
+html::view-transition-old(第二),
+html::view-transition-old(第三) { animation: unset; opacity: 1; }
+
+/* hide the root so we show transition background to ensure we're in a transition */
+html::view-transition-group(root) { animation: unset; opacity: 0; }
+html::view-transition { background: lightpink; }
+
+</style>
+
+<div id=hidden>Should not be visible</div>
+<div id=target1>Should not be visible</div>
+<div id=target2>Should not be visible</div>
+<div id=target3>Should not be visible</div>
+<div id=one class="shared tb">T</div>
+<div id=two class="shared lr">T</div>
+<div id=three class="shared rl">T</div>
+
+<script>
+failIfNot(document.startViewTransition, "Missing document.startViewTransition");
+
+async function runTest() {
+ document.startViewTransition(() => {
+ one.remove();
+ two.remove();
+ three.remove();
+ hidden.style.left = "200px";
+ target1.style.viewTransitionName = "第一";
+ target2.style.viewTransitionName = "第二";
+ target3.style.viewTransitionName = "第三";
+ requestAnimationFrame(() => requestAnimationFrame(takeScreenshot));
+ });
+}
+onload = () => requestAnimationFrame(() => requestAnimationFrame(runTest));
+</script>
+
+
+
+
diff --git a/testing/web-platform/tests/css/css-view-transitions/mix-blend-mode-only-on-transition.html b/testing/web-platform/tests/css/css-view-transitions/mix-blend-mode-only-on-transition.html
new file mode 100644
index 0000000000..5047a067cb
--- /dev/null
+++ b/testing/web-platform/tests/css/css-view-transitions/mix-blend-mode-only-on-transition.html
@@ -0,0 +1,46 @@
+<!DOCTYPE html>
+<html>
+<title>SET: Blend modes are set up only in paired transitions</title>
+<link rel="help" href="https://github.com/WICG/view-transitions">
+<link rel="author" href="mailto:vmpstr@chromium.org">
+
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+
+<style>
+div {
+ width: 100px;
+ height: 100px;
+ background: blue;
+ contain: paint;
+}
+.tagone { view-transition-name: one }
+.tagtwo { view-transition-name: two }
+.tagthree { view-transition-name: three }
+</style>
+
+<div id=first class=tagone></div>
+<div id=second></div>
+<div id=third class=tagthree></div>
+
+<script>
+async_test(t => {
+ assert_implements(document.startViewTransition, "Missing document.startViewTransition");
+ let transition = document.startViewTransition(() => {
+ first.classList.toggle("tagone");
+ second.classList.toggle("tagtwo");
+ requestAnimationFrame(() => {
+ requestAnimationFrame(() => {
+ t.step(() => assert_equals(getComputedStyle(document.documentElement, "::view-transition-image-pair(one)").isolation, "auto"));
+ t.step(() => assert_equals(getComputedStyle(document.documentElement, "::view-transition-old(one)").mixBlendMode, "normal"));
+ t.step(() => assert_equals(getComputedStyle(document.documentElement, "::view-transition-image-pair(two)").isolation, "auto"));
+ t.step(() => assert_equals(getComputedStyle(document.documentElement, "::view-transition-new(two)").mixBlendMode, "normal"));
+ t.step(() => assert_equals(getComputedStyle(document.documentElement, "::view-transition-image-pair(three)").isolation, "isolate"));
+ t.step(() => assert_equals(getComputedStyle(document.documentElement, "::view-transition-old(three)").mixBlendMode, "plus-lighter"));
+ t.step(() => assert_equals(getComputedStyle(document.documentElement, "::view-transition-new(three)").mixBlendMode, "plus-lighter"));
+ t.done();
+ });
+ });
+ });
+}, "Blend modes are set up on paired transitions");
+</script>
diff --git a/testing/web-platform/tests/css/css-view-transitions/new-and-old-sizes-match-ref.html b/testing/web-platform/tests/css/css-view-transitions/new-and-old-sizes-match-ref.html
new file mode 100644
index 0000000000..a2f8942fcc
--- /dev/null
+++ b/testing/web-platform/tests/css/css-view-transitions/new-and-old-sizes-match-ref.html
@@ -0,0 +1,48 @@
+<!DOCTYPE html>
+<html class=reftest-wait>
+<title>Shared transitions: capture elements with different size capture</title>
+<link rel="help" href="https://github.com/WICG/view-transitions">
+<link rel="author" href="mailto:vmpstr@chromium.org">
+<script src="/common/reftest-wait.js"></script>
+<style>
+.box {
+ width: 100px;
+ height: 100px;
+ contain: paint;
+ position: absolute;
+ overflow-clip-margin: 50px;
+}
+#target {
+ top: 20px;
+ left: 20px;
+ view-transition-name: target;
+}
+.inner_overflow {
+ width: 50px;
+ height: 150px;
+ margin-left: -10px;
+ margin-top: -20px;
+ background: lightgreen;
+ clip-path: inset(1px 1px 1px 1px);
+}
+
+/* We're verifying what we capture, so just display the new contents for 5 minutes. */
+html::view-transition-group(*) { animation-duration: 300s; }
+html::view-transition-new(*) { animation: unset; opacity: 0; }
+html::view-transition-old(*) { animation: unset; opacity: 1; }
+/* hide the root so we show transition background to ensure we're in a transition */
+html::view-transition-group(root) { animation: unset; opacity: 0; }
+html::view-transition { background: lightpink; }
+</style>
+<div id=target class=box><div class=inner_overflow>X</div></div>
+<script>
+failIfNot(document.startViewTransition, "Reference missing document.startViewTransition");
+
+async function runTest() {
+ document.startViewTransition(() => {
+ requestAnimationFrame(() => requestAnimationFrame(takeScreenshot));
+ });
+}
+onload = () => requestAnimationFrame(() => requestAnimationFrame(runTest));
+</script>
+
diff --git a/testing/web-platform/tests/css/css-view-transitions/new-and-old-sizes-match.html b/testing/web-platform/tests/css/css-view-transitions/new-and-old-sizes-match.html
new file mode 100644
index 0000000000..b80f90fd70
--- /dev/null
+++ b/testing/web-platform/tests/css/css-view-transitions/new-and-old-sizes-match.html
@@ -0,0 +1,50 @@
+<!DOCTYPE html>
+<html class=reftest-wait>
+<title>Shared transitions: capture elements with different size capture</title>
+<link rel="help" href="https://github.com/WICG/view-transitions">
+<link rel="author" href="mailto:vmpstr@chromium.org">
+<link rel="match" href="new-and-old-sizes-match-ref.html">
+<meta name="fuzzy" content="new-and-old-sizes-match-ref.html:0-1;0-300">
+<script src="/common/reftest-wait.js"></script>
+<style>
+.box {
+ width: 100px;
+ height: 100px;
+ contain: paint;
+ position: absolute;
+ overflow-clip-margin: 50px;
+}
+#target {
+ top: 20px;
+ left: 20px;
+ view-transition-name: target;
+}
+.inner_overflow {
+ width: 50px;
+ height: 150px;
+ margin-left: -10px;
+ margin-top: -20px;
+ background: lightgreen;
+ clip-path: inset(1px 1px 1px 1px);
+}
+
+/* We're verifying what we capture, so just display the new contents for 5 minutes. */
+html::view-transition-group(*) { animation-duration: 300s; }
+html::view-transition-new(*) { animation: unset; opacity: 1; }
+html::view-transition-old(*) { animation: unset; opacity: 0; }
+/* hide the root so we show transition background to ensure we're in a transition */
+html::view-transition-group(root) { animation: unset; opacity: 0; }
+html::view-transition { background: lightpink; }
+</style>
+<div id=target class=box><div class=inner_overflow>X</div></div>
+<script>
+failIfNot(document.startViewTransition, "Missing document.startViewTransition");
+
+async function runTest() {
+ let t = document.startViewTransition(() => {
+ requestAnimationFrame(() => requestAnimationFrame(takeScreenshot));
+ });
+}
+onload = () => requestAnimationFrame(() => requestAnimationFrame(runTest));
+</script>
+
diff --git a/testing/web-platform/tests/css/css-view-transitions/new-content-captures-clip-path-ref.html b/testing/web-platform/tests/css/css-view-transitions/new-content-captures-clip-path-ref.html
new file mode 100644
index 0000000000..0275e1a254
--- /dev/null
+++ b/testing/web-platform/tests/css/css-view-transitions/new-content-captures-clip-path-ref.html
@@ -0,0 +1,23 @@
+<!DOCTYPE html>
+<title>Shared transitions: capture opacity elements (ref)</title>
+<link rel="help" href="https://github.com/WICG/view-transitions">
+<link rel="author" href="mailto:vmpstr@chromium.org">
+<style>
+.box {
+ color: red;
+ background: lightgreen;
+ width: 100px;
+ height: 100px;
+ contain: paint;
+ position: absolute;
+ font-size: 30pt;
+}
+#e1 {
+ clip-path: polygon(50% 0, 100% 50%, 50% 100%, 0 50%);
+ top: 20px;
+ left: 20px;
+}
+body { background: lightpink; }
+</style>
+<div id=e1 class=box></div>
+
diff --git a/testing/web-platform/tests/css/css-view-transitions/new-content-captures-clip-path.html b/testing/web-platform/tests/css/css-view-transitions/new-content-captures-clip-path.html
new file mode 100644
index 0000000000..85f29bad1c
--- /dev/null
+++ b/testing/web-platform/tests/css/css-view-transitions/new-content-captures-clip-path.html
@@ -0,0 +1,48 @@
+<!DOCTYPE html>
+<html class=reftest-wait>
+<title>Shared transitions: capture clip-path elements</title>
+<link rel="help" href="https://github.com/WICG/view-transitions">
+<link rel="author" href="mailto:vmpstr@chromium.org">
+<link rel="match" href="new-content-captures-clip-path-ref.html">
+<meta name="fuzzy" content="new-content-captures-clip-path-ref.html:0-1;0-500">
+<script src="/common/reftest-wait.js"></script>
+<style>
+.box {
+ color: red;
+ background: lightblue;
+ width: 100px;
+ height: 100px;
+ contain: paint;
+ position: absolute;
+ font-size: 30pt;
+}
+#e1 {
+ clip-path: polygon(50% 0, 100% 50%, 50% 100%, 0 50%);
+ top: 20px;
+ left: 20px;
+ view-transition-name: e1;
+}
+
+div.dst { background: lightgreen; }
+/* We're verifying what we capture, so just display the new contents for 5 minutes. */
+html::view-transition-group(*) { animation-duration: 300s; }
+html::view-transition-image-pair(*) { isolation: isolate; }
+html::view-transition-new(*) { animation: unset; opacity: 1; }
+html::view-transition-old(*) { animation: unset; opacity: 0; }
+/* hide the root so we show transition background to ensure we're in a transition */
+html::view-transition-group(root) { animation: unset; opacity: 0; }
+html::view-transition { background: lightpink; }
+</style>
+<div id=e1 class=box></div>
+<script>
+failIfNot(document.startViewTransition, "Missing document.startViewTransition");
+
+async function runTest() {
+ let t = document.startViewTransition(() => {
+ e1.classList.add("dst");
+ requestAnimationFrame(() => requestAnimationFrame(takeScreenshot));
+ });
+}
+onload = () => requestAnimationFrame(() => requestAnimationFrame(runTest));
+</script>
+
diff --git a/testing/web-platform/tests/css/css-view-transitions/new-content-captures-different-size-ref.html b/testing/web-platform/tests/css/css-view-transitions/new-content-captures-different-size-ref.html
new file mode 100644
index 0000000000..88d7f9963f
--- /dev/null
+++ b/testing/web-platform/tests/css/css-view-transitions/new-content-captures-different-size-ref.html
@@ -0,0 +1,36 @@
+<!DOCTYPE html>
+<title>Shared transitions: capture elements with different size capture (ref)</title>
+<link rel="help" href="https://github.com/WICG/view-transitions">
+<link rel="author" href="mailto:vmpstr@chromium.org">
+<style>
+.box {
+ color: red;
+ background: lightgreen;
+ width: 100px;
+ height: 100px;
+ contain: paint;
+ position: absolute;
+ font-size: 30pt;
+}
+#e1 {
+ clip-path: circle(30%);
+ top: 20px;
+ left: 20px;
+}
+#e2 {
+ clip-path: ellipse(70% 30%);
+ top: 160px;
+ left: 20px;
+}
+#e3 {
+ filter: blur(5px);
+ top: 300px;
+ left: 20px;
+}
+
+body { background: lightpink; }
+</style>
+<div id=e1 class=box>one</div>
+<div id=e2 class=box>two</div>
+<div id=e3 class=box>three</div>
+
diff --git a/testing/web-platform/tests/css/css-view-transitions/new-content-captures-different-size.html b/testing/web-platform/tests/css/css-view-transitions/new-content-captures-different-size.html
new file mode 100644
index 0000000000..da9983fc46
--- /dev/null
+++ b/testing/web-platform/tests/css/css-view-transitions/new-content-captures-different-size.html
@@ -0,0 +1,64 @@
+<!DOCTYPE html>
+<meta name="timeout" content="long">
+<html class=reftest-wait>
+<title>Shared transitions: capture elements with different size capture</title>
+<link rel="help" href="https://github.com/WICG/view-transitions">
+<link rel="author" href="mailto:vmpstr@chromium.org">
+<link rel="match" href="new-content-captures-different-size-ref.html">
+<meta name=fuzzy content="new-content-captures-different-size-ref.html:0-40;0-30000">
+<script src="/common/reftest-wait.js"></script>
+<style>
+.box {
+ color: red;
+ background: lightblue;
+ width: 100px;
+ height: 100px;
+ contain: paint;
+ position: absolute;
+ font-size: 30pt;
+}
+#e1 {
+ clip-path: circle(30%);
+ top: 20px;
+ left: 20px;
+ view-transition-name: e1;
+}
+#e2 {
+ clip-path: ellipse(70% 30%);
+ top: 160px;
+ left: 20px;
+ view-transition-name: e2;
+}
+#e3 {
+ filter: blur(5px);
+ top: 300px;
+ left: 20px;
+ view-transition-name: e3;
+}
+
+div.dst { background: lightgreen; }
+/* We're verifying what we capture, so just display the new contents for 5 minutes. */
+html::view-transition-group(*) { animation-duration: 300s; }
+html::view-transition-new(*) { animation: unset; opacity: 1; }
+html::view-transition-old(*) { animation: unset; opacity: 0; }
+/* hide the root so we show transition background to ensure we're in a transition */
+html::view-transition-group(root) { animation: unset; opacity: 0; }
+html::view-transition { background: lightpink; }
+</style>
+<div id=e1 class=box>one</div>
+<div id=e2 class=box>two</div>
+<div id=e3 class=box>three</div>
+<script>
+failIfNot(document.startViewTransition, "Missing document.startViewTransition");
+
+async function runTest() {
+ let t = document.startViewTransition(() => {
+ e1.classList.add("dst");
+ e2.classList.add("dst");
+ e3.classList.add("dst");
+ requestAnimationFrame(() => requestAnimationFrame(takeScreenshot));
+ });
+}
+onload = () => requestAnimationFrame(() => requestAnimationFrame(runTest));
+</script>
+
diff --git a/testing/web-platform/tests/css/css-view-transitions/new-content-captures-opacity-ref.html b/testing/web-platform/tests/css/css-view-transitions/new-content-captures-opacity-ref.html
new file mode 100644
index 0000000000..4fdd41c2d6
--- /dev/null
+++ b/testing/web-platform/tests/css/css-view-transitions/new-content-captures-opacity-ref.html
@@ -0,0 +1,24 @@
+<!DOCTYPE html>
+<title>Shared transitions: capture opacity elements (ref)</title>
+<link rel="help" href="https://github.com/WICG/view-transitions">
+<link rel="author" href="mailto:vmpstr@chromium.org">
+<style>
+.box {
+ color: red;
+ background: lightgreen;
+ width: 100px;
+ height: 100px;
+ contain: paint;
+ position: absolute;
+ font-size: 30pt;
+ will-change: opacity;
+}
+#e1 { opacity: 0.75; top: 20px; left: 20px; }
+#e2 { opacity: 0.5; top: 160px; left: 20px; }
+#e3 { opacity: 0.25; top: 300px; left: 20px; }
+body { background: lightpink; }
+</style>
+<div id=e1 class=box></div>
+<div id=e2 class=box></div>
+<div id=e3 class=box></div>
+
diff --git a/testing/web-platform/tests/css/css-view-transitions/new-content-captures-opacity.html b/testing/web-platform/tests/css/css-view-transitions/new-content-captures-opacity.html
new file mode 100644
index 0000000000..02c43d724b
--- /dev/null
+++ b/testing/web-platform/tests/css/css-view-transitions/new-content-captures-opacity.html
@@ -0,0 +1,47 @@
+<!DOCTYPE html>
+<html class=reftest-wait>
+<title>Shared transitions: capture opacity elements</title>
+<link rel="help" href="https://github.com/WICG/view-transitions">
+<link rel="author" href="mailto:vmpstr@chromium.org">
+<link rel="match" href="new-content-captures-opacity-ref.html">
+<script src="/common/reftest-wait.js"></script>
+<style>
+.box {
+ color: red;
+ background: lightblue;
+ width: 100px;
+ height: 100px;
+ contain: paint;
+ position: absolute;
+ font-size: 30pt;
+ will-change: opacity;
+}
+#e1 { opacity: 0.75; top: 20px; left: 20px; view-transition-name: e1; }
+#e2 { opacity: 0.5; top: 160px; left: 20px; view-transition-name: e2; }
+#e3 { opacity: 0.25; top: 300px; left: 20px; view-transition-name: e3; }
+div.dst { background: lightgreen; }
+/* We're verifying what we capture, so just display the new contents for 5 minutes. */
+html::view-transition-group(*) { animation-duration: 300s; }
+html::view-transition-new(*) { animation: unset; opacity: 1; }
+html::view-transition-old(*) { animation: unset; opacity: 0; }
+/* hide the root so we show transition background to ensure we're in a transition */
+html::view-transition-group(root) { animation: unset; opacity: 0; }
+html::view-transition { background: lightpink; }
+</style>
+<div id=e1 class=box></div>
+<div id=e2 class=box></div>
+<div id=e3 class=box></div>
+<script>
+failIfNot(document.startViewTransition, "Missing document.startViewTransition");
+
+async function runTest() {
+ let t = document.startViewTransition(() => {
+ e1.classList.add("dst");
+ e2.classList.add("dst");
+ e3.classList.add("dst");
+ requestAnimationFrame(() => requestAnimationFrame(takeScreenshot));
+ });
+}
+onload = () => requestAnimationFrame(() => requestAnimationFrame(runTest));
+</script>
+
diff --git a/testing/web-platform/tests/css/css-view-transitions/new-content-captures-root-ref.html b/testing/web-platform/tests/css/css-view-transitions/new-content-captures-root-ref.html
new file mode 100644
index 0000000000..5b5842b630
--- /dev/null
+++ b/testing/web-platform/tests/css/css-view-transitions/new-content-captures-root-ref.html
@@ -0,0 +1,20 @@
+<!DOCTYPE html>
+<title>Shared transitions: capture opacity elements (ref)</title>
+<link rel="help" href="https://github.com/WICG/view-transitions">
+<link rel="author" href="mailto:vmpstr@chromium.org">
+<style>
+.box {
+ background: lightgreen;
+ width: 100px;
+ height: 100px;
+ contain: paint;
+ position: absolute;
+ will-change: transform;
+}
+#e1 {
+ top: 10px;
+ left: 30px;
+}
+</style>
+<div id=e1 class=box></div>
+
diff --git a/testing/web-platform/tests/css/css-view-transitions/new-content-captures-root.html b/testing/web-platform/tests/css/css-view-transitions/new-content-captures-root.html
new file mode 100644
index 0000000000..3b3fe71ceb
--- /dev/null
+++ b/testing/web-platform/tests/css/css-view-transitions/new-content-captures-root.html
@@ -0,0 +1,53 @@
+<!DOCTYPE html>
+<html class=reftest-wait>
+<title>Shared transitions: capture root elements</title>
+<link rel="help" href="https://github.com/WICG/view-transitions">
+<link rel="author" href="mailto:vmpstr@chromium.org">
+<link rel="match" href="new-content-captures-root-ref.html">
+<script src="/common/reftest-wait.js"></script>
+<style>
+.box {
+ background: lightblue;
+ width: 100px;
+ height: 100px;
+ contain: paint;
+ position: absolute;
+ will-change: transform;
+}
+#e1 {
+ top: 10px;
+ left: 30px;
+}
+#shared {
+ contain: paint;
+ width: 100px;
+ height: 100px;
+ background: red;
+ view-transition-name: shared;
+}
+
+div.dst { background: lightgreen; }
+/* We're verifying what we capture, so just display the old contents for 5 minutes. */
+html::view-transition { background: pink; }
+html::view-transition-group(shared) { animation-duration: 300s; }
+html::view-transition-image-pair(shared) { visibility: hidden }
+html::view-transition-old(root) { animation-duration: 0s; opacity: 0 }
+html::view-transition-new(root) { animation-duration: 0s; opacity: 1 }
+</style>
+<body style="background: red">
+<div id=e1 class=box></div>
+<div id=shared></div>
+<script>
+failIfNot(document.startViewTransition, "Missing document.startViewTransition");
+
+async function runTest() {
+ let t = document.startViewTransition(() => {
+ e1.classList.add("dst");
+ document.body.style = "";
+ requestAnimationFrame(() => requestAnimationFrame(takeScreenshot));
+ });
+}
+onload = () => requestAnimationFrame(() => requestAnimationFrame(runTest));
+</script>
+
+</body>
diff --git a/testing/web-platform/tests/css/css-view-transitions/new-content-container-writing-modes-ref.html b/testing/web-platform/tests/css/css-view-transitions/new-content-container-writing-modes-ref.html
new file mode 100644
index 0000000000..e889195b8c
--- /dev/null
+++ b/testing/web-platform/tests/css/css-view-transitions/new-content-container-writing-modes-ref.html
@@ -0,0 +1,23 @@
+<!DOCTYPE html>
+<title>Shared transitions: container of shared element writing-modes (ref)</title>
+<link rel="help" href="https://github.com/WICG/view-transitions">
+<link rel="author" href="mailto:vmpstr@chromium.org">
+
+<style>
+.tb { writing-mode: horizontal-tb; }
+.lr { writing-mode: vertical-lr; }
+.rl { writing-mode: vertical-rl; }
+.shared {
+ margin: 2px;
+ width: 100px;
+ height: 50px;
+ background: green;
+ contain: paint;
+ border: 1px solid black;
+}
+html { background: lightpink; }
+</style>
+
+<div class=tb><div id=one class=shared>T</div></div>
+<div class=lr><div id=two class=shared>T</div></div>
+<div class=rl><div id=three class=shared>T</div></div>
diff --git a/testing/web-platform/tests/css/css-view-transitions/new-content-container-writing-modes.html b/testing/web-platform/tests/css/css-view-transitions/new-content-container-writing-modes.html
new file mode 100644
index 0000000000..75149ca57d
--- /dev/null
+++ b/testing/web-platform/tests/css/css-view-transitions/new-content-container-writing-modes.html
@@ -0,0 +1,89 @@
+<!DOCTYPE html>
+<html class=reftest-wait>
+<title>Shared transitions: container of shared element writing-modes</title>
+<link rel="help" href="https://github.com/WICG/view-transitions">
+<link rel="author" href="mailto:vmpstr@chromium.org">
+<link rel="match" href="new-content-container-writing-modes-ref.html">
+<script src="/common/reftest-wait.js"></script>
+<style>
+#hidden {
+ width: 100px;
+ height: 100px;
+ background: red;
+ position: absolute;
+ top: 0;
+ left: 0;
+ contain: paint;
+ view-transition-name: hidden;
+}
+.tb { writing-mode: horizontal-tb; }
+.lr { writing-mode: vertical-lr; }
+.rl { writing-mode: vertical-rl; }
+.shared {
+ margin: 2px;
+ width: 100px;
+ height: 50px;
+ background: green;
+ contain: paint;
+ border: 1px solid black;
+}
+.source {
+ background: red;
+ position: absolute;
+ top: 50px;
+ left: 50px;
+ width: 100px;
+ height: 500px;
+ contain: paint;
+}
+html::view-transition-group(hidden) { animation-duration: 300s; }
+html::view-transition-image-pair(hidden) { animation: unset; opacity: 0; }
+
+html::view-transition-group(s1),
+html::view-transition-group(s2),
+html::view-transition-group(s3) { animation-duration: 0s; }
+
+html::view-transition-new(s1),
+html::view-transition-new(s2),
+html::view-transition-new(s3) { animation: unset; opacity: 1; }
+
+html::view-transition-old(s1),
+html::view-transition-old(s2),
+html::view-transition-old(s3) { animation: unset; opacity: 0; }
+
+/* hide the root so we show transition background to ensure we're in a transition */
+html::view-transition-group(root) { animation: unset; opacity: 0; }
+html::view-transition { background: lightpink; }
+
+</style>
+
+<div id=hidden>Should not be visible</div>
+<div id=s1 class=source>Should not be visible</div>
+<div id=s2 class=source>Should not be visible</div>
+<div id=s3 class=source>Should not be visible</div>
+<div class=tb><div id=one class=shared>T</div></div>
+<div class=lr><div id=two class=shared>T</div></div>
+<div class=rl><div id=three class=shared>T</div></div>
+
+<script>
+failIfNot(document.startViewTransition, "Missing document.startViewTransition");
+
+async function runTest() {
+ s1.style = "view-transition-name: s1";
+ s2.style = "view-transition-name: s2";
+ s3.style = "view-transition-name: s3";
+ document.startViewTransition(() => {
+ s1.remove();
+ s2.remove();
+ s3.remove();
+ hidden.style.left = "200px";
+ one.style = "view-transition-name: s1";
+ two.style = "view-transition-name: s2";
+ three.style = "view-transition-name: s3";
+ requestAnimationFrame(() => requestAnimationFrame(takeScreenshot));
+ });
+}
+onload = () => requestAnimationFrame(() => requestAnimationFrame(runTest));
+</script>
+
+
diff --git a/testing/web-platform/tests/css/css-view-transitions/new-content-element-writing-modes-ref.html b/testing/web-platform/tests/css/css-view-transitions/new-content-element-writing-modes-ref.html
new file mode 100644
index 0000000000..58bcdc44cc
--- /dev/null
+++ b/testing/web-platform/tests/css/css-view-transitions/new-content-element-writing-modes-ref.html
@@ -0,0 +1,24 @@
+<!DOCTYPE html>
+<title>Shared transitions: shared element writing-modes (ref)</title>
+<link rel="help" href="https://github.com/WICG/view-transitions">
+<link rel="author" href="mailto:vmpstr@chromium.org">
+
+<style>
+.tb { writing-mode: horizontal-tb; }
+.lr { writing-mode: vertical-lr; }
+.rl { writing-mode: vertical-rl; }
+.shared {
+ margin: 2px;
+ width: 100px;
+ height: 50px;
+ background: green;
+ contain: paint;
+ border: 1px solid black;
+}
+html { background: lightpink; }
+</style>
+
+<div id=one class="tb shared">T</div>
+<div id=two class="lr shared">T</div>
+<div id=three class="rl shared">T</div>
+
diff --git a/testing/web-platform/tests/css/css-view-transitions/new-content-element-writing-modes.html b/testing/web-platform/tests/css/css-view-transitions/new-content-element-writing-modes.html
new file mode 100644
index 0000000000..20d81a67db
--- /dev/null
+++ b/testing/web-platform/tests/css/css-view-transitions/new-content-element-writing-modes.html
@@ -0,0 +1,94 @@
+<!DOCTYPE html>
+<html class=reftest-wait>
+<title>Shared transitions: shared element writing-modes</title>
+<link rel="help" href="https://github.com/WICG/view-transitions">
+<link rel="author" href="mailto:vmpstr@chromium.org">
+<link rel="match" href="new-content-element-writing-modes-ref.html">
+<script src="/common/reftest-wait.js"></script>
+<style>
+#hidden {
+ width: 100px;
+ height: 100px;
+ background: red;
+ position: absolute;
+ top: 0;
+ left: 0;
+ contain: paint;
+ view-transition-name: hidden;
+}
+.tb { writing-mode: horizontal-tb; }
+.lr { writing-mode: vertical-lr; }
+.rl { writing-mode: vertical-rl; }
+.shared {
+ margin: 2px;
+ width: 100px;
+ height: 50px;
+ background: green;
+ contain: paint;
+ border: 1px solid black;
+}
+.source {
+ contain: layout;
+}
+#target {
+ background: red;
+ position: absolute;
+ top: 50px;
+ left: 50px;
+ width: 100px;
+ height: 500px;
+ contain: paint;
+}
+
+html::view-transition-group(hidden) { animation-duration: 300s; }
+html::view-transition-image-pair(hidden) { animation: unset; opacity: 0; }
+
+html::view-transition-group(s1),
+html::view-transition-group(s2),
+html::view-transition-group(s3) { animation-duration: 0s; }
+
+html::view-transition-new(s1),
+html::view-transition-new(s2),
+html::view-transition-new(s3) { animation: unset; opacity: 1; }
+
+html::view-transition-old(s1),
+html::view-transition-old(s2),
+html::view-transition-old(s3) { animation: unset; opacity: 0; }
+
+/* hide the root so we show transition background to ensure we're in a transition */
+html::view-transition-group(root) { animation: unset; opacity: 0; }
+html::view-transition { background: lightpink; }
+
+</style>
+
+<div id=hidden>Should not be visible</div>
+<div id=s1 class=source>Should not be visible</div>
+<div id=s2 class=source>Should not be visible</div>
+<div id=s3 class=source>Should not be visible</div>
+<div id=one class="tb shared">T</div>
+<div id=two class="lr shared">T</div>
+<div id=three class="rl shared">T</div>
+
+<script>
+failIfNot(document.startViewTransition, "Missing document.startViewTransition");
+
+async function runTest() {
+ s1.style = "view-transition-name: s1";
+ s2.style = "view-transition-name: s2";
+ s3.style = "view-transition-name: s3";
+ document.startViewTransition(() => {
+ s1.remove();
+ s2.remove();
+ s3.remove();
+ hidden.style.left = "200px";
+ one.style = "view-transition-name: s1";
+ two.style = "view-transition-name: s2";
+ three.style = "view-transition-name: s3";
+ requestAnimationFrame(() => requestAnimationFrame(takeScreenshot));
+ });
+}
+onload = () => requestAnimationFrame(() => requestAnimationFrame(runTest));
+</script>
+
+
+
diff --git a/testing/web-platform/tests/css/css-view-transitions/new-content-has-scrollbars-ref.html b/testing/web-platform/tests/css/css-view-transitions/new-content-has-scrollbars-ref.html
new file mode 100644
index 0000000000..e7e2f71b43
--- /dev/null
+++ b/testing/web-platform/tests/css/css-view-transitions/new-content-has-scrollbars-ref.html
@@ -0,0 +1,27 @@
+<!DOCTYPE html>
+<title>Shared transitions: incoming viewport has scrollbars (ref)</title>
+<link rel="help" href="https://github.com/WICG/view-transitions">
+<link rel="help" href="https://github.com/w3c/csswg-drafts/issues/7859">
+<link rel="author" href="mailto:bokan@chromium.org">
+<style>
+ html, body {
+ width: 100%;
+ height: 100%;
+ background-color: lightpink;
+ }
+ body {
+ margin: 50px;
+ }
+ div {
+ background-image:
+ linear-gradient(45deg, #000 25%, transparent 25%),
+ linear-gradient(45deg, transparent 75%, #000 75%),
+ linear-gradient(45deg, transparent 75%, #000 75%),
+ linear-gradient(45deg, #000 25%, lightgreen 25%);
+ background-size: 200px 200px;
+ background-position: 0 0, 0 0, -100px -100px, 100px 100px;
+ width: 200%;
+ height: 200%;
+ }
+</style>
+<div></div>
diff --git a/testing/web-platform/tests/css/css-view-transitions/new-content-has-scrollbars.html b/testing/web-platform/tests/css/css-view-transitions/new-content-has-scrollbars.html
new file mode 100644
index 0000000000..c21eb0e379
--- /dev/null
+++ b/testing/web-platform/tests/css/css-view-transitions/new-content-has-scrollbars.html
@@ -0,0 +1,62 @@
+<!DOCTYPE html>
+<meta name="timeout" content="long">
+<html class=reftest-wait>
+<title>Shared transitions: incoming viewport has scrollbars</title>
+<link rel="help" href="https://github.com/WICG/view-transitions">
+<link rel="help" href="https://github.com/w3c/csswg-drafts/issues/7859">
+<link rel="author" href="mailto:bokan@chromium.org">
+<link rel="match" href="new-content-has-scrollbars-ref.html">
+<meta name=fuzzy content="new-content-has-scrollbars-ref.html:0-40;0-30000">
+<script src="/common/reftest-wait.js"></script>
+<style>
+ html, body {
+ width: 100%;
+ height: 100%;
+ background-color: lightpink;
+ }
+ html {
+ overflow: hidden;
+ }
+ body {
+ /* Margin to make sure background color is correctly drawn into the snapshot. */
+ margin: 50px;
+ }
+ div {
+ /* Draw a checkerboard pattern to make sure the snapshot is captured at the
+ * full size, rather than scaled. */
+ background-image:
+ linear-gradient(45deg, #000 25%, transparent 25%),
+ linear-gradient(45deg, transparent 75%, #000 75%),
+ linear-gradient(45deg, transparent 75%, #000 75%),
+ linear-gradient(45deg, #000 25%, lightgreen 25%);
+ background-size: 200px 200px;
+ background-position: 0 0, 0 0, -100px -100px, 100px 100px;
+ width: 200%;
+ height: 200%;
+ }
+
+ /* We're verifying what we capture, so just display the old contents for 5 minutes. */
+ html::view-transition-new(root) { animation: unset; opacity: 0; }
+ html::view-transition-old(root) {
+ animation-duration: 300s;
+ animation-timing-function: steps(1, end);
+ opacity: 1;
+ }
+</style>
+
+<div></div>
+<script>
+failIfNot(document.startViewTransition, "Missing document.startViewTransition");
+
+// Ensure a root snapshot captured in the absence of scrollbars is displayed at
+// full size when rendered in the incoming viewport which is inset by
+// scrollbars. The content must not be scaled-to-fit.
+async function runTest() {
+ document.startViewTransition(() => {
+ document.documentElement.style.overflow = "unset";
+ requestAnimationFrame(() => requestAnimationFrame(takeScreenshot));
+ });
+}
+onload = () => requestAnimationFrame(() => requestAnimationFrame(runTest));
+</script>
+
diff --git a/testing/web-platform/tests/css/css-view-transitions/new-content-intrinsic-aspect-ratio.html b/testing/web-platform/tests/css/css-view-transitions/new-content-intrinsic-aspect-ratio.html
new file mode 100644
index 0000000000..924630f574
--- /dev/null
+++ b/testing/web-platform/tests/css/css-view-transitions/new-content-intrinsic-aspect-ratio.html
@@ -0,0 +1,67 @@
+<!DOCTYPE html>
+<html class=reftest-wait>
+<title>Shared transitions: different width container should keep aspect ratio (by default)</title>
+<link rel="help" href="https://github.com/WICG/view-transitions">
+<link rel="author" href="mailto:vmpstr@chromium.org">
+<link rel="match" href="intrinsic-aspect-ratio-ref.html">
+<script src="/common/reftest-wait.js"></script>
+<style>
+.spacer {
+ height: 10px;
+}
+.box {
+ width: 100px;
+ height: 100px;
+ contain: paint;
+ background: blue;
+}
+#target1 {
+ view-transition-name: target1;
+}
+#target2 {
+ view-transition-name: target2;
+}
+#hidden {
+ view-transition-name: hidden;
+ width: 10px;
+ height: 10px;
+ visibility: hidden;
+ contain: paint;
+}
+
+/* We're verifying what we capture, so just display the new contents for 5 minutes. */
+html::view-transition-group(*) { animation-duration: 300s; }
+html::view-transition-new(*) { animation: unset; opacity: 1; }
+html::view-transition-old(*) { animation: unset; opacity: 0; }
+
+html::view-transition-group(target1) {
+ animation: unset;
+ width: 50px;
+ border: 2px solid black;
+}
+html::view-transition-group(target2) {
+ animation: unset;
+ width: 200px;
+ border: 2px solid black;
+}
+
+/* hide the root so we show transition background to ensure we're in a transition */
+html::view-transition-group(root) { animation: unset; opacity: 0; }
+html::view-transition { background: lightpink; }
+</style>
+
+<div id=target1 class=box></div>
+<div class=spacer></div>
+<div id=target2 class=box></div>
+<div id=hidden></div>
+<script>
+failIfNot(document.startViewTransition, "Missing document.startViewTransition");
+
+async function runTest() {
+ document.startViewTransition(() => {
+ requestAnimationFrame(() => requestAnimationFrame(takeScreenshot));
+ });
+}
+onload = () => requestAnimationFrame(() => requestAnimationFrame(runTest));
+</script>
+
diff --git a/testing/web-platform/tests/css/css-view-transitions/new-content-is-empty-div-ref.html b/testing/web-platform/tests/css/css-view-transitions/new-content-is-empty-div-ref.html
new file mode 100644
index 0000000000..ab70b830a5
--- /dev/null
+++ b/testing/web-platform/tests/css/css-view-transitions/new-content-is-empty-div-ref.html
@@ -0,0 +1,19 @@
+<!DOCTYPE html>
+<title>Shared transitions: new content captures an empty div (ref)</title>
+<link rel="help" href="https://github.com/WICG/view-transitions">
+<link rel="author" href="mailto:vmpstr@chromium.org">
+<style>
+div {
+ width: 100px;
+ height: 100px;
+ contain: paint;
+ position: absolute;
+ top: 50px;
+ left: 200px;
+ background: green;
+}
+body { background: lightpink; }
+</style>
+<div></div>
+
+
diff --git a/testing/web-platform/tests/css/css-view-transitions/new-content-is-empty-div.html b/testing/web-platform/tests/css/css-view-transitions/new-content-is-empty-div.html
new file mode 100644
index 0000000000..09e09dea6d
--- /dev/null
+++ b/testing/web-platform/tests/css/css-view-transitions/new-content-is-empty-div.html
@@ -0,0 +1,61 @@
+<!DOCTYPE html>
+<html class=reftest-wait>
+<title>Shared transitions: old content captures an empty div</title>
+<link rel="help" href="https://github.com/WICG/view-transitions">
+<link rel="author" href="mailto:vmpstr@chromium.org">
+<link rel="match" href="new-content-is-empty-div-ref.html">
+
+<script src="/common/reftest-wait.js"></script>
+<style>
+div {
+ contain: paint;
+ width: 100px;
+ height: 100px;
+ position: absolute;
+ top: 50px;
+}
+#source {
+ left: 50px;
+ background: green;
+}
+#target {
+ left: 200px;
+}
+#hidden {
+ background: red;
+ view-transition-name: hidden;
+}
+
+html::view-transition-group(hidden) { animation-duration: 300s; }
+html::view-transition-image-pair(hidden) { animation: unset; opacity: 0; }
+
+/* The effect of the following should be position at the incoming element
+ but contents of the new element.
+*/
+html::view-transition-group(shared) { animation-duration: 0s; }
+html::view-transition-new(shared) { animation: unset; opacity: 1; }
+html::view-transition-old(shared) { animation: unset; opacity: 1; }
+
+html::view-transition-group(root) { animation: unset; opacity: 0; }
+html::view-transition { background: lightpink; }
+
+</style>
+
+<div id=source></div>
+<div id=target></div>
+<div id=hidden></div>
+
+<script>
+failIfNot(document.startViewTransition, "Missing document.startViewTransition");
+
+async function runTest() {
+ source.style = "view-transition-name: shared";
+ document.startViewTransition(() => {
+ source.style = "";
+ target.style = "view-transition-name: shared";
+
+ requestAnimationFrame(() => requestAnimationFrame(takeScreenshot))
+ });
+}
+onload = () => requestAnimationFrame(() => requestAnimationFrame(runTest));
+</script>
diff --git a/testing/web-platform/tests/css/css-view-transitions/new-content-object-fit-fill.html b/testing/web-platform/tests/css/css-view-transitions/new-content-object-fit-fill.html
new file mode 100644
index 0000000000..04b404de26
--- /dev/null
+++ b/testing/web-platform/tests/css/css-view-transitions/new-content-object-fit-fill.html
@@ -0,0 +1,77 @@
+<!DOCTYPE html>
+<html class=reftest-wait>
+<title>Shared transitions: display content in a pseudo with object-fit: fill</title>
+<link rel="help" href="https://github.com/WICG/view-transitions">
+<link rel="author" href="mailto:vmpstr@chromium.org">
+<link rel="match" href="content-object-fit-fill-ref.html">
+<meta name="fuzzy" content="content-object-fit-fill-ref.html:0-60;0-20">
+<script src="/common/reftest-wait.js"></script>
+<style>
+#target {
+ width: 100px;
+ height: 100px;
+ contain: paint;
+ position: absolute;
+ top: 20px;
+ left: 20px;
+ view-transition-name: target;
+ background: lightblue;
+}
+#inner {
+ width: 10px;
+ height: 10px;
+ background: green;
+ top: 5px;
+ left: 10px;
+}
+#hidden {
+ background: pink;
+ width: 10px;
+ height: 10px;
+ view-transition-name: hidden;
+ contain: layout;
+}
+
+html::view-transition-group(target) {
+ animation: unset;
+ transform: unset;
+ position: absolute;
+ top: 10px;
+ left: 10px;
+ width: 50px;
+ height: 50px;
+}
+
+html::view-transition-new(target) {
+ animation: unset;
+ opacity: 1;
+ object-fit: fill;
+}
+html::view-transition-old(target) {
+ animation: unset;
+ opacity: 0;
+}
+
+html::view-transition-group(hidden) {
+ animation-duration: 500s;
+ visibility: hidden;
+}
+
+html::view-transition-group(root) { animation: unset; opacity: 0; }
+html::view-transition { background: lightpink; }
+</style>
+
+<div id=target><div id=inner></div></div>
+<div id=hidden></div>
+
+<script>
+failIfNot(document.startViewTransition, "Missing document.startViewTransition");
+
+async function runTest() {
+ document.startViewTransition(() => {
+ requestAnimationFrame(() => requestAnimationFrame(takeScreenshot));
+ });
+}
+onload = () => requestAnimationFrame(() => requestAnimationFrame(runTest));
+</script>
+
diff --git a/testing/web-platform/tests/css/css-view-transitions/new-content-object-fit-none.html b/testing/web-platform/tests/css/css-view-transitions/new-content-object-fit-none.html
new file mode 100644
index 0000000000..eab7a0e207
--- /dev/null
+++ b/testing/web-platform/tests/css/css-view-transitions/new-content-object-fit-none.html
@@ -0,0 +1,70 @@
+<!DOCTYPE html>
+<html class=reftest-wait>
+<title>Shared transitions: display content in a pseudo with object-fit: none</title>
+<link rel="help" href="https://github.com/WICG/view-transitions">
+<link rel="author" href="mailto:vmpstr@chromium.org">
+<link rel="match" href="content-object-fit-none-ref.html">
+<script src="/common/reftest-wait.js"></script>
+<style>
+#target {
+ width: 100px;
+ height: 100px;
+ contain: paint;
+ position: absolute;
+ top: 20px;
+ left: 20px;
+ view-transition-name: target;
+ background: lightblue;
+}
+#hidden {
+ background: pink;
+ width: 10px;
+ height: 10px;
+ view-transition-name: hidden;
+ contain: layout;
+}
+
+html::view-transition-group(target) {
+ animation: unset;
+ transform: unset;
+ position: absolute;
+ top: 10px;
+ left: 10px;
+ width: 50px;
+ height: 50px;
+}
+
+html::view-transition-new(target) {
+ animation: unset;
+ opacity: 1;
+ object-fit: none;
+ object-position: 0% 0%;
+}
+html::view-transition-old(target) {
+ animation: unset;
+ opacity: 0;
+}
+
+html::view-transition-group(hidden) {
+ animation-duration: 500s;
+ visibility: hidden;
+}
+
+html::view-transition-group(root) { animation: unset; opacity: 0; }
+html::view-transition { background: lightpink; }
+</style>
+
+<div id=target>This is text</div>
+<div id=hidden></div>
+
+<script>
+failIfNot(document.startViewTransition, "Missing document.startViewTransition");
+
+async function runTest() {
+ document.startViewTransition(() => {
+ requestAnimationFrame(() => requestAnimationFrame(takeScreenshot));
+ });
+}
+onload = () => requestAnimationFrame(() => requestAnimationFrame(runTest));
+</script>
+
diff --git a/testing/web-platform/tests/css/css-view-transitions/new-content-object-view-box-clip-path-ref.html b/testing/web-platform/tests/css/css-view-transitions/new-content-object-view-box-clip-path-ref.html
new file mode 100644
index 0000000000..208284cc71
--- /dev/null
+++ b/testing/web-platform/tests/css/css-view-transitions/new-content-object-view-box-clip-path-ref.html
@@ -0,0 +1,46 @@
+<!DOCTYPE html>
+<title>Shared transitions: object-view-box with larger overflow (ref)</title>
+<link rel="help" href="https://github.com/WICG/view-transitions">
+<link rel="author" href="mailto:vmpstr@chromium.org">
+<style>
+.target {
+ color: red;
+ width: 100px;
+ height: 100px;
+ contain: paint;
+ position: relative;
+ top: 50px;
+ left: 50px;
+}
+.child {
+ width: 123px;
+ height: 150px;
+ background: lightblue;
+ position: relative;
+ top: -10px;
+ left: -20px;
+}
+.grandchild {
+ width: 25px;
+ height: 25px;
+ position: relative;
+ top: 20px;
+ left: 40px;
+ background: green;
+}
+#one { clip-path: inset(10px 12px 20px 28px); }
+#two { clip-path: inset(10px -12px 20px -28px); }
+body { background: lightpink; }
+</style>
+
+<div id=one class=target>
+ <div class=child>
+ <div class=grandchild></div>
+ </div>
+</div>
+<div style="height: 20px;"></div>
+<div id=two class=target>
+ <div class=child>
+ <div class=grandchild></div>
+ </div>
+</div>
diff --git a/testing/web-platform/tests/css/css-view-transitions/new-content-object-view-box-clip-path-reference-ref.html b/testing/web-platform/tests/css/css-view-transitions/new-content-object-view-box-clip-path-reference-ref.html
new file mode 100644
index 0000000000..394a80f344
--- /dev/null
+++ b/testing/web-platform/tests/css/css-view-transitions/new-content-object-view-box-clip-path-reference-ref.html
@@ -0,0 +1,57 @@
+<!DOCTYPE html>
+<title>Shared transitions: object-view-box with larger overflow (ref)</title>
+<link rel="help" href="https://github.com/WICG/view-transitions">
+<link rel="author" href="mailto:vmpstr@chromium.org">
+<style>
+.target {
+ color: red;
+ width: 100px;
+ height: 100px;
+ contain: paint;
+ position: relative;
+ top: 50px;
+ left: 50px;
+}
+.child {
+ width: 123px;
+ height: 150px;
+ background: lightblue;
+ position: relative;
+ top: -10px;
+ left: -20px;
+}
+.grandchild {
+ width: 25px;
+ height: 25px;
+ position: relative;
+ top: 20px;
+ left: 40px;
+ background: green;
+}
+#one { clip-path: url(#clip1); }
+#two { clip-path: url(#clip2); }
+body { background: lightpink; }
+</style>
+
+<div id=one class=target>
+ <div class=child>
+ <div class=grandchild></div>
+ </div>
+</div>
+<div style="height: 20px;"></div>
+<div id=two class=target>
+ <div class=child>
+ <div class=grandchild></div>
+ </div>
+</div>
+
+<svg>
+ <defs>
+ <clipPath id="clip1">
+ <rect x="10" y="20" width="70" height="50" />
+ </clipPath>
+ <clipPath id="clip2">
+ <rect x="-10" y="20" width="130" height="50" />
+ </clipPath>
+ </defs>
+</svg>
diff --git a/testing/web-platform/tests/css/css-view-transitions/new-content-object-view-box-clip-path-reference.html b/testing/web-platform/tests/css/css-view-transitions/new-content-object-view-box-clip-path-reference.html
new file mode 100644
index 0000000000..8dd5774ec4
--- /dev/null
+++ b/testing/web-platform/tests/css/css-view-transitions/new-content-object-view-box-clip-path-reference.html
@@ -0,0 +1,93 @@
+<!DOCTYPE html>
+<html class=reftest-wait>
+<title>Shared transitions: object-view-box with larger clip-path</title>
+<link rel="help" href="https://github.com/WICG/view-transitions">
+<link rel="author" href="mailto:vmpstr@chromium.org">
+<link rel="match" href="new-content-object-view-box-clip-path-reference-ref.html">
+<script src="/common/reftest-wait.js"></script>
+<style>
+.target {
+ color: red;
+ width: 100px;
+ height: 100px;
+ contain: paint;
+ overflow-clip-margin: 1000px;
+ position: relative;
+ top: 50px;
+ left: 50px;
+}
+.child {
+ width: 123px;
+ height: 150px;
+ background: lightblue;
+ position: relative;
+ top: -10px;
+ left: -20px;
+}
+.grandchild {
+ width: 25px;
+ height: 25px;
+ position: relative;
+ top: 20px;
+ left: 40px;
+ background: green;
+}
+#one {
+ view-transition-name: target-one;
+ clip-path: url(#clip1);
+}
+#two {
+ view-transition-name: target-two;
+ clip-path: url(#clip2);
+}
+
+html::view-transition-group(target-one),
+html::view-transition-group(target-two) { animation-duration: 300s; }
+html::view-transition-old(target-one),
+html::view-transition-old(target-two) { animation: unset; opacity: 0; height: 100%; }
+html::view-transition-new(target-one),
+html::view-transition-new(target-two) {
+ animation: unset;
+ opacity: 1;
+ /* clip overflow, and verify inner contents only */
+ overflow: hidden;
+ height: 100%;
+}
+
+html::view-transition-group(root) { animation: unset; opacity: 0; }
+html::view-transition { background: lightpink; }
+</style>
+
+<div id=one class=target>
+ <div class=child>
+ <div class=grandchild></div>
+ </div>
+</div>
+<div style="height: 20px;"></div>
+<div id=two class=target>
+ <div class=child>
+ <div class=grandchild></div>
+ </div>
+</div>
+
+<svg>
+ <defs>
+ <clipPath id="clip1">
+ <rect x="10" y="20" width="70" height="50" />
+ </clipPath>
+ <clipPath id="clip2">
+ <rect x="-10" y="20" width="130" height="50" />
+ </clipPath>
+ </defs>
+</svg>
+
+<script>
+failIfNot(document.startViewTransition, "Missing document.startViewTransition");
+
+async function runTest() {
+ document.startViewTransition(() =>
+ requestAnimationFrame(() => requestAnimationFrame(takeScreenshot)));
+}
+onload = () => requestAnimationFrame(() => requestAnimationFrame(runTest));
+</script>
+
diff --git a/testing/web-platform/tests/css/css-view-transitions/new-content-object-view-box-clip-path.html b/testing/web-platform/tests/css/css-view-transitions/new-content-object-view-box-clip-path.html
new file mode 100644
index 0000000000..e1b6c92d2a
--- /dev/null
+++ b/testing/web-platform/tests/css/css-view-transitions/new-content-object-view-box-clip-path.html
@@ -0,0 +1,82 @@
+<!DOCTYPE html>
+<html class=reftest-wait>
+<title>Shared transitions: object-view-box with larger clip-path</title>
+<link rel="help" href="https://github.com/WICG/view-transitions">
+<link rel="author" href="mailto:vmpstr@chromium.org">
+<link rel="match" href="new-content-object-view-box-clip-path-ref.html">
+<script src="/common/reftest-wait.js"></script>
+<style>
+.target {
+ color: red;
+ width: 100px;
+ height: 100px;
+ contain: paint;
+ overflow-clip-margin: 1000px;
+ position: relative;
+ top: 50px;
+ left: 50px;
+}
+.child {
+ width: 123px;
+ height: 150px;
+ background: lightblue;
+ position: relative;
+ top: -10px;
+ left: -20px;
+}
+.grandchild {
+ width: 25px;
+ height: 25px;
+ position: relative;
+ top: 20px;
+ left: 40px;
+ background: green;
+}
+#one {
+ view-transition-name: target-one;
+ clip-path: inset(10px 12px 20px 28px);
+}
+#two {
+ view-transition-name: target-two;
+ clip-path: inset(10px -12px 20px -28px);
+}
+
+html::view-transition-group(target-one),
+html::view-transition-group(target-two) { animation-duration: 300s; }
+html::view-transition-old(target-one),
+html::view-transition-old(target-two) { animation: unset; opacity: 0; height: 100%; }
+html::view-transition-new(target-one),
+html::view-transition-new(target-two) {
+ animation: unset;
+ opacity: 1;
+ /* clip overflow, and verify inner contents only */
+ overflow: hidden;
+ height: 100%;
+}
+
+html::view-transition-group(root) { animation: unset; opacity: 0; }
+html::view-transition { background: lightpink; }
+</style>
+
+<div id=one class=target>
+ <div class=child>
+ <div class=grandchild></div>
+ </div>
+</div>
+<div style="height: 20px;"></div>
+<div id=two class=target>
+ <div class=child>
+ <div class=grandchild></div>
+ </div>
+</div>
+
+<script>
+failIfNot(document.startViewTransition, "Missing document.startViewTransition");
+
+async function runTest() {
+ document.startViewTransition(() =>
+ requestAnimationFrame(() => requestAnimationFrame(takeScreenshot)));
+}
+onload = () => requestAnimationFrame(() => requestAnimationFrame(runTest));
+</script>
+
diff --git a/testing/web-platform/tests/css/css-view-transitions/new-content-object-view-box-overflow-clipped-ref.html b/testing/web-platform/tests/css/css-view-transitions/new-content-object-view-box-overflow-clipped-ref.html
new file mode 100644
index 0000000000..2b55f1537d
--- /dev/null
+++ b/testing/web-platform/tests/css/css-view-transitions/new-content-object-view-box-overflow-clipped-ref.html
@@ -0,0 +1,38 @@
+<!DOCTYPE html>
+<title>Shared transitions: object-view-box with larger overflow (ref)</title>
+<link rel="help" href="https://github.com/WICG/view-transitions">
+<link rel="author" href="mailto:vmpstr@chromium.org">
+<style>
+.target {
+ color: red;
+ width: 100px;
+ height: 100px;
+ contain: paint;
+ position: relative;
+ top: 50px;
+ left: 50px;
+}
+.child {
+ width: 123px;
+ height: 150px;
+ background: lightblue;
+ position: relative;
+ top: -10px;
+ left: -20px;
+}
+.grandchild {
+ width: 25px;
+ height: 25px;
+ position: relative;
+ top: 20px;
+ left: 40px;
+ background: green;
+}
+body { background: lightpink; }
+</style>
+
+<div class=target>
+ <div class=child>
+ <div class=grandchild></div>
+ </div>
+</div>
diff --git a/testing/web-platform/tests/css/css-view-transitions/new-content-object-view-box-overflow-clipped.html b/testing/web-platform/tests/css/css-view-transitions/new-content-object-view-box-overflow-clipped.html
new file mode 100644
index 0000000000..f856a89433
--- /dev/null
+++ b/testing/web-platform/tests/css/css-view-transitions/new-content-object-view-box-overflow-clipped.html
@@ -0,0 +1,67 @@
+<!DOCTYPE html>
+<html class=reftest-wait>
+<title>Shared transitions: object-view-box with larger overflow</title>
+<link rel="help" href="https://github.com/WICG/view-transitions">
+<link rel="author" href="mailto:vmpstr@chromium.org">
+<link rel="match" href="new-content-object-view-box-overflow-clipped-ref.html">
+<script src="/common/reftest-wait.js"></script>
+<style>
+.target {
+ color: red;
+ width: 100px;
+ height: 100px;
+ contain: paint;
+ overflow-clip-margin: 10px;
+ position: relative;
+ top: 50px;
+ left: 50px;
+ view-transition-name: target;
+}
+.child {
+ width: 123px;
+ height: 150px;
+ background: lightblue;
+ position: relative;
+ top: -10px;
+ left: -20px;
+}
+.grandchild {
+ width: 25px;
+ height: 25px;
+ position: relative;
+ top: 20px;
+ left: 40px;
+ background: green;
+}
+
+html::view-transition-group(target) { animation-duration: 300s; }
+html::view-transition-new(target) {
+ animation: unset;
+ opacity: 1;
+
+ /* clip overflow, and verify inner contents only */
+ overflow: hidden;
+ height: 100%;
+}
+html::view-transition-old(target) { animation: unset; opacity: 0; height: 100%; }
+
+html::view-transition-group(root) { animation: unset; opacity: 0; }
+html::view-transition { background: lightpink; }
+</style>
+
+<div class=target>
+ <div class=child>
+ <div class=grandchild></div>
+ </div>
+</div>
+
+<script>
+failIfNot(document.startViewTransition, "Missing document.startViewTransition");
+
+async function runTest() {
+ document.startViewTransition(() =>
+ requestAnimationFrame(() => requestAnimationFrame(takeScreenshot)));
+}
+onload = () => requestAnimationFrame(() => requestAnimationFrame(runTest));
+</script>
+
diff --git a/testing/web-platform/tests/css/css-view-transitions/new-content-object-view-box-overflow-ref.html b/testing/web-platform/tests/css/css-view-transitions/new-content-object-view-box-overflow-ref.html
new file mode 100644
index 0000000000..2b55f1537d
--- /dev/null
+++ b/testing/web-platform/tests/css/css-view-transitions/new-content-object-view-box-overflow-ref.html
@@ -0,0 +1,38 @@
+<!DOCTYPE html>
+<title>Shared transitions: object-view-box with larger overflow (ref)</title>
+<link rel="help" href="https://github.com/WICG/view-transitions">
+<link rel="author" href="mailto:vmpstr@chromium.org">
+<style>
+.target {
+ color: red;
+ width: 100px;
+ height: 100px;
+ contain: paint;
+ position: relative;
+ top: 50px;
+ left: 50px;
+}
+.child {
+ width: 123px;
+ height: 150px;
+ background: lightblue;
+ position: relative;
+ top: -10px;
+ left: -20px;
+}
+.grandchild {
+ width: 25px;
+ height: 25px;
+ position: relative;
+ top: 20px;
+ left: 40px;
+ background: green;
+}
+body { background: lightpink; }
+</style>
+
+<div class=target>
+ <div class=child>
+ <div class=grandchild></div>
+ </div>
+</div>
diff --git a/testing/web-platform/tests/css/css-view-transitions/new-content-object-view-box-overflow.html b/testing/web-platform/tests/css/css-view-transitions/new-content-object-view-box-overflow.html
new file mode 100644
index 0000000000..08a12c23e5
--- /dev/null
+++ b/testing/web-platform/tests/css/css-view-transitions/new-content-object-view-box-overflow.html
@@ -0,0 +1,67 @@
+<!DOCTYPE html>
+<html class=reftest-wait>
+<title>Shared transitions: object-view-box with larger overflow</title>
+<link rel="help" href="https://github.com/WICG/view-transitions">
+<link rel="author" href="mailto:vmpstr@chromium.org">
+<link rel="match" href="new-content-object-view-box-overflow-ref.html">
+<script src="/common/reftest-wait.js"></script>
+<style>
+.target {
+ color: red;
+ width: 100px;
+ height: 100px;
+ contain: paint;
+ overflow-clip-margin: 1000px;
+ position: relative;
+ top: 50px;
+ left: 50px;
+ view-transition-name: target;
+}
+.child {
+ width: 123px;
+ height: 150px;
+ background: lightblue;
+ position: relative;
+ top: -10px;
+ left: -20px;
+}
+.grandchild {
+ width: 25px;
+ height: 25px;
+ position: relative;
+ top: 20px;
+ left: 40px;
+ background: green;
+}
+
+html::view-transition-group(target) { animation-duration: 300s; }
+html::view-transition-new(target) {
+ animation: unset;
+ opacity: 1;
+
+ /* clip overflow, and verify inner contents only */
+ overflow: hidden;
+ height: 100%;
+}
+html::view-transition-old(target) { animation: unset; opacity: 0; height: 100%; }
+
+html::view-transition-group(root) { animation: unset; opacity: 0; }
+html::view-transition { background: lightpink; }
+</style>
+
+<div class=target>
+ <div class=child>
+ <div class=grandchild></div>
+ </div>
+</div>
+
+<script>
+failIfNot(document.startViewTransition, "Missing document.startViewTransition");
+
+async function runTest() {
+ document.startViewTransition(() =>
+ requestAnimationFrame(() => requestAnimationFrame(takeScreenshot)));
+}
+onload = () => requestAnimationFrame(() => requestAnimationFrame(runTest));
+</script>
+
diff --git a/testing/web-platform/tests/css/css-view-transitions/new-content-scaling-ref.html b/testing/web-platform/tests/css/css-view-transitions/new-content-scaling-ref.html
new file mode 100644
index 0000000000..bcd195fc26
--- /dev/null
+++ b/testing/web-platform/tests/css/css-view-transitions/new-content-scaling-ref.html
@@ -0,0 +1,21 @@
+<!DOCTYPE html>
+<title>Shared transitions: display content in a pseudo with proper scaling (ref)</title>
+<link rel="help" href="https://github.com/WICG/view-transitions">
+<link rel="author" href="mailto:vmpstr@chromium.org">
+<style>
+.inner {
+ position: absolute;
+ inset: 4px;
+ background: green;
+}
+.dst {
+ position: relative;
+ width: 100px;
+ height: 100px;
+ border: 1px solid blue;
+ box-sizing: border-box;
+}
+body { background: lightpink; }
+</style>
+
+<div class=dst><div class=inner></div></div>
diff --git a/testing/web-platform/tests/css/css-view-transitions/new-content-scaling.html b/testing/web-platform/tests/css/css-view-transitions/new-content-scaling.html
new file mode 100644
index 0000000000..9fc70e39af
--- /dev/null
+++ b/testing/web-platform/tests/css/css-view-transitions/new-content-scaling.html
@@ -0,0 +1,63 @@
+<!DOCTYPE html>
+<html class=reftest-wait>
+<title>Shared transitions: display content in a pseudo with proper scaling</title>
+<link rel="help" href="https://github.com/WICG/view-transitions">
+<link rel="author" href="mailto:vmpstr@chromium.org">
+<link rel="match" href="new-content-scaling-ref.html">
+<meta name="fuzzy" content="new-content-scaling-ref.html:maxDifference=0-16;totalPixels=0-400">
+<script src="/common/reftest-wait.js"></script>
+<style>
+.shared {
+ view-transition-name: shared;
+ contain: paint;
+}
+.src {
+ position: relative;
+ width: 100px;
+ height: 100px;
+}
+.inner {
+ position: absolute;
+ inset: 20px;
+ background: green;
+}
+.dst {
+ position: relative;
+ width: 500px;
+ height: 500px;
+ border: 5px solid blue;
+ box-sizing: border-box;
+}
+
+html::view-transition-group(shared) {
+ animation-delay: 500s;
+}
+
+html::view-transition-new(shared) {
+ animation: unset;
+ opacity: 1;
+}
+html::view-transition-old(shared) {
+ animation: unset;
+ opacity: 0;
+}
+
+html::view-transition-group(root) { animation: unset; opacity: 0; }
+html::view-transition { background: lightpink; }
+</style>
+
+<div id=target class="shared src"><div class=inner></div></div>
+
+<script>
+failIfNot(document.startViewTransition, "Missing document.startViewTransition");
+
+async function runTest() {
+ let t = document.startViewTransition(() => {
+ target.classList.remove("src");
+ target.classList.add("dst");
+ requestAnimationFrame(() => requestAnimationFrame(takeScreenshot));
+ });
+}
+onload = () => requestAnimationFrame(() => requestAnimationFrame(runTest));
+</script>
+
diff --git a/testing/web-platform/tests/css/css-view-transitions/new-content-with-overflow-zoomed.html b/testing/web-platform/tests/css/css-view-transitions/new-content-with-overflow-zoomed.html
new file mode 100644
index 0000000000..1919daafa2
--- /dev/null
+++ b/testing/web-platform/tests/css/css-view-transitions/new-content-with-overflow-zoomed.html
@@ -0,0 +1,56 @@
+<!DOCTYPE html>
+<html class=reftest-wait>
+<title>Shared transitions: shared element with overflow</title>
+<link rel="help" href="https://github.com/WICG/view-transitions">
+<link rel="author" href="mailto:khushalsagar@chromium.org">
+<link rel="match" href="content-with-overflow-zoomed-ref.html">
+<script src="/common/reftest-wait.js"></script>
+<style>
+.target {
+ width: 80px;
+ height: 80px;
+ contain: paint;
+ background: blue;
+ overflow-clip-margin: 50px;
+ view-transition-name: target;
+ zoom: 1.5;
+}
+.child {
+ width: 200px;
+ height: 200px;
+ position: relative;
+ top: 50px;
+ left: 50px;
+ background: green;
+ zoom: 1.2;
+}
+
+html::view-transition-group(target) { animation-duration: 300s; }
+html::view-transition-old(target) { animation: unset; opacity: 0; }
+html::view-transition-new(target) {
+ animation: unset;
+ opacity: 1;
+ border: 3px solid black;
+}
+
+html::view-transition-group(root) { animation: unset; opacity: 0; }
+html::view-transition { background: lightpink; }
+</style>
+
+<div class=ancestor>
+ <div class=target>
+ <div class=child>
+ </div>
+ </div>
+</div>
+
+<script>
+failIfNot(document.startViewTransition, "Missing document.startViewTransition");
+
+async function runTest() {
+ document.startViewTransition(() =>
+ requestAnimationFrame(() => requestAnimationFrame(takeScreenshot)));
+}
+onload = () => requestAnimationFrame(() => requestAnimationFrame(runTest));
+</script>
+
diff --git a/testing/web-platform/tests/css/css-view-transitions/new-content-with-overflow.html b/testing/web-platform/tests/css/css-view-transitions/new-content-with-overflow.html
new file mode 100644
index 0000000000..2dc0185f70
--- /dev/null
+++ b/testing/web-platform/tests/css/css-view-transitions/new-content-with-overflow.html
@@ -0,0 +1,51 @@
+<!DOCTYPE html>
+<html class=reftest-wait>
+<title>Shared transitions: shared element with overflow</title>
+<link rel="help" href="https://github.com/WICG/view-transitions">
+<link rel="author" href="mailto:khushalsagar@chromium.org">
+<link rel="match" href="content-with-overflow-ref.html">
+<script src="/common/reftest-wait.js"></script>
+<style>
+.target {
+ width: 100px;
+ height: 100px;
+ contain: paint;
+ background: blue;
+ overflow-clip-margin: 50px;
+ view-transition-name: target;
+}
+.child {
+ width: 200px;
+ height: 200px;
+ position: relative;
+ top: 50px;
+ left: 50px;
+ background: green;
+}
+
+html::view-transition-group(target) { animation-duration: 300s; }
+html::view-transition-old(target) { animation: unset; opacity: 0; }
+html::view-transition-new(target) {
+ animation: unset;
+ opacity: 1;
+}
+
+html::view-transition-group(root) { animation: unset; opacity: 0; }
+html::view-transition { background: lightpink; }
+</style>
+
+<div class=target>
+ <div class=child>
+ </div>
+</div>
+
+<script>
+failIfNot(document.startViewTransition, "Missing document.startViewTransition");
+
+async function runTest() {
+ document.startViewTransition(() =>
+ requestAnimationFrame(() => requestAnimationFrame(takeScreenshot)));
+}
+onload = () => requestAnimationFrame(() => requestAnimationFrame(runTest));
+</script>
+
diff --git a/testing/web-platform/tests/css/css-view-transitions/new-element-on-start-ref.html b/testing/web-platform/tests/css/css-view-transitions/new-element-on-start-ref.html
new file mode 100644
index 0000000000..b721b4d54e
--- /dev/null
+++ b/testing/web-platform/tests/css/css-view-transitions/new-element-on-start-ref.html
@@ -0,0 +1,19 @@
+<!DOCTYPE html>
+<title>Shared transitions: one element captured for two tags (ref)</title>
+<link rel="help" href="https://github.com/WICG/view-transitions">
+<link rel="author" href="mailto:vmpstr@chromium.org">
+<style>
+div {
+ width: 100px;
+ height: 100px;
+ contain: paint;
+ position: absolute;
+ top: 50px;
+ background: black;
+ left: 200px;
+ filter: invert(1);
+}
+body { background: lightpink; }
+</style>
+<div></div>
+
diff --git a/testing/web-platform/tests/css/css-view-transitions/new-element-on-start.html b/testing/web-platform/tests/css/css-view-transitions/new-element-on-start.html
new file mode 100644
index 0000000000..da404a6af6
--- /dev/null
+++ b/testing/web-platform/tests/css/css-view-transitions/new-element-on-start.html
@@ -0,0 +1,69 @@
+<!DOCTYPE html>
+<html class=reftest-wait>
+<title>Shared transitions: new element tag specified for start phase</title>
+<link rel="help" href="https://github.com/WICG/view-transitions">
+<link rel="author" href="mailto:vmpstr@chromium.org">
+<link rel="match" href="new-element-on-start-ref.html">
+
+<script src="/common/reftest-wait.js"></script>
+<style>
+div {
+ width: 100px;
+ height: 100px;
+ contain: paint;
+ position: absolute;
+ top: 50px;
+}
+
+.before {
+ background: lightblue;
+ left: 50px;
+}
+.after {
+ background: black;
+ left: 200px;
+}
+.hidden {
+ background: red;
+ left: 350px;
+}
+
+html::view-transition-group(hidden) { animation-duration: 300s; }
+html::view-transition-image-pair(hidden) { opacity: 0; }
+
+html::view-transition-group(before) { animation-duration: 0s; }
+html::view-transition-image-pair(before) { filter: invert(1); }
+html::view-transition-new(before) { animation-duration: 0s; }
+html::view-transition-old(before) { animation-duration: 0s; }
+
+html::view-transition-group(after) { animation-duration: 0s; }
+html::view-transition-image-pair(after) { filter: invert(1); }
+html::view-transition-new(after) { animation-duration: 0s; }
+html::view-transition-old(after) { animation-duration: 0s; }
+
+html::view-transition-group(root) { animation: unset; opacity: 0; }
+html::view-transition { background: lightpink; }
+
+</style>
+
+<div id=before class=before></div>
+<div id=after class=after></div>
+
+<div id=hidden class=hidden></div>
+
+<script>
+failIfNot(document.startViewTransition, "Missing document.startViewTransition");
+
+async function runTest() {
+ hidden.style.viewTransitionName = "hidden";
+ before.style.viewTransitionName = "before";
+ let transition = document.startViewTransition(() => {
+ before.remove();
+ hidden.style.viewTransitionName = "";
+ after.style.viewTransitionName = "after";
+ });
+ transition.ready.then(() => requestAnimationFrame(() => requestAnimationFrame(takeScreenshot)));
+}
+onload = () => requestAnimationFrame(() => requestAnimationFrame(runTest));
+</script>
+
diff --git a/testing/web-platform/tests/css/css-view-transitions/new-root-vertical-writing-mode-ref.html b/testing/web-platform/tests/css/css-view-transitions/new-root-vertical-writing-mode-ref.html
new file mode 100644
index 0000000000..6a0f1c4f25
--- /dev/null
+++ b/testing/web-platform/tests/css/css-view-transitions/new-root-vertical-writing-mode-ref.html
@@ -0,0 +1,22 @@
+<!DOCTYPE html>
+<title>Shared transitions: container of shared element writing-modes (ref)</title>
+<link rel="help" href="https://github.com/WICG/view-transitions">
+<link rel="author" href="mailto:vmpstr@chromium.org">
+
+<style>
+html { writing-mode: vertical-lr; }
+.shared {
+ margin: 2px;
+ width: 90px;
+ height: 50px;
+ background: green;
+ contain: paint;
+}
+#two {
+ background: lightblue;
+}
+</style>
+
+<div id=one class=shared>T</div>
+<div id=two class=shared></div>
+
diff --git a/testing/web-platform/tests/css/css-view-transitions/new-root-vertical-writing-mode.html b/testing/web-platform/tests/css/css-view-transitions/new-root-vertical-writing-mode.html
new file mode 100644
index 0000000000..fc7d7de277
--- /dev/null
+++ b/testing/web-platform/tests/css/css-view-transitions/new-root-vertical-writing-mode.html
@@ -0,0 +1,73 @@
+<!DOCTYPE html>
+<html class=reftest-wait>
+<title>Shared transitions: container of shared element writing-modes</title>
+<link rel="help" href="https://github.com/WICG/view-transitions">
+<link rel="author" href="mailto:vmpstr@chromium.org">
+<link rel="match" href="new-root-vertical-writing-mode-ref.html">
+<script src="/common/reftest-wait.js"></script>
+<style>
+html { writing-mode: vertical-lr; }
+#hidden {
+ width: 100px;
+ height: 100px;
+ background: red;
+ position: absolute;
+ top: 0;
+ left: 0;
+ contain: paint;
+ view-transition-name: hidden;
+}
+.shared {
+ margin: 2px;
+ width: 90px;
+ height: 50px;
+ background: green;
+ contain: paint;
+}
+#target {
+ background: red;
+ position: absolute;
+ top: 50px;
+ left: 50px;
+ width: 100px;
+ height: 500px;
+ contain: paint;
+ view-transition-name: s1;
+}
+#two {
+ background: lightblue;
+}
+
+html::view-transition-group(hidden) { animation-duration: 300s; }
+html::view-transition-image-pair(hidden) { animation: unset; opacity: 0; }
+
+html::view-transition-group(s1) { animation-duration: 0s; }
+html::view-transition-new(s1) { animation: unset; opacity: 1; }
+html::view-transition-old(s1) { animation: unset; opacity: 0; }
+
+html::view-transition-new(root) { animation: unset; opacity: 1; }
+html::view-transition-old(root) { animation: unset; opacity: 0; }
+
+</style>
+
+<div id=hidden>Should not be visible</div>
+<div id=target>Should not be visible</div>
+<div id=one class=shared>T</div>
+<div id=two class=shared></div>
+
+<script>
+failIfNot(document.startViewTransition, "Missing document.startViewTransition");
+
+async function runTest() {
+ document.startViewTransition(() => {
+ target.remove();
+ hidden.style.left = "200px";
+ one.style.viewTransitionName = "s1";
+ requestAnimationFrame(() => requestAnimationFrame(takeScreenshot));
+ });
+}
+onload = () => requestAnimationFrame(() => requestAnimationFrame(runTest));
+</script>
+
+
+
diff --git a/testing/web-platform/tests/css/css-view-transitions/no-containment-on-new-element-mid-transition.html b/testing/web-platform/tests/css/css-view-transitions/no-containment-on-new-element-mid-transition.html
new file mode 100644
index 0000000000..551d2c41f7
--- /dev/null
+++ b/testing/web-platform/tests/css/css-view-transitions/no-containment-on-new-element-mid-transition.html
@@ -0,0 +1,38 @@
+<!DOCTYPE html>
+<html>
+<title>View transitions: transition skipped if no containment on new element after animation started</title>
+<link rel="help" href="https://www.w3.org/TR/css-view-transitions-1/">
+<link rel="author" href="mailto:khushalsagar@chromium.org">
+
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+
+<style>
+div {
+ width: 100px;
+ height: 100px;
+ background: blue;
+ view-transition-name: target;
+ contain: paint;
+}
+
+html::view-transition-group(target) {
+ animation-duration: 300s;
+}
+</style>
+
+<div id=first></div>
+
+<script>
+promise_test(async t => {
+ assert_implements(document.startViewTransition, "Missing document.startViewTransition");
+ return new Promise(async (resolve, reject) => {
+ let transition = document.startViewTransition();
+ await transition.domUpdated;
+ await transition.ready;
+
+ transition.finished.then(resolve, reject);
+ first.style.contain = "none";
+ });
+}, "new element becoming uncontained should skip the transition");
+</script>
diff --git a/testing/web-platform/tests/css/css-view-transitions/no-containment-on-new-element.html b/testing/web-platform/tests/css/css-view-transitions/no-containment-on-new-element.html
new file mode 100644
index 0000000000..46f576dbd5
--- /dev/null
+++ b/testing/web-platform/tests/css/css-view-transitions/no-containment-on-new-element.html
@@ -0,0 +1,47 @@
+<!DOCTYPE html>
+<html>
+<title>View transitions: transition skipped if no containment on new element</title>
+<link rel="help" href="https://www.w3.org/TR/css-view-transitions-1/">
+<link rel="author" href="mailto:khushalsagar@chromium.org">
+
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+
+<style>
+div {
+ width: 100px;
+ height: 100px;
+ background: blue;
+ view-transition-name: target;
+ contain: paint;
+}
+</style>
+
+<div id=first></div>
+
+<script>
+promise_test(async t => {
+ assert_implements(document.startViewTransition, "Missing document.startViewTransition");
+ return new Promise(async (resolve, reject) => {
+ let transition = document.startViewTransition(() => {
+ first.style.contain = "none";
+ });
+
+ let readyRejected = false;
+ transition.ready.then(reject, () => { readyRejected = true; });
+
+ let domUpdated = false;
+ transition.domUpdated.then(() => { domUpdated = true; }, reject);
+ transition.finished.then(() => {
+ assert_true(readyRejected, "ready not rejected");
+ assert_true(domUpdated, "dom not updated");
+
+ if (window.getComputedStyle(first).contain == "none")
+ resolve();
+ else
+ reject("dom update callback did not run");
+
+ }, reject);
+ });
+}, "uncontained new element should skip the transition");
+</script>
diff --git a/testing/web-platform/tests/css/css-view-transitions/no-containment-on-old-element.html b/testing/web-platform/tests/css/css-view-transitions/no-containment-on-old-element.html
new file mode 100644
index 0000000000..8b21916019
--- /dev/null
+++ b/testing/web-platform/tests/css/css-view-transitions/no-containment-on-old-element.html
@@ -0,0 +1,46 @@
+<!DOCTYPE html>
+<html>
+<title>View transitions: transition skipped if no containment on old element</title>
+<link rel="help" href="https://www.w3.org/TR/css-view-transitions-1/">
+<link rel="author" href="mailto:khushalsagar@chromium.org">
+
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+
+<style>
+div {
+ width: 100px;
+ height: 100px;
+ background: blue;
+ view-transition-name: target;
+}
+</style>
+
+<div id=first></div>
+
+<script>
+promise_test(async t => {
+ assert_implements(document.startViewTransition, "Missing document.startViewTransition");
+ return new Promise(async (resolve, reject) => {
+ let transition = document.startViewTransition(() => {
+ first.style.contain = "paint";
+ });
+
+ let readyRejected = false;
+ transition.ready.then(reject, () => { readyRejected = true; });
+
+ let domUpdated = false;
+ transition.domUpdated.then(() => { domUpdated = true; }, reject);
+ transition.finished.then(() => {
+ assert_true(readyRejected, "ready not rejected");
+ assert_true(domUpdated, "dom not updated");
+
+ if (window.getComputedStyle(first).contain == "paint")
+ resolve();
+ else
+ reject("dom update callback did not run");
+
+ }, reject);
+ });
+}, "uncontained old element should skip the transition");
+</script>
diff --git a/testing/web-platform/tests/css/css-view-transitions/no-crash-set-exception.html b/testing/web-platform/tests/css/css-view-transitions/no-crash-set-exception.html
new file mode 100644
index 0000000000..cb8942d112
--- /dev/null
+++ b/testing/web-platform/tests/css/css-view-transitions/no-crash-set-exception.html
@@ -0,0 +1,45 @@
+<!DOCTYPE html>
+<html>
+<title>Shared transitions: author styles ignored during prepare</title>
+<link rel="help" href="https://github.com/WICG/view-transitions">
+<link rel="author" href="mailto:khushalsagar@chromium.org">
+
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+
+<style>
+div {
+ width: 100px;
+ height: 100px;
+ background: blue;
+ contain: paint;
+ view-transition-name: shared;
+}
+
+html::view-transition,
+html::view-transition-group(shared),
+html::view-transition-image-pair(shared),
+html::view-transition-old(shared),
+html::view-transition-new(shared) {
+ background: blue;
+}
+</style>
+
+<div></div>
+
+<script>
+function validate_background(pseudoString) {
+ return window.getComputedStyle(document.documentElement, pseudoString).style.background != 'blue';
+}
+
+promise_test(async t => {
+ assert_implements(document.startViewTransition, "Missing document.startViewTransition");
+ return new Promise((resolve, reject) => {
+ document.startViewTransition(() => {
+ resolve();
+ throw 'error';
+ });
+ });
+}, "An exception thrown during a transition shouldn't crash.");
+
+</script>
diff --git a/testing/web-platform/tests/css/css-view-transitions/no-css-animation-while-render-blocked.html b/testing/web-platform/tests/css/css-view-transitions/no-css-animation-while-render-blocked.html
new file mode 100644
index 0000000000..4bc124ce66
--- /dev/null
+++ b/testing/web-platform/tests/css/css-view-transitions/no-css-animation-while-render-blocked.html
@@ -0,0 +1,59 @@
+<!DOCTYPE html>
+<meta name="timeout" content="long">
+<html>
+<title>Shared transitions: CSS Animations are paused while render-blocked</title>
+<link rel="help" href="https://github.com/WICG/view-transitions">
+<link rel="author" href="mailto:khushalsagar@chromium.org">
+
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+
+<style>
+@keyframes fade {
+ from {
+ opacity: 0;
+ }
+}
+
+div {
+ width: 100px;
+ height: 100px;
+ background: blue;
+ contain: paint;
+ view-transition-name: target;
+}
+
+.animated {
+ animation: fade 0.5s;
+}
+</style>
+
+<div id=target></div>
+
+<script>
+let renderBlocked = true;
+
+promise_test(() => {
+ assert_implements(document.startViewTransition, "Missing document.startViewTransition");
+ return new Promise(async (resolve, reject) => {
+ requestAnimationFrame(() => {
+ document.startViewTransition(() => {
+ return new Promise(async (inner_resolve) => {
+ step_timeout(() => {
+ renderBlocked = false;
+ inner_resolve();
+ }, 1000);
+ });
+ });
+
+ target.classList.toggle("animated");
+ target.onanimationend = () => {
+ if (renderBlocked)
+ reject();
+ else
+ resolve();
+ };
+ });
+ });
+}, "CSS animation is blocked until prepare callback");
+</script>
diff --git a/testing/web-platform/tests/css/css-view-transitions/no-raf-while-render-blocked.html b/testing/web-platform/tests/css/css-view-transitions/no-raf-while-render-blocked.html
new file mode 100644
index 0000000000..566d6f7e3e
--- /dev/null
+++ b/testing/web-platform/tests/css/css-view-transitions/no-raf-while-render-blocked.html
@@ -0,0 +1,48 @@
+<!DOCTYPE html>
+<meta name="timeout" content="long">
+<html>
+<title>Shared transitions: rAF is not issued while render-blocked</title>
+<link rel="help" href="https://github.com/WICG/view-transitions">
+<link rel="author" href="mailto:khushalsagar@chromium.org">
+
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+
+<style>
+div {
+ width: 100px;
+ height: 100px;
+ background: blue;
+ contain: paint;
+ view-transition-name: target;
+}
+</style>
+
+<div id=target></div>
+
+<script>
+let renderBlocked = true;
+
+promise_test(() => {
+ assert_implements(document.startViewTransition, "Missing document.startViewTransition");
+ return new Promise(async (resolve, reject) => {
+ requestAnimationFrame(() => {
+ document.startViewTransition(() => {
+ return new Promise(async (inner_resolve) => {
+ step_timeout(() => {
+ renderBlocked = false;
+ inner_resolve();
+ }, 1000);
+ });
+ });
+
+ requestAnimationFrame(() => {
+ if (renderBlocked)
+ reject();
+ else
+ resolve();
+ });
+ });
+ });
+}, "rAF is blocked until prepare callback");
+</script>
diff --git a/testing/web-platform/tests/css/css-view-transitions/no-root-capture-ref.html b/testing/web-platform/tests/css/css-view-transitions/no-root-capture-ref.html
new file mode 100644
index 0000000000..7d735626e0
--- /dev/null
+++ b/testing/web-platform/tests/css/css-view-transitions/no-root-capture-ref.html
@@ -0,0 +1,28 @@
+<!DOCTYPE html>
+<title>Shared transitions: shared element with overflow (ref)</title>
+<link rel="help" href="https://github.com/WICG/view-transitions">
+<link rel="author" href="mailto:khushalsagar@chromium.org">
+<style>
+.target {
+ width: 100px;
+ height: 100px;
+ contain: paint;
+ background: blue;
+ overflow-clip-margin: 50px;
+ view-transition-name: target;
+}
+.child {
+ width: 200px;
+ height: 200px;
+ position: relative;
+ top: 50px;
+ left: 50px;
+ background: green;
+}
+</style>
+
+This text should appear unmodified, since the root isn't captured.
+<div class=target>
+ <div class=child>
+ </div>
+</div>
diff --git a/testing/web-platform/tests/css/css-view-transitions/no-root-capture.html b/testing/web-platform/tests/css/css-view-transitions/no-root-capture.html
new file mode 100644
index 0000000000..7856a33297
--- /dev/null
+++ b/testing/web-platform/tests/css/css-view-transitions/no-root-capture.html
@@ -0,0 +1,54 @@
+<!DOCTYPE html>
+<html class=reftest-wait>
+<title>Shared transitions: shared element with overflow</title>
+<link rel="help" href="https://github.com/WICG/view-transitions">
+<link rel="author" href="mailto:vmpstr@chromium.org">
+<link rel="match" href="no-root-capture-ref.html">
+<script src="/common/reftest-wait.js"></script>
+<style>
+:root { view-transition-name: none; }
+.target {
+ width: 100px;
+ height: 100px;
+ contain: paint;
+ background: blue;
+ overflow-clip-margin: 50px;
+ view-transition-name: target;
+}
+.child {
+ width: 200px;
+ height: 200px;
+ position: relative;
+ top: 50px;
+ left: 50px;
+ background: green;
+}
+
+html::view-transition-group(target) { animation-duration: 300s; }
+html::view-transition-new(target) { animation: unset; opacity: 0; }
+html::view-transition-old(target) {
+ animation: unset;
+ opacity: 1;
+}
+
+/* None of these should apply, so make everything red if it does */
+html::view-transition-group(root) { animation: unset; opacity: 1; background: red; }
+html::view-transition-image-pair(root) { visibility: hidden }
+</style>
+
+This text should appear unmodified, since the root isn't captured.
+<div class=target>
+ <div class=child>
+ </div>
+</div>
+
+<script>
+failIfNot(document.startViewTransition, "Missing document.startViewTransition");
+
+async function runTest() {
+ document.startViewTransition(() =>
+ requestAnimationFrame(() => requestAnimationFrame(takeScreenshot)));
+}
+onload = () => requestAnimationFrame(() => requestAnimationFrame(runTest));
+</script>
+
diff --git a/testing/web-platform/tests/css/css-view-transitions/nothing-captured-ref.html b/testing/web-platform/tests/css/css-view-transitions/nothing-captured-ref.html
new file mode 100644
index 0000000000..7d735626e0
--- /dev/null
+++ b/testing/web-platform/tests/css/css-view-transitions/nothing-captured-ref.html
@@ -0,0 +1,28 @@
+<!DOCTYPE html>
+<title>Shared transitions: shared element with overflow (ref)</title>
+<link rel="help" href="https://github.com/WICG/view-transitions">
+<link rel="author" href="mailto:khushalsagar@chromium.org">
+<style>
+.target {
+ width: 100px;
+ height: 100px;
+ contain: paint;
+ background: blue;
+ overflow-clip-margin: 50px;
+ view-transition-name: target;
+}
+.child {
+ width: 200px;
+ height: 200px;
+ position: relative;
+ top: 50px;
+ left: 50px;
+ background: green;
+}
+</style>
+
+This text should appear unmodified, since the root isn't captured.
+<div class=target>
+ <div class=child>
+ </div>
+</div>
diff --git a/testing/web-platform/tests/css/css-view-transitions/nothing-captured.html b/testing/web-platform/tests/css/css-view-transitions/nothing-captured.html
new file mode 100644
index 0000000000..c6d45cec8f
--- /dev/null
+++ b/testing/web-platform/tests/css/css-view-transitions/nothing-captured.html
@@ -0,0 +1,47 @@
+<!DOCTYPE html>
+<html class=reftest-wait>
+<title>Shared transitions: shared element with overflow</title>
+<link rel="help" href="https://github.com/WICG/view-transitions">
+<link rel="author" href="mailto:vmpstr@chromium.org">
+<link rel="match" href="nothing-captured-ref.html">
+<script src="/common/reftest-wait.js"></script>
+<style>
+:root { view-transition-name: none; }
+.target {
+ width: 100px;
+ height: 100px;
+ contain: paint;
+ background: blue;
+ overflow-clip-margin: 50px;
+}
+.child {
+ width: 200px;
+ height: 200px;
+ position: relative;
+ top: 50px;
+ left: 50px;
+ background: green;
+}
+
+/* None of these should apply, so make everything red if it does */
+html::view-transition-group(*) { animation-duration: 300s; }
+html::view-transition-image-pair(*) { visibility: hidden }
+html::view-transition { background: red; }
+</style>
+
+This text should appear unmodified, since the root isn't captured.
+<div class=target>
+ <div class=child>
+ </div>
+</div>
+
+<script>
+failIfNot(document.startViewTransition, "Missing document.startViewTransition");
+
+async function runTest() {
+ document.startViewTransition(() =>
+ requestAnimationFrame(() => requestAnimationFrame(takeScreenshot)));
+}
+onload = () => requestAnimationFrame(() => requestAnimationFrame(runTest));
+</script>
+
diff --git a/testing/web-platform/tests/css/css-view-transitions/object-view-box-new-image.html b/testing/web-platform/tests/css/css-view-transitions/object-view-box-new-image.html
new file mode 100644
index 0000000000..c23e65f617
--- /dev/null
+++ b/testing/web-platform/tests/css/css-view-transitions/object-view-box-new-image.html
@@ -0,0 +1,70 @@
+<!DOCTYPE html>
+<html class=reftest-wait>
+<title>Shared transitions: object-view-box</title>
+<link rel="help" href="https://github.com/WICG/view-transitions">
+<link rel="author" href="mailto:khushalsagar@chromium.org">
+<link rel="match" href="object-view-box-ref.html">
+
+<script src="/common/reftest-wait.js"></script>
+<style>
+.target {
+ contain: paint;
+ width: 100px;
+ height: 100px;
+ transform: scale(2.0, 3.0);
+ position: relative;
+ top: 200px;
+ left: 200px;
+ view-transition-name: target;
+}
+
+.embedded {
+ width: 100%;
+ height: 50%;
+}
+
+.hidden {
+ contain: paint;
+ width: 10px;
+ height: 10px;
+ background: grey;
+ view-transition-name: hidden;
+}
+
+html::view-transition-group(hidden) { animation-duration: 300s; }
+html::view-transition-image-pair(hidden) { animation: unset; opacity: 0; }
+
+html::view-transition-old(target) {
+ animation: unset;
+ opacity: 0;
+ height: 100%;
+}
+html::view-transition-new(target) {
+ animation: unset;
+ opacity: 1;
+ object-view-box: inset(50px 0px 0px 0px);
+ object-fit: none;
+ object-position: 0% 0%;
+ height: 100%;
+ contain: paint;
+}
+
+</style>
+
+<div id="target" class="target">
+ <div class="embedded" style="background: green;"></div>
+ <div class="embedded" style="background: blue">SharedElement</div>
+</div>
+<div id=hidden class=hidden></div>
+
+<script>
+failIfNot(document.startViewTransition, "Missing document.startViewTransition");
+
+async function runTest() {
+ document.startViewTransition(() => {
+ requestAnimationFrame(() => requestAnimationFrame(takeScreenshot));
+ });
+}
+onload = () => requestAnimationFrame(runTest);
+</script>
+
diff --git a/testing/web-platform/tests/css/css-view-transitions/object-view-box-old-image.html b/testing/web-platform/tests/css/css-view-transitions/object-view-box-old-image.html
new file mode 100644
index 0000000000..9e4e4b83fb
--- /dev/null
+++ b/testing/web-platform/tests/css/css-view-transitions/object-view-box-old-image.html
@@ -0,0 +1,72 @@
+<!DOCTYPE html>
+<meta name="timeout" content="long">
+<html class=reftest-wait>
+<title>Shared transitions: object-view-box</title>
+<link rel="help" href="https://github.com/WICG/view-transitions">
+<link rel="author" href="mailto:khushalsagar@chromium.org">
+<link rel="match" href="object-view-box-ref.html">
+<meta name="fuzzy" content="object-view-box-ref.html:0-1;0-300">
+
+<script src="/common/reftest-wait.js"></script>
+<style>
+.target {
+ contain: paint;
+ width: 100px;
+ height: 100px;
+ transform: scale(2.0, 3.0);
+ position: relative;
+ top: 200px;
+ left: 200px;
+ view-transition-name: target;
+}
+
+.embedded {
+ width: 100%;
+ height: 50%;
+}
+
+.hidden {
+ contain: paint;
+ width: 10px;
+ height: 10px;
+ background: grey;
+ view-transition-name: hidden;
+}
+
+html::view-transition-group(hidden) { animation-duration: 300s; }
+html::view-transition-image-pair(hidden) { animation: unset; opacity: 0; }
+
+html::view-transition-new(target) {
+ animation: unset;
+ opacity: 0;
+ height: 100%;
+}
+html::view-transition-old(target) {
+ animation: unset;
+ opacity: 1;
+ object-view-box: inset(50px 0px 0px 0px);
+ object-fit: none;
+ object-position: 0% 0%;
+ height: 100%;
+ contain: paint;
+}
+
+</style>
+
+<div id="target" class="target">
+ <div class="embedded" style="background: green;"></div>
+ <div class="embedded" style="background: blue">SharedElement</div>
+</div>
+<div id=hidden class=hidden></div>
+
+<script>
+failIfNot(document.startViewTransition, "Missing document.startViewTransition");
+
+async function runTest() {
+ document.startViewTransition(() => {
+ requestAnimationFrame(() => requestAnimationFrame(takeScreenshot));
+ });
+}
+onload = () => requestAnimationFrame(runTest);
+</script>
+
diff --git a/testing/web-platform/tests/css/css-view-transitions/object-view-box-ref.html b/testing/web-platform/tests/css/css-view-transitions/object-view-box-ref.html
new file mode 100644
index 0000000000..1451e0d203
--- /dev/null
+++ b/testing/web-platform/tests/css/css-view-transitions/object-view-box-ref.html
@@ -0,0 +1,25 @@
+<!DOCTYPE html>
+<title>Shared transitions: object-view-box (ref)</title>
+<link rel="help" href="https://github.com/WICG/view-transitions">
+<link rel="author" href="mailto:vmpstr@chromium.org">
+<style>
+.target {
+ contain: paint;
+ width: 100px;
+ height: 100px;
+ transform: scale(2.0, 3.0);
+ position: relative;
+ top: 200px;
+ left: 200px;
+}
+.content {
+ width: 100px;
+ height: 50px;
+ background: blue;
+}
+
+</style>
+<div class="target">
+ <div class="content">SharedElement</div>
+</div>
+
diff --git a/testing/web-platform/tests/css/css-view-transitions/old-content-captures-clip-path-ref.html b/testing/web-platform/tests/css/css-view-transitions/old-content-captures-clip-path-ref.html
new file mode 100644
index 0000000000..168f4d8409
--- /dev/null
+++ b/testing/web-platform/tests/css/css-view-transitions/old-content-captures-clip-path-ref.html
@@ -0,0 +1,22 @@
+<!DOCTYPE html>
+<title>Shared transitions: capture clip-path elements (ref)</title>
+<link rel="help" href="https://github.com/WICG/view-transitions">
+<link rel="author" href="mailto:vmpstr@chromium.org">
+<style>
+.box {
+ color: red;
+ background: lightblue;
+ width: 100px;
+ height: 100px;
+ contain: paint;
+ position: absolute;
+ font-size: 30pt;
+}
+#e1 {
+ clip-path: polygon(50% 0, 100% 50%, 50% 100%, 0 50%);
+ top: 20px;
+ left: 20px;
+}
+body { background: lightpink; }
+</style>
+<div id=e1 class=box></div>
diff --git a/testing/web-platform/tests/css/css-view-transitions/old-content-captures-clip-path.html b/testing/web-platform/tests/css/css-view-transitions/old-content-captures-clip-path.html
new file mode 100644
index 0000000000..ac6200da16
--- /dev/null
+++ b/testing/web-platform/tests/css/css-view-transitions/old-content-captures-clip-path.html
@@ -0,0 +1,46 @@
+<!DOCTYPE html>
+<html class=reftest-wait>
+<title>Shared transitions: capture clip-path elements</title>
+<link rel="help" href="https://github.com/WICG/view-transitions">
+<link rel="author" href="mailto:vmpstr@chromium.org">
+<link rel="match" href="old-content-captures-clip-path-ref.html">
+<script src="/common/reftest-wait.js"></script>
+<style>
+.box {
+ color: red;
+ background: lightblue;
+ width: 100px;
+ height: 100px;
+ contain: paint;
+ position: absolute;
+ font-size: 30pt;
+}
+#e1 {
+ clip-path: polygon(50% 0, 100% 50%, 50% 100%, 0 50%);
+ top: 20px;
+ left: 20px;
+ view-transition-name: e1;
+}
+
+div.dst { background: lightgreen; }
+/* We're verifying what we capture, so just display the old contents for 5 minutes. */
+html::view-transition-group(*) { animation-duration: 300s; }
+html::view-transition-new(*) { animation: unset; opacity: 0; }
+html::view-transition-old(*) { animation: unset; opacity: 1; }
+/* hide the root so we show transition background to ensure we're in a transition */
+html::view-transition-group(root) { animation: unset; opacity: 0; }
+html::view-transition { background: lightpink; }
+</style>
+<div id=e1 class=box></div>
+<script>
+failIfNot(document.startViewTransition, "Missing document.startViewTransition");
+
+async function runTest() {
+ document.startViewTransition(() => {
+ e1.classList.add("dst");
+ requestAnimationFrame(() => requestAnimationFrame(takeScreenshot));
+ });
+}
+onload = () => requestAnimationFrame(() => requestAnimationFrame(runTest));
+</script>
+
diff --git a/testing/web-platform/tests/css/css-view-transitions/old-content-captures-different-size-ref.html b/testing/web-platform/tests/css/css-view-transitions/old-content-captures-different-size-ref.html
new file mode 100644
index 0000000000..9433681c75
--- /dev/null
+++ b/testing/web-platform/tests/css/css-view-transitions/old-content-captures-different-size-ref.html
@@ -0,0 +1,35 @@
+<!DOCTYPE html>
+<title>Shared transitions: capture elements with different size capture (ref)</title>
+<link rel="help" href="https://github.com/WICG/view-transitions">
+<link rel="author" href="mailto:vmpstr@chromium.org">
+<style>
+.box {
+ color: red;
+ background: lightblue;
+ width: 100px;
+ height: 100px;
+ contain: paint;
+ position: absolute;
+ font-size: 30pt;
+}
+#e1 {
+ clip-path: circle(30%);
+ top: 20px;
+ left: 20px;
+}
+#e2 {
+ clip-path: ellipse(70% 30%);
+ top: 160px;
+ left: 20px;
+}
+#e3 {
+ filter: blur(5px);
+ top: 300px;
+ left: 20px;
+}
+body { background: lightpink; }
+</style>
+<div id=e1 class=box>one</div>
+<div id=e2 class=box>two</div>
+<div id=e3 class=box>three</div>
+
diff --git a/testing/web-platform/tests/css/css-view-transitions/old-content-captures-different-size.html b/testing/web-platform/tests/css/css-view-transitions/old-content-captures-different-size.html
new file mode 100644
index 0000000000..8bfa2407e5
--- /dev/null
+++ b/testing/web-platform/tests/css/css-view-transitions/old-content-captures-different-size.html
@@ -0,0 +1,64 @@
+<!DOCTYPE html>
+<meta name="timeout" content="long">
+<html class=reftest-wait>
+<title>Shared transitions: capture elements with different size capture</title>
+<link rel="help" href="https://github.com/WICG/view-transitions">
+<link rel="author" href="mailto:vmpstr@chromium.org">
+<link rel="match" href="old-content-captures-different-size-ref.html">
+<meta name=fuzzy content="old-content-captures-different-size-ref.html:0-40;0-30000">
+<script src="/common/reftest-wait.js"></script>
+<style>
+.box {
+ color: red;
+ background: lightblue;
+ width: 100px;
+ height: 100px;
+ contain: paint;
+ position: absolute;
+ font-size: 30pt;
+}
+#e1 {
+ clip-path: circle(30%);
+ top: 20px;
+ left: 20px;
+ view-transition-name: e1;
+}
+#e2 {
+ clip-path: ellipse(70% 30%);
+ top: 160px;
+ left: 20px;
+ view-transition-name: e2;
+}
+#e3 {
+ filter: blur(5px);
+ top: 300px;
+ left: 20px;
+ view-transition-name: e3;
+}
+
+div.dst { background: lightgreen; }
+/* We're verifying what we capture, so just display the old contents for 5 minutes. */
+html::view-transition-group(*) { animation-duration: 300s; }
+html::view-transition-new(*) { animation: unset; opacity: 0; }
+html::view-transition-old(*) { animation: unset; opacity: 1; }
+/* hide the root so we show transition background to ensure we're in a transition */
+html::view-transition-group(root) { animation: unset; opacity: 0; }
+html::view-transition { background: lightpink; }
+</style>
+<div id=e1 class=box>one</div>
+<div id=e2 class=box>two</div>
+<div id=e3 class=box>three</div>
+<script>
+failIfNot(document.startViewTransition, "Missing document.startViewTransition");
+
+async function runTest() {
+ document.startViewTransition(() => {
+ e1.classList.add("dst");
+ e2.classList.add("dst");
+ e3.classList.add("dst");
+ requestAnimationFrame(() => requestAnimationFrame(takeScreenshot));
+ });
+}
+onload = () => requestAnimationFrame(() => requestAnimationFrame(runTest));
+</script>
+
diff --git a/testing/web-platform/tests/css/css-view-transitions/old-content-captures-opacity-ref.html b/testing/web-platform/tests/css/css-view-transitions/old-content-captures-opacity-ref.html
new file mode 100644
index 0000000000..10964ce9f1
--- /dev/null
+++ b/testing/web-platform/tests/css/css-view-transitions/old-content-captures-opacity-ref.html
@@ -0,0 +1,24 @@
+<!DOCTYPE html>
+<title>Shared transitions: capture opacity elements (ref)</title>
+<link rel="help" href="https://github.com/WICG/view-transitions">
+<link rel="author" href="mailto:vmpstr@chromium.org">
+<style>
+.box {
+ color: red;
+ background: lightblue;
+ width: 100px;
+ height: 100px;
+ contain: paint;
+ position: absolute;
+ font-size: 30pt;
+ will-change: opacity;
+}
+#e1 { opacity: 0.75; top: 20px; left: 20px; }
+#e2 { opacity: 0.5; top: 160px; left: 20px; }
+#e3 { opacity: 0.25; top: 300px; left: 20px; }
+body { background: lightpink; }
+</style>
+<div id=e1 class=box>one</div>
+<div id=e2 class=box>two</div>
+<div id=e3 class=box>three</div>
+
diff --git a/testing/web-platform/tests/css/css-view-transitions/old-content-captures-opacity.html b/testing/web-platform/tests/css/css-view-transitions/old-content-captures-opacity.html
new file mode 100644
index 0000000000..a1d976d5f5
--- /dev/null
+++ b/testing/web-platform/tests/css/css-view-transitions/old-content-captures-opacity.html
@@ -0,0 +1,48 @@
+<!DOCTYPE html>
+<html class=reftest-wait>
+<title>Shared transitions: capture opacity elements</title>
+<link rel="help" href="https://github.com/WICG/view-transitions">
+<link rel="author" href="mailto:vmpstr@chromium.org">
+<link rel="match" href="old-content-captures-opacity-ref.html">
+<meta name=fuzzy content="old-content-captures-opacity-ref.html:0-1;0-50000">
+
+<script src="/common/reftest-wait.js"></script>
+<style>
+.box {
+ color: red;
+ background: lightblue;
+ width: 100px;
+ height: 100px;
+ contain: paint;
+ position: absolute;
+ font-size: 30pt;
+}
+#e1 { opacity: 0.75; top: 20px; left: 20px; view-transition-name: e1; }
+#e2 { opacity: 0.5; top: 160px; left: 20px; view-transition-name: e2; }
+#e3 { opacity: 0.25; top: 300px; left: 20px; view-transition-name: e3; }
+div.dst { background: lightgreen; }
+/* We're verifying what we capture, so just display the old contents for 5 minutes. */
+html::view-transition-group(*) { animation-duration: 300s; }
+html::view-transition-new(*) { animation: unset; opacity: 0; }
+html::view-transition-old(*) { animation: unset; opacity: 1; }
+/* hide the root so we show transition background to ensure we're in a transition */
+html::view-transition-group(root) { animation: unset; opacity: 0; }
+html::view-transition { background: lightpink; }
+</style>
+<div id=e1 class=box>one</div>
+<div id=e2 class=box>two</div>
+<div id=e3 class=box>three</div>
+<script>
+failIfNot(document.startViewTransition, "Missing document.startViewTransition");
+
+async function runTest() {
+ document.startViewTransition(() => {
+ e1.classList.add("dst");
+ e2.classList.add("dst");
+ e3.classList.add("dst");
+ requestAnimationFrame(() => requestAnimationFrame(takeScreenshot));
+ });
+}
+onload = () => requestAnimationFrame(() => requestAnimationFrame(runTest));
+</script>
+
diff --git a/testing/web-platform/tests/css/css-view-transitions/old-content-captures-root-ref.html b/testing/web-platform/tests/css/css-view-transitions/old-content-captures-root-ref.html
new file mode 100644
index 0000000000..1222d6440b
--- /dev/null
+++ b/testing/web-platform/tests/css/css-view-transitions/old-content-captures-root-ref.html
@@ -0,0 +1,19 @@
+<!DOCTYPE html>
+<title>Shared transitions: capture root elements (ref)</title>
+<link rel="help" href="https://github.com/WICG/view-transitions">
+<link rel="author" href="mailto:vmpstr@chromium.org">
+<style>
+.box {
+ background: lightblue;
+ width: 100px;
+ height: 100px;
+ contain: paint;
+ position: absolute;
+ font-size: 30pt;
+}
+#e1 {
+ top: 20px;
+ left: 20px;
+}
+</style>
+<div id=e1 class=box></div>
diff --git a/testing/web-platform/tests/css/css-view-transitions/old-content-captures-root.html b/testing/web-platform/tests/css/css-view-transitions/old-content-captures-root.html
new file mode 100644
index 0000000000..067c049818
--- /dev/null
+++ b/testing/web-platform/tests/css/css-view-transitions/old-content-captures-root.html
@@ -0,0 +1,51 @@
+<!DOCTYPE html>
+<html class=reftest-wait>
+<title>Shared transitions: capture root elements</title>
+<link rel="help" href="https://github.com/WICG/view-transitions">
+<link rel="author" href="mailto:vmpstr@chromium.org">
+<link rel="match" href="old-content-captures-root-ref.html">
+<meta name="fuzzy" content="old-content-captures-root-ref.html:0-1;0-500">
+<script src="/common/reftest-wait.js"></script>
+<style>
+.box {
+ background: lightblue;
+ width: 100px;
+ height: 100px;
+ contain: paint;
+ position: absolute;
+ font-size: 30pt;
+}
+#e1 {
+ top: 20px;
+ left: 20px;
+}
+#shared {
+ contain: paint;
+ width: 100px;
+ height: 100px;
+ background: red;
+ view-transition-name: shared;
+}
+
+div.dst { background: lightgreen; }
+/* We're verifying what we capture, so just display the old contents for 5 minutes. */
+html::view-transition { background: pink; }
+html::view-transition-group(shared) { animation-duration: 300s; }
+html::view-transition-image-pair(shared) { visibility: hidden }
+html::view-transition-old(root) { animation: unset; opacity: 1 }
+html::view-transition-new(root) { animation: unset; opacity: 0 }
+</style>
+<div id=e1 class=box></div>
+<div id=shared></div>
+<script>
+failIfNot(document.startViewTransition, "Missing document.startViewTransition");
+
+async function runTest() {
+ document.startViewTransition(() => {
+ e1.classList.add("dst");
+ document.body.style.background = "red";
+ requestAnimationFrame(() => requestAnimationFrame(takeScreenshot));
+ });
+}
+onload = () => requestAnimationFrame(() => requestAnimationFrame(runTest));
+</script>
diff --git a/testing/web-platform/tests/css/css-view-transitions/old-content-container-writing-modes-ref.html b/testing/web-platform/tests/css/css-view-transitions/old-content-container-writing-modes-ref.html
new file mode 100644
index 0000000000..e0a18aa6ed
--- /dev/null
+++ b/testing/web-platform/tests/css/css-view-transitions/old-content-container-writing-modes-ref.html
@@ -0,0 +1,24 @@
+<!DOCTYPE html>
+<title>Shared transitions: container of shared element writing-modes (ref)</title>
+<link rel="help" href="https://github.com/WICG/view-transitions">
+<link rel="author" href="mailto:vmpstr@chromium.org">
+
+<style>
+.tb { writing-mode: horizontal-tb; }
+.lr { writing-mode: vertical-lr; }
+.rl { writing-mode: vertical-rl; }
+.shared {
+ margin: 2px;
+ width: 100px;
+ height: 50px;
+ background: green;
+ contain: paint;
+ border: 1px solid black;
+}
+html { background: lightpink; }
+</style>
+
+<div class=tb><div id=one class=shared>T</div></div>
+<div class=lr><div id=two class=shared>T</div></div>
+<div class=rl><div id=three class=shared>T</div></div>
+
diff --git a/testing/web-platform/tests/css/css-view-transitions/old-content-container-writing-modes.html b/testing/web-platform/tests/css/css-view-transitions/old-content-container-writing-modes.html
new file mode 100644
index 0000000000..2c487440ac
--- /dev/null
+++ b/testing/web-platform/tests/css/css-view-transitions/old-content-container-writing-modes.html
@@ -0,0 +1,94 @@
+<!DOCTYPE html>
+<html class=reftest-wait>
+<title>Shared transitions: container of shared element writing-modes</title>
+<link rel="help" href="https://github.com/WICG/view-transitions">
+<link rel="author" href="mailto:vmpstr@chromium.org">
+<link rel="match" href="old-content-container-writing-modes-ref.html">
+<script src="/common/reftest-wait.js"></script>
+<style>
+#hidden {
+ width: 100px;
+ height: 100px;
+ background: red;
+ position: absolute;
+ top: 0;
+ left: 0;
+ contain: paint;
+ view-transition-name: hidden;
+}
+.tb { writing-mode: horizontal-tb; }
+.lr { writing-mode: vertical-lr; }
+.rl { writing-mode: vertical-rl; }
+.shared {
+ margin: 2px;
+ width: 100px;
+ height: 50px;
+ background: green;
+ contain: paint;
+ border: 1px solid black;
+}
+#target1, #target2, #target3 {
+ background: red;
+ position: absolute;
+ top: 50px;
+ left: 50px;
+ width: 100px;
+ height: 500px;
+ contain: paint;
+}
+#one { view-transition-name: s1; }
+#two { view-transition-name: s2; }
+#three { view-transition-name: s3; }
+
+html::view-transition-group(hidden) { animation-duration: 300s; }
+html::view-transition-image-pair(hidden) { animation: unset; opacity: 0; }
+
+html::view-transition-group(s1),
+html::view-transition-group(s2),
+html::view-transition-group(s3) {
+ animation-delay: 300s;
+ animation-fill-mode: both;
+}
+
+html::view-transition-new(s1),
+html::view-transition-new(s2),
+html::view-transition-new(s3) { animation: unset; opacity: 0; }
+
+html::view-transition-old(s1),
+html::view-transition-old(s2),
+html::view-transition-old(s3) { animation: unset; opacity: 1; }
+
+/* hide the root so we show transition background to ensure we're in a transition */
+html::view-transition-group(root) { animation: unset; opacity: 0; }
+html::view-transition { background: lightpink; }
+
+</style>
+
+<div id=hidden>Should not be visible</div>
+<div id=target1>Should not be visible</div>
+<div id=target2>Should not be visible</div>
+<div id=target3>Should not be visible</div>
+<div class=tb><div id=one class=shared>T</div></div>
+<div class=lr><div id=two class=shared>T</div></div>
+<div class=rl><div id=three class=shared>T</div></div>
+
+<script>
+failIfNot(document.startViewTransition, "Missing document.startViewTransition");
+
+async function runTest() {
+ document.startViewTransition(() => {
+ one.remove();
+ two.remove();
+ three.remove();
+ hidden.style.left = "200px";
+ target1.style.viewTransitionName = "s1";
+ target2.style.viewTransitionName = "s2";
+ target3.style.viewTransitionName = "s3";
+ requestAnimationFrame(() => requestAnimationFrame(takeScreenshot));
+ });
+}
+onload = () => requestAnimationFrame(() => requestAnimationFrame(runTest));
+</script>
+
+
+
diff --git a/testing/web-platform/tests/css/css-view-transitions/old-content-element-writing-modes-ref.html b/testing/web-platform/tests/css/css-view-transitions/old-content-element-writing-modes-ref.html
new file mode 100644
index 0000000000..8b351feaed
--- /dev/null
+++ b/testing/web-platform/tests/css/css-view-transitions/old-content-element-writing-modes-ref.html
@@ -0,0 +1,25 @@
+<!DOCTYPE html>
+<title>Shared transitions: shared element writing-modes (ref)</title>
+<link rel="help" href="https://github.com/WICG/view-transitions">
+<link rel="author" href="mailto:vmpstr@chromium.org">
+
+<style>
+.tb { writing-mode: horizontal-tb; }
+.lr { writing-mode: vertical-lr; }
+.rl { writing-mode: vertical-rl; }
+.shared {
+ margin: 2px;
+ width: 100px;
+ height: 50px;
+ background: green;
+ contain: paint;
+ border: 1px solid black;
+}
+html { background: lightpink; }
+</style>
+
+<div id=one class="tb shared">T</div>
+<div id=two class="lr shared">T</div>
+<div id=three class="rl shared">T</div>
+
+
diff --git a/testing/web-platform/tests/css/css-view-transitions/old-content-element-writing-modes.html b/testing/web-platform/tests/css/css-view-transitions/old-content-element-writing-modes.html
new file mode 100644
index 0000000000..87a736d124
--- /dev/null
+++ b/testing/web-platform/tests/css/css-view-transitions/old-content-element-writing-modes.html
@@ -0,0 +1,95 @@
+<!DOCTYPE html>
+<html class=reftest-wait>
+<title>Shared transitions: shared element writing-modes</title>
+<link rel="help" href="https://github.com/WICG/view-transitions">
+<link rel="author" href="mailto:vmpstr@chromium.org">
+<link rel="match" href="old-content-element-writing-modes-ref.html">
+<script src="/common/reftest-wait.js"></script>
+<style>
+#hidden {
+ width: 100px;
+ height: 100px;
+ background: red;
+ position: absolute;
+ top: 0;
+ left: 0;
+ contain: paint;
+ view-transition-name: hidden;
+}
+.tb { writing-mode: horizontal-tb; }
+.lr { writing-mode: vertical-lr; }
+.rl { writing-mode: vertical-rl; }
+.shared {
+ margin: 2px;
+ width: 100px;
+ height: 50px;
+ background: green;
+ contain: paint;
+ border: 1px solid black;
+}
+#target1, #target2, #target3 {
+ background: red;
+ position: absolute;
+ top: 50px;
+ left: 50px;
+ width: 100px;
+ height: 500px;
+ contain: paint;
+}
+#one { view-transition-name: s1; }
+#two { view-transition-name: s2; }
+#three { view-transition-name: s3; }
+
+html::view-transition-group(hidden) { animation-duration: 300s; }
+html::view-transition-image-pair(hidden) { animation: unset; opacity: 0; }
+
+html::view-transition-group(s1),
+html::view-transition-group(s2),
+html::view-transition-group(s3) {
+ animation-delay: 300s;
+ animation-fill-mode: both;
+}
+
+html::view-transition-new(s1),
+html::view-transition-new(s2),
+html::view-transition-new(s3) { animation: unset; opacity: 0; }
+
+html::view-transition-old(s1),
+html::view-transition-old(s2),
+html::view-transition-old(s3) { animation: unset; opacity: 1; }
+
+/* hide the root so we show transition background to ensure we're in a transition */
+html::view-transition-group(root) { animation: unset; opacity: 0; }
+html::view-transition { background: lightpink; }
+
+</style>
+
+<div id=hidden>Should not be visible</div>
+<div id=target1>Should not be visible</div>
+<div id=target2>Should not be visible</div>
+<div id=target3>Should not be visible</div>
+<div id=one class="shared tb">T</div>
+<div id=two class="shared lr">T</div>
+<div id=three class="shared rl">T</div>
+
+<script>
+failIfNot(document.startViewTransition, "Missing document.startViewTransition");
+
+async function runTest() {
+ document.startViewTransition(() => {
+ one.remove();
+ two.remove();
+ three.remove();
+ hidden.style.left = "200px";
+ target1.style.viewTransitionName = "s1";
+ target2.style.viewTransitionName = "s2";
+ target3.style.viewTransitionName = "s3";
+ requestAnimationFrame(() => requestAnimationFrame(takeScreenshot));
+ });
+}
+onload = () => requestAnimationFrame(() => requestAnimationFrame(runTest));
+</script>
+
+
+
+
diff --git a/testing/web-platform/tests/css/css-view-transitions/old-content-has-scrollbars-ref.html b/testing/web-platform/tests/css/css-view-transitions/old-content-has-scrollbars-ref.html
new file mode 100644
index 0000000000..ea7a0f7c14
--- /dev/null
+++ b/testing/web-platform/tests/css/css-view-transitions/old-content-has-scrollbars-ref.html
@@ -0,0 +1,30 @@
+<!DOCTYPE html>
+<title>Shared transitions: outgoing viewport has scrollbars (ref)</title>
+<link rel="help" href="https://github.com/WICG/view-transitions">
+<link rel="help" href="https://github.com/w3c/csswg-drafts/issues/7859">
+<link rel="author" href="mailto:bokan@chromium.org">
+<style>
+ html, body {
+ width: 100%;
+ height: 100%;
+ background-color: lightpink;
+ }
+ html {
+ overflow: hidden;
+ }
+ body {
+ margin: 50px;
+ }
+ div {
+ background-image:
+ linear-gradient(45deg, #000 25%, transparent 25%),
+ linear-gradient(45deg, transparent 75%, #000 75%),
+ linear-gradient(45deg, transparent 75%, #000 75%),
+ linear-gradient(45deg, #000 25%, lightgreen 25%);
+ background-size: 200px 200px;
+ background-position: 0 0, 0 0, -100px -100px, 100px 100px;
+ width: 200%;
+ height: 200%;
+ }
+</style>
+<div></div>
diff --git a/testing/web-platform/tests/css/css-view-transitions/old-content-has-scrollbars.html b/testing/web-platform/tests/css/css-view-transitions/old-content-has-scrollbars.html
new file mode 100644
index 0000000000..f87a4498c1
--- /dev/null
+++ b/testing/web-platform/tests/css/css-view-transitions/old-content-has-scrollbars.html
@@ -0,0 +1,60 @@
+<!DOCTYPE html>
+<meta name="timeout" content="long">
+<html class=reftest-wait>
+<title>Shared transitions: outgoing viewport has scrollbars</title>
+<link rel="help" href="https://github.com/WICG/view-transitions">
+<link rel="help" href="https://github.com/w3c/csswg-drafts/issues/7859">
+<link rel="author" href="mailto:bokan@chromium.org">
+<link rel="match" href="old-content-has-scrollbars-ref.html">
+<meta name=fuzzy content="old-content-has-scrollbars-ref.html:0-40;0-30000">
+<script src="/common/reftest-wait.js"></script>
+<style>
+ html, body {
+ width: 100%;
+ height: 100%;
+ background-color: lightpink;
+ }
+ body {
+ /* Margin to make sure background color is correctly drawn into the snapshot. */
+ margin: 50px;
+ }
+ div {
+ /* Draw a checkerboard pattern to make sure the snapshot is captured at the
+ * full size, rather than scaled. */
+ background-image:
+ linear-gradient(45deg, #000 25%, transparent 25%),
+ linear-gradient(45deg, transparent 75%, #000 75%),
+ linear-gradient(45deg, transparent 75%, #000 75%),
+ linear-gradient(45deg, #000 25%, lightgreen 25%);
+ background-size: 200px 200px;
+ background-position: 0 0, 0 0, -100px -100px, 100px 100px;
+ width: 200%;
+ height: 200%;
+ }
+
+ /* We're verifying what we capture, so just display the old contents for 5 minutes. */
+ html::view-transition-new(root) { animation: unset; opacity: 0; }
+ html::view-transition-old(root) {
+ animation-duration: 300s;
+ animation-timing-function: steps(1, end);
+ opacity: 1;
+ }
+</style>
+
+<div></div>
+<script>
+failIfNot(document.startViewTransition, "Missing document.startViewTransition");
+
+// Ensure a root snapshot captured on a page with scrollbars uses the full
+// viewport size (including scrollbars). Areas obscured by scrollbars should be
+// filled with background and content; the snapshot should not be scaled-to-fit.
+async function runTest() {
+ document.startViewTransition(() => {
+ document.querySelector('div').remove();
+ document.documentElement.style.overflow = "hidden";
+ requestAnimationFrame(() => requestAnimationFrame(takeScreenshot));
+ });
+}
+onload = () => requestAnimationFrame(() => requestAnimationFrame(runTest));
+</script>
+
diff --git a/testing/web-platform/tests/css/css-view-transitions/old-content-intrinsic-aspect-ratio.html b/testing/web-platform/tests/css/css-view-transitions/old-content-intrinsic-aspect-ratio.html
new file mode 100644
index 0000000000..8ba2a8f31f
--- /dev/null
+++ b/testing/web-platform/tests/css/css-view-transitions/old-content-intrinsic-aspect-ratio.html
@@ -0,0 +1,67 @@
+<!DOCTYPE html>
+<html class=reftest-wait>
+<title>Shared transitions: different width container should keep aspect ratio (by default)</title>
+<link rel="help" href="https://github.com/WICG/view-transitions">
+<link rel="author" href="mailto:vmpstr@chromium.org">
+<link rel="match" href="intrinsic-aspect-ratio-ref.html">
+<script src="/common/reftest-wait.js"></script>
+<style>
+.spacer {
+ height: 10px;
+}
+.box {
+ width: 100px;
+ height: 100px;
+ contain: paint;
+ background: blue;
+}
+#target1 {
+ view-transition-name: target1;
+}
+#target2 {
+ view-transition-name: target2;
+}
+#hidden {
+ view-transition-name: hidden;
+ width: 10px;
+ height: 10px;
+ visibility: hidden;
+ contain: paint;
+}
+
+/* We're verifying what we capture, so just display the new contents for 5 minutes. */
+html::view-transition-group(*) { animation-duration: 300s; }
+html::view-transition-new(*) { animation: unset; opacity: 0; }
+html::view-transition-old(*) { animation: unset; opacity: 1; }
+
+html::view-transition-group(target1) {
+ animation: unset;
+ width: 50px;
+ border: 2px solid black;
+}
+html::view-transition-group(target2) {
+ animation: unset;
+ width: 200px;
+ border: 2px solid black;
+}
+
+/* hide the root so we show transition background to ensure we're in a transition */
+html::view-transition-group(root) { animation: unset; opacity: 0; }
+html::view-transition { background: lightpink; }
+</style>
+
+<div id=target1 class=box></div>
+<div class=spacer></div>
+<div id=target2 class=box></div>
+<div id=hidden></div>
+<script>
+failIfNot(document.startViewTransition, "Missing document.startViewTransition");
+
+async function runTest() {
+ document.startViewTransition(() => {
+ requestAnimationFrame(() => requestAnimationFrame(takeScreenshot));
+ });
+}
+onload = () => requestAnimationFrame(() => requestAnimationFrame(runTest));
+</script>
+
diff --git a/testing/web-platform/tests/css/css-view-transitions/old-content-is-empty-div-ref.html b/testing/web-platform/tests/css/css-view-transitions/old-content-is-empty-div-ref.html
new file mode 100644
index 0000000000..b658d56535
--- /dev/null
+++ b/testing/web-platform/tests/css/css-view-transitions/old-content-is-empty-div-ref.html
@@ -0,0 +1,19 @@
+<!DOCTYPE html>
+<title>Shared transitions: old content captures an empty div (ref)</title>
+<link rel="help" href="https://github.com/WICG/view-transitions">
+<link rel="author" href="mailto:vmpstr@chromium.org">
+<style>
+div {
+ width: 100px;
+ height: 100px;
+ contain: paint;
+ position: absolute;
+ top: 50px;
+ left: 50px;
+ background: green;
+}
+body { background: lightpink; }
+</style>
+<div></div>
+
+
diff --git a/testing/web-platform/tests/css/css-view-transitions/old-content-is-empty-div.html b/testing/web-platform/tests/css/css-view-transitions/old-content-is-empty-div.html
new file mode 100644
index 0000000000..c6a6655a78
--- /dev/null
+++ b/testing/web-platform/tests/css/css-view-transitions/old-content-is-empty-div.html
@@ -0,0 +1,60 @@
+<!DOCTYPE html>
+<html class=reftest-wait>
+<title>Shared transitions: old content captures an empty div</title>
+<link rel="help" href="https://github.com/WICG/view-transitions">
+<link rel="author" href="mailto:vmpstr@chromium.org">
+<link rel="match" href="old-content-is-empty-div-ref.html">
+
+<script src="/common/reftest-wait.js"></script>
+<style>
+div {
+ contain: paint;
+ width: 100px;
+ height: 100px;
+ position: absolute;
+ top: 50px;
+}
+#empty {
+ left: 50px;
+}
+#target {
+ left: 200px;
+ background: green;
+}
+#hidden {
+ background: red;
+}
+
+html::view-transition-group(hidden) { animation-duration: 300s; }
+html::view-transition-image-pair(hidden) { animation: unset; opacity: 0; }
+
+/* The effect of the following should be position at the outgoing element
+ but contents of the new element.
+*/
+html::view-transition-group(shared) { animation-delay: 100s; }
+html::view-transition-new(shared) { animation: unset; opacity: 1; }
+html::view-transition-old(shared) { animation: unset; opacity: 1; }
+
+html::view-transition-group(root) { animation: unset; opacity: 0; }
+html::view-transition { background: lightpink; }
+
+</style>
+
+<div id=empty></div>
+<div id=target></div>
+<div id=hidden></div>
+
+<script>
+failIfNot(document.startViewTransition, "Missing document.startViewTransition");
+
+async function runTest() {
+ empty.style.viewTransitionName = "shared";
+ document.startViewTransition(() => {
+ empty.style.viewTransitionName = "";
+ target.style.viewTransitionName = "shared";
+
+ requestAnimationFrame(() => requestAnimationFrame(takeScreenshot))
+ });
+}
+onload = () => requestAnimationFrame(() => requestAnimationFrame(runTest));
+</script>
diff --git a/testing/web-platform/tests/css/css-view-transitions/old-content-object-fit-fill.html b/testing/web-platform/tests/css/css-view-transitions/old-content-object-fit-fill.html
new file mode 100644
index 0000000000..a3f146f9fe
--- /dev/null
+++ b/testing/web-platform/tests/css/css-view-transitions/old-content-object-fit-fill.html
@@ -0,0 +1,77 @@
+<!DOCTYPE html>
+<html class=reftest-wait>
+<title>Shared transitions: display content in a pseudo with object-fit: fill</title>
+<link rel="help" href="https://github.com/WICG/view-transitions">
+<link rel="author" href="mailto:vmpstr@chromium.org">
+<link rel="match" href="content-object-fit-fill-ref.html">
+<meta name="fuzzy" content="content-object-fit-fill-ref.html:0-60;0-20">
+<script src="/common/reftest-wait.js"></script>
+<style>
+#target {
+ width: 100px;
+ height: 100px;
+ contain: paint;
+ position: absolute;
+ top: 20px;
+ left: 20px;
+ view-transition-name: target;
+ background: lightblue;
+}
+#inner {
+ width: 10px;
+ height: 10px;
+ background: green;
+ top: 5px;
+ left: 10px;
+}
+#hidden {
+ background: pink;
+ width: 10px;
+ height: 10px;
+ view-transition-name: hidden;
+ contain: layout;
+}
+
+html::view-transition-group(target) {
+ animation: unset;
+ transform: unset;
+ position: absolute;
+ top: 10px;
+ left: 10px;
+ width: 50px;
+ height: 50px;
+}
+
+html::view-transition-new(target) {
+ animation: unset;
+ opacity: 0;
+}
+html::view-transition-old(target) {
+ animation: unset;
+ opacity: 1;
+ object-fit: fill;
+}
+
+html::view-transition-group(hidden) {
+ animation-duration: 500s;
+ visibility: hidden;
+}
+
+html::view-transition-group(root) { animation: unset; opacity: 0; }
+html::view-transition { background: lightpink; }
+</style>
+
+<div id=target><div id=inner></div></div>
+<div id=hidden></div>
+
+<script>
+failIfNot(document.startViewTransition, "Missing document.startViewTransition");
+
+async function runTest() {
+ document.startViewTransition(() => {
+ requestAnimationFrame(() => requestAnimationFrame(takeScreenshot));
+ });
+}
+onload = () => requestAnimationFrame(() => requestAnimationFrame(runTest));
+</script>
+
diff --git a/testing/web-platform/tests/css/css-view-transitions/old-content-object-fit-none.html b/testing/web-platform/tests/css/css-view-transitions/old-content-object-fit-none.html
new file mode 100644
index 0000000000..592b89949b
--- /dev/null
+++ b/testing/web-platform/tests/css/css-view-transitions/old-content-object-fit-none.html
@@ -0,0 +1,70 @@
+<!DOCTYPE html>
+<html class=reftest-wait>
+<title>Shared transitions: display content in a pseudo with object-fit: none</title>
+<link rel="help" href="https://github.com/WICG/view-transitions">
+<link rel="author" href="mailto:vmpstr@chromium.org">
+<link rel="match" href="content-object-fit-none-ref.html">
+<script src="/common/reftest-wait.js"></script>
+<style>
+#target {
+ width: 100px;
+ height: 100px;
+ contain: paint;
+ position: absolute;
+ top: 20px;
+ left: 20px;
+ view-transition-name: target;
+ background: lightblue;
+}
+#hidden {
+ background: pink;
+ width: 10px;
+ height: 10px;
+ view-transition-name: hidden;
+ contain: layout;
+}
+
+html::view-transition-group(target) {
+ animation: unset;
+ transform: unset;
+ position: absolute;
+ top: 10px;
+ left: 10px;
+ width: 50px;
+ height: 50px;
+}
+
+html::view-transition-new(target) {
+ animation: unset;
+ opacity: 0;
+}
+html::view-transition-old(target) {
+ animation: unset;
+ opacity: 1;
+ object-fit: none;
+ object-position: 0% 0%;
+}
+
+html::view-transition-group(hidden) {
+ animation-duration: 500s;
+ visibility: hidden;
+}
+
+html::view-transition-group(root) { animation: unset; opacity: 0; }
+html::view-transition { background: lightpink; }
+</style>
+
+<div id=target>This is text</div>
+<div id=hidden></div>
+
+<script>
+failIfNot(document.startViewTransition, "Missing document.startViewTransition");
+
+async function runTest() {
+ document.startViewTransition(() => {
+ requestAnimationFrame(() => requestAnimationFrame(takeScreenshot));
+ });
+}
+onload = () => requestAnimationFrame(() => requestAnimationFrame(runTest));
+</script>
+
diff --git a/testing/web-platform/tests/css/css-view-transitions/old-content-object-view-box-clip-path-ref.html b/testing/web-platform/tests/css/css-view-transitions/old-content-object-view-box-clip-path-ref.html
new file mode 100644
index 0000000000..208284cc71
--- /dev/null
+++ b/testing/web-platform/tests/css/css-view-transitions/old-content-object-view-box-clip-path-ref.html
@@ -0,0 +1,46 @@
+<!DOCTYPE html>
+<title>Shared transitions: object-view-box with larger overflow (ref)</title>
+<link rel="help" href="https://github.com/WICG/view-transitions">
+<link rel="author" href="mailto:vmpstr@chromium.org">
+<style>
+.target {
+ color: red;
+ width: 100px;
+ height: 100px;
+ contain: paint;
+ position: relative;
+ top: 50px;
+ left: 50px;
+}
+.child {
+ width: 123px;
+ height: 150px;
+ background: lightblue;
+ position: relative;
+ top: -10px;
+ left: -20px;
+}
+.grandchild {
+ width: 25px;
+ height: 25px;
+ position: relative;
+ top: 20px;
+ left: 40px;
+ background: green;
+}
+#one { clip-path: inset(10px 12px 20px 28px); }
+#two { clip-path: inset(10px -12px 20px -28px); }
+body { background: lightpink; }
+</style>
+
+<div id=one class=target>
+ <div class=child>
+ <div class=grandchild></div>
+ </div>
+</div>
+<div style="height: 20px;"></div>
+<div id=two class=target>
+ <div class=child>
+ <div class=grandchild></div>
+ </div>
+</div>
diff --git a/testing/web-platform/tests/css/css-view-transitions/old-content-object-view-box-clip-path-reference-ref.html b/testing/web-platform/tests/css/css-view-transitions/old-content-object-view-box-clip-path-reference-ref.html
new file mode 100644
index 0000000000..394a80f344
--- /dev/null
+++ b/testing/web-platform/tests/css/css-view-transitions/old-content-object-view-box-clip-path-reference-ref.html
@@ -0,0 +1,57 @@
+<!DOCTYPE html>
+<title>Shared transitions: object-view-box with larger overflow (ref)</title>
+<link rel="help" href="https://github.com/WICG/view-transitions">
+<link rel="author" href="mailto:vmpstr@chromium.org">
+<style>
+.target {
+ color: red;
+ width: 100px;
+ height: 100px;
+ contain: paint;
+ position: relative;
+ top: 50px;
+ left: 50px;
+}
+.child {
+ width: 123px;
+ height: 150px;
+ background: lightblue;
+ position: relative;
+ top: -10px;
+ left: -20px;
+}
+.grandchild {
+ width: 25px;
+ height: 25px;
+ position: relative;
+ top: 20px;
+ left: 40px;
+ background: green;
+}
+#one { clip-path: url(#clip1); }
+#two { clip-path: url(#clip2); }
+body { background: lightpink; }
+</style>
+
+<div id=one class=target>
+ <div class=child>
+ <div class=grandchild></div>
+ </div>
+</div>
+<div style="height: 20px;"></div>
+<div id=two class=target>
+ <div class=child>
+ <div class=grandchild></div>
+ </div>
+</div>
+
+<svg>
+ <defs>
+ <clipPath id="clip1">
+ <rect x="10" y="20" width="70" height="50" />
+ </clipPath>
+ <clipPath id="clip2">
+ <rect x="-10" y="20" width="130" height="50" />
+ </clipPath>
+ </defs>
+</svg>
diff --git a/testing/web-platform/tests/css/css-view-transitions/old-content-object-view-box-clip-path-reference.html b/testing/web-platform/tests/css/css-view-transitions/old-content-object-view-box-clip-path-reference.html
new file mode 100644
index 0000000000..a9bbf0ff24
--- /dev/null
+++ b/testing/web-platform/tests/css/css-view-transitions/old-content-object-view-box-clip-path-reference.html
@@ -0,0 +1,94 @@
+<!DOCTYPE html>
+<html class=reftest-wait>
+<title>Shared transitions: object-view-box with larger clip-path</title>
+<link rel="help" href="https://github.com/WICG/view-transitions">
+<link rel="author" href="mailto:vmpstr@chromium.org">
+<link rel="match" href="old-content-object-view-box-clip-path-reference-ref.html">
+<meta name="fuzzy" content="old-content-object-view-box-clip-path-reference-ref.html:0-1;0-100">
+<script src="/common/reftest-wait.js"></script>
+<style>
+.target {
+ color: red;
+ width: 100px;
+ height: 100px;
+ contain: paint;
+ overflow-clip-margin: 1000px;
+ position: relative;
+ top: 50px;
+ left: 50px;
+}
+.child {
+ width: 123px;
+ height: 150px;
+ background: lightblue;
+ position: relative;
+ top: -10px;
+ left: -20px;
+}
+.grandchild {
+ width: 25px;
+ height: 25px;
+ position: relative;
+ top: 20px;
+ left: 40px;
+ background: green;
+}
+#one {
+ view-transition-name: target-one;
+ clip-path: url(#clip1);
+}
+#two {
+ view-transition-name: target-two;
+ clip-path: url(#clip2)
+}
+
+html::view-transition-group(target-one),
+html::view-transition-group(target-two) { animation-duration: 300s; }
+html::view-transition-new(target-one),
+html::view-transition-new(target-two) { animation: unset; opacity: 0; height: 100%; }
+html::view-transition-old(target-one),
+html::view-transition-old(target-two) {
+ animation: unset;
+ opacity: 1;
+ /* clip overflow, and verify inner contents only */
+ overflow: hidden;
+ height: 100%;
+}
+
+html::view-transition-group(root) { animation: unset; opacity: 0; }
+html::view-transition { background: lightpink; }
+</style>
+
+<div id=one class=target>
+ <div class=child>
+ <div class=grandchild></div>
+ </div>
+</div>
+<div style="height: 20px;"></div>
+<div id=two class=target>
+ <div class=child>
+ <div class=grandchild></div>
+ </div>
+</div>
+
+<svg>
+ <defs>
+ <clipPath id="clip1">
+ <rect x="10" y="20" width="70" height="50" />
+ </clipPath>
+ <clipPath id="clip2">
+ <rect x="-10" y="20" width="130" height="50" />
+ </clipPath>
+ </defs>
+</svg>
+
+<script>
+failIfNot(document.startViewTransition, "Missing document.startViewTransition");
+
+async function runTest() {
+ document.startViewTransition(() =>
+ requestAnimationFrame(() => requestAnimationFrame(takeScreenshot)));
+}
+onload = () => requestAnimationFrame(() => requestAnimationFrame(runTest));
+</script>
+
diff --git a/testing/web-platform/tests/css/css-view-transitions/old-content-object-view-box-clip-path.html b/testing/web-platform/tests/css/css-view-transitions/old-content-object-view-box-clip-path.html
new file mode 100644
index 0000000000..04d4f31670
--- /dev/null
+++ b/testing/web-platform/tests/css/css-view-transitions/old-content-object-view-box-clip-path.html
@@ -0,0 +1,83 @@
+<!DOCTYPE html>
+<html class=reftest-wait>
+<title>Shared transitions: object-view-box with larger clip-path</title>
+<link rel="help" href="https://github.com/WICG/view-transitions">
+<link rel="author" href="mailto:vmpstr@chromium.org">
+<link rel="match" href="old-content-object-view-box-clip-path-ref.html">
+<meta name="fuzzy" content="old-content-object-view-box-clip-path-ref.html:0-1;0-30">
+<script src="/common/reftest-wait.js"></script>
+<style>
+.target {
+ color: red;
+ width: 100px;
+ height: 100px;
+ contain: paint;
+ overflow-clip-margin: 1000px;
+ position: relative;
+ top: 50px;
+ left: 50px;
+}
+.child {
+ width: 123px;
+ height: 150px;
+ background: lightblue;
+ position: relative;
+ top: -10px;
+ left: -20px;
+}
+.grandchild {
+ width: 25px;
+ height: 25px;
+ position: relative;
+ top: 20px;
+ left: 40px;
+ background: green;
+}
+#one {
+ view-transition-name: target-one;
+ clip-path: inset(10px 12px 20px 28px);
+}
+#two {
+ view-transition-name: target-two;
+ clip-path: inset(10px -12px 20px -28px);
+}
+
+html::view-transition-group(target-one),
+html::view-transition-group(target-two) { animation-duration: 300s; }
+html::view-transition-new(target-one),
+html::view-transition-new(target-two) { animation: unset; opacity: 0; height: 100%; }
+html::view-transition-old(target-one),
+html::view-transition-old(target-two) {
+ animation: unset;
+ opacity: 1;
+ /* clip overflow, and verify inner contents only */
+ overflow: hidden;
+ height: 100%;
+}
+
+html::view-transition-group(root) { animation: unset; opacity: 0; }
+html::view-transition { background: lightpink; }
+</style>
+
+<div id=one class=target>
+ <div class=child>
+ <div class=grandchild></div>
+ </div>
+</div>
+<div style="height: 20px;"></div>
+<div id=two class=target>
+ <div class=child>
+ <div class=grandchild></div>
+ </div>
+</div>
+
+<script>
+failIfNot(document.startViewTransition, "Missing document.startViewTransition");
+
+async function runTest() {
+ document.startViewTransition(() =>
+ requestAnimationFrame(() => requestAnimationFrame(takeScreenshot)));
+}
+onload = () => requestAnimationFrame(() => requestAnimationFrame(runTest));
+</script>
+
diff --git a/testing/web-platform/tests/css/css-view-transitions/old-content-object-view-box-overflow-ref.html b/testing/web-platform/tests/css/css-view-transitions/old-content-object-view-box-overflow-ref.html
new file mode 100644
index 0000000000..2b55f1537d
--- /dev/null
+++ b/testing/web-platform/tests/css/css-view-transitions/old-content-object-view-box-overflow-ref.html
@@ -0,0 +1,38 @@
+<!DOCTYPE html>
+<title>Shared transitions: object-view-box with larger overflow (ref)</title>
+<link rel="help" href="https://github.com/WICG/view-transitions">
+<link rel="author" href="mailto:vmpstr@chromium.org">
+<style>
+.target {
+ color: red;
+ width: 100px;
+ height: 100px;
+ contain: paint;
+ position: relative;
+ top: 50px;
+ left: 50px;
+}
+.child {
+ width: 123px;
+ height: 150px;
+ background: lightblue;
+ position: relative;
+ top: -10px;
+ left: -20px;
+}
+.grandchild {
+ width: 25px;
+ height: 25px;
+ position: relative;
+ top: 20px;
+ left: 40px;
+ background: green;
+}
+body { background: lightpink; }
+</style>
+
+<div class=target>
+ <div class=child>
+ <div class=grandchild></div>
+ </div>
+</div>
diff --git a/testing/web-platform/tests/css/css-view-transitions/old-content-object-view-box-overflow.html b/testing/web-platform/tests/css/css-view-transitions/old-content-object-view-box-overflow.html
new file mode 100644
index 0000000000..e5bfee912d
--- /dev/null
+++ b/testing/web-platform/tests/css/css-view-transitions/old-content-object-view-box-overflow.html
@@ -0,0 +1,66 @@
+<!DOCTYPE html>
+<html class=reftest-wait>
+<title>Shared transitions: object-view-box with larger overflow</title>
+<link rel="help" href="https://github.com/WICG/view-transitions">
+<link rel="author" href="mailto:vmpstr@chromium.org">
+<link rel="match" href="old-content-object-view-box-overflow-ref.html">
+<script src="/common/reftest-wait.js"></script>
+<style>
+.target {
+ color: red;
+ width: 100px;
+ height: 100px;
+ contain: paint;
+ overflow-clip-margin: 1000px;
+ position: relative;
+ top: 50px;
+ left: 50px;
+ view-transition-name: target;
+}
+.child {
+ width: 123px;
+ height: 150px;
+ background: lightblue;
+ position: relative;
+ top: -10px;
+ left: -20px;
+}
+.grandchild {
+ width: 25px;
+ height: 25px;
+ position: relative;
+ top: 20px;
+ left: 40px;
+ background: green;
+}
+
+html::view-transition-group(target) { animation-duration: 300s; }
+html::view-transition-new(target) { animation: unset; opacity: 0; }
+html::view-transition-old(target) {
+ animation: unset;
+ opacity: 1;
+ /* clip overflow, and verify inner contents only */
+ overflow: hidden;
+ height: 100%;
+}
+
+html::view-transition-group(root) { animation: unset; opacity: 0; }
+html::view-transition { background: lightpink; }
+</style>
+
+<div class=target>
+ <div class=child>
+ <div class=grandchild></div>
+ </div>
+</div>
+
+<script>
+failIfNot(document.startViewTransition, "Missing document.startViewTransition");
+
+async function runTest() {
+ document.startViewTransition(() =>
+ requestAnimationFrame(() => requestAnimationFrame(takeScreenshot)));
+}
+onload = () => requestAnimationFrame(() => requestAnimationFrame(runTest));
+</script>
+
diff --git a/testing/web-platform/tests/css/css-view-transitions/old-content-with-overflow-zoomed.html b/testing/web-platform/tests/css/css-view-transitions/old-content-with-overflow-zoomed.html
new file mode 100644
index 0000000000..d78c424662
--- /dev/null
+++ b/testing/web-platform/tests/css/css-view-transitions/old-content-with-overflow-zoomed.html
@@ -0,0 +1,56 @@
+<!DOCTYPE html>
+<html class=reftest-wait>
+<title>Shared transitions: shared element with overflow</title>
+<link rel="help" href="https://github.com/WICG/view-transitions">
+<link rel="author" href="mailto:khushalsagar@chromium.org">
+<link rel="match" href="content-with-overflow-zoomed-ref.html">
+<script src="/common/reftest-wait.js"></script>
+<style>
+.target {
+ width: 80px;
+ height: 80px;
+ contain: paint;
+ background: blue;
+ overflow-clip-margin: 50px;
+ view-transition-name: target;
+ zoom: 1.5;
+}
+.child {
+ width: 200px;
+ height: 200px;
+ position: relative;
+ top: 50px;
+ left: 50px;
+ background: green;
+ zoom: 1.2;
+}
+
+html::view-transition-group(target) { animation-duration: 300s; }
+html::view-transition-new(target) { animation: unset; opacity: 0; }
+html::view-transition-old(target) {
+ animation: unset;
+ opacity: 1;
+ border: 3px solid black;
+}
+
+html::view-transition-group(root) { animation: unset; opacity: 0; }
+html::view-transition { background: lightpink; }
+</style>
+
+<div class=ancestor>
+ <div class=target>
+ <div class=child>
+ </div>
+ </div>
+</div>
+
+<script>
+failIfNot(document.startViewTransition, "Missing document.startViewTransition");
+
+async function runTest() {
+ document.startViewTransition(() =>
+ requestAnimationFrame(() => requestAnimationFrame(takeScreenshot)));
+}
+onload = () => requestAnimationFrame(() => requestAnimationFrame(runTest));
+</script>
+
diff --git a/testing/web-platform/tests/css/css-view-transitions/old-content-with-overflow.html b/testing/web-platform/tests/css/css-view-transitions/old-content-with-overflow.html
new file mode 100644
index 0000000000..3ddf818c78
--- /dev/null
+++ b/testing/web-platform/tests/css/css-view-transitions/old-content-with-overflow.html
@@ -0,0 +1,51 @@
+<!DOCTYPE html>
+<html class=reftest-wait>
+<title>Shared transitions: shared element with overflow</title>
+<link rel="help" href="https://github.com/WICG/view-transitions">
+<link rel="author" href="mailto:khushalsagar@chromium.org">
+<link rel="match" href="content-with-overflow-ref.html">
+<script src="/common/reftest-wait.js"></script>
+<style>
+.target {
+ width: 100px;
+ height: 100px;
+ contain: paint;
+ background: blue;
+ overflow-clip-margin: 50px;
+ view-transition-name: target;
+}
+.child {
+ width: 200px;
+ height: 200px;
+ position: relative;
+ top: 50px;
+ left: 50px;
+ background: green;
+}
+
+html::view-transition-group(target) { animation-duration: 300s; }
+html::view-transition-new(target) { animation: unset; opacity: 0; }
+html::view-transition-old(target) {
+ animation: unset;
+ opacity: 1;
+}
+
+html::view-transition-group(root) { animation: unset; opacity: 0; }
+html::view-transition { background: lightpink; }
+</style>
+
+<div class=target>
+ <div class=child>
+ </div>
+</div>
+
+<script>
+failIfNot(document.startViewTransition, "Missing document.startViewTransition");
+
+async function runTest() {
+ document.startViewTransition(() =>
+ requestAnimationFrame(() => requestAnimationFrame(takeScreenshot)));
+}
+onload = () => requestAnimationFrame(() => requestAnimationFrame(runTest));
+</script>
+
diff --git a/testing/web-platform/tests/css/css-view-transitions/old-root-vertical-writing-mode-ref.html b/testing/web-platform/tests/css/css-view-transitions/old-root-vertical-writing-mode-ref.html
new file mode 100644
index 0000000000..227db8a132
--- /dev/null
+++ b/testing/web-platform/tests/css/css-view-transitions/old-root-vertical-writing-mode-ref.html
@@ -0,0 +1,24 @@
+<!DOCTYPE html>
+<title>Shared transitions: container of shared element writing-modes (ref)</title>
+<link rel="help" href="https://github.com/WICG/view-transitions">
+<link rel="author" href="mailto:vmpstr@chromium.org">
+
+<style>
+html { writing-mode: vertical-lr; }
+.shared {
+ margin: 2px;
+ width: 90px;
+ height: 50px;
+ background: green;
+ contain: paint;
+}
+#two {
+ background: lightblue;
+ will-change: transform;
+}
+</style>
+
+<div id=one class=shared>T</div>
+<div id=two class=shared></div>
+
+
diff --git a/testing/web-platform/tests/css/css-view-transitions/old-root-vertical-writing-mode.html b/testing/web-platform/tests/css/css-view-transitions/old-root-vertical-writing-mode.html
new file mode 100644
index 0000000000..af4fcf5bb2
--- /dev/null
+++ b/testing/web-platform/tests/css/css-view-transitions/old-root-vertical-writing-mode.html
@@ -0,0 +1,76 @@
+<!DOCTYPE html>
+<html class=reftest-wait>
+<title>Shared transitions: container of shared element writing-modes</title>
+<link rel="help" href="https://github.com/WICG/view-transitions">
+<link rel="author" href="mailto:vmpstr@chromium.org">
+<link rel="match" href="new-root-vertical-writing-mode-ref.html">
+<script src="/common/reftest-wait.js"></script>
+<style>
+html { writing-mode: vertical-lr; }
+#hidden {
+ width: 100px;
+ height: 100px;
+ background: red;
+ position: absolute;
+ top: 0;
+ left: 0;
+ contain: paint;
+ view-transition-name: hidden;
+}
+.shared {
+ margin: 2px;
+ width: 90px;
+ height: 50px;
+ background: green;
+ contain: paint;
+}
+#target {
+ background: red;
+ position: absolute;
+ top: 50px;
+ left: 50px;
+ width: 100px;
+ height: 500px;
+ contain: paint;
+}
+#one { view-transition-name: s1; }
+#two {
+ background: lightblue;
+ will-change: transform;
+}
+
+html::view-transition-group(hidden) { animation-duration: 300s; }
+html::view-transition-image-pair(hidden) { animation: unset; opacity: 0; }
+
+html::view-transition-group(s1) { animation-delay: 100s; animation-fill-mode: both; }
+html::view-transition-new(s1) { animation: unset; opacity: 0; }
+html::view-transition-old(s1) { animation: unset; opacity: 1; }
+
+html::view-transition-new(root) { animation: unset; opacity: 0; }
+html::view-transition-old(root) { animation: unset; opacity: 1; }
+
+</style>
+
+<div id=hidden>Should not be visible</div>
+<div id=target style="display: none">Should not be visible</div>
+<div id=one class=shared>T</div>
+<div id=two class=shared></div>
+
+<script>
+failIfNot(document.startViewTransition, "Missing document.startViewTransition");
+
+async function runTest() {
+ document.startViewTransition(() => {
+ one.remove();
+ target.style = "";
+ target.style.viewTransitionName = "s1";
+ hidden.style.left = "200px";
+ requestAnimationFrame(() => requestAnimationFrame(takeScreenshot));
+ });
+}
+onload = () => requestAnimationFrame(() => requestAnimationFrame(runTest));
+</script>
+
+
+
+
diff --git a/testing/web-platform/tests/css/css-view-transitions/only-child-group.html b/testing/web-platform/tests/css/css-view-transitions/only-child-group.html
new file mode 100644
index 0000000000..034df41dde
--- /dev/null
+++ b/testing/web-platform/tests/css/css-view-transitions/only-child-group.html
@@ -0,0 +1,100 @@
+<!DOCTYPE html>
+<html class=reftest-wait>
+<title>View transitions: ensure :only-child is supported on view-transition-group</title>
+<link rel="help" href="https://github.com/WICG/view-transitions">
+<link rel="author" href="mailto:khushalsagar@chromium.org">
+
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+
+<style>
+::view-transition-group(root) {
+ background-color: blue;
+}
+::view-transition-group(target) {
+ background-color: blue;
+}
+::view-transition-group(*) {
+ color: blue;
+}
+
+::view-transition-group(root):only-child {
+ background-color: red;
+}
+::view-transition-group(target):only-child {
+ background-color: red;
+}
+::view-transition-group(*):only-child {
+ color: red;
+}
+
+div {
+ contain: layout;
+}
+</style>
+<div id="target"></div>
+<div id="target2"></div>
+
+<script>
+promise_test(() => {
+ return new Promise(async (resolve, reject) => {
+ let transition = document.startViewTransition();
+ transition.ready.then(() => {
+ let style = getComputedStyle(
+ document.documentElement, ":view-transition-group(root)");
+ if (style.backgroundColor == "rgb(255, 0, 0)" && style.color == "rgb(255, 0, 0)")
+ resolve();
+ else
+ reject(style.backgroundColor + " and " + style.color);
+ });
+ });
+}, ":only-child should match because ::view-transition-group is generated for root element only");
+
+promise_test(() => {
+ return new Promise(async (resolve, reject) => {
+ target.style.viewTransitionName = "target";
+ let transition = document.startViewTransition();
+ transition.ready.then(() => {
+ let style = getComputedStyle(
+ document.documentElement, ":view-transition-group(root)");
+ if (style.backgroundColor == "rgb(0, 0, 255)" && style.color == "rgb(0, 0, 255)")
+ resolve();
+ else
+ reject(style.backgroundColor + " and " + style.color);
+ });
+ });
+}, ":only-child should not match because ::view-transition-group is generated for multiple elements");
+
+promise_test(() => {
+ return new Promise(async (resolve, reject) => {
+ document.documentElement.style.viewTransitionName = "none";
+ target.style.viewTransitionName = "target";
+ let transition = document.startViewTransition();
+ transition.ready.then(() => {
+ let style = getComputedStyle(
+ document.documentElement, ":view-transition-group(target)");
+ if (style.backgroundColor == "rgb(255, 0, 0)" && style.color == "rgb(255, 0, 0)")
+ resolve();
+ else
+ reject(style.backgroundColor + " and " + style.color);
+ });
+ });
+}, ":only-child should match because ::view-transition-group is generated for sub element only");
+
+promise_test(() => {
+ return new Promise(async (resolve, reject) => {
+ document.documentElement.style.viewTransitionName = "none";
+ target.style.viewTransitionName = "target";
+ target2.style.viewTransitionName = "target2";
+ let transition = document.startViewTransition();
+ transition.ready.then(() => {
+ let style = getComputedStyle(
+ document.documentElement, ":view-transition-group(target)");
+ if (style.backgroundColor == "rgb(0, 0, 255)" && style.color == "rgb(0, 0, 255)")
+ resolve();
+ else
+ reject(style.backgroundColor + " and " + style.color);
+ });
+ });
+}, ":only-child should not match because ::view-transition-group is generated for multiple sub elements");
+</script>
diff --git a/testing/web-platform/tests/css/css-view-transitions/only-child-image-pair.html b/testing/web-platform/tests/css/css-view-transitions/only-child-image-pair.html
new file mode 100644
index 0000000000..830b37313e
--- /dev/null
+++ b/testing/web-platform/tests/css/css-view-transitions/only-child-image-pair.html
@@ -0,0 +1,33 @@
+<!DOCTYPE html>
+<html class=reftest-wait>
+<title>View transitions: ensure :only-child is supported on view-transition-image-pair</title>
+<link rel="help" href="https://github.com/WICG/view-transitions">
+<link rel="author" href="mailto:khushalsagar@chromium.org">
+
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+
+<style>
+::view-transition-image-pair(root):only-child {
+ background-color: red;
+}
+::view-transition-image-pair(*):only-child {
+ color: red;
+}
+</style>
+
+<script>
+promise_test(() => {
+ return new Promise(async (resolve, reject) => {
+ let transition = document.startViewTransition();
+ transition.ready.then(() => {
+ let style = getComputedStyle(
+ document.documentElement, ":view-transition-image-pair(root)");
+ if (style.backgroundColor == "rgb(255, 0, 0)" && style.color == "rgb(255, 0, 0)")
+ resolve();
+ else
+ reject(style.backgroundColor + " and " + style.color);
+ });
+ });
+}, ":only-child should always match for ::view-transition-image-pair");
+</script>
diff --git a/testing/web-platform/tests/css/css-view-transitions/only-child-new.html b/testing/web-platform/tests/css/css-view-transitions/only-child-new.html
new file mode 100644
index 0000000000..2f8a7a4023
--- /dev/null
+++ b/testing/web-platform/tests/css/css-view-transitions/only-child-new.html
@@ -0,0 +1,153 @@
+<!DOCTYPE html>
+<html class=reftest-wait>
+<title>View transitions: ensure :only-child is supported on view-transition-new</title>
+<link rel="help" href="https://github.com/WICG/view-transitions">
+<link rel="author" href="mailto:khushalsagar@chromium.org">
+
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+
+<style>
+::view-transition-new(root) {
+ background-color: blue;
+}
+::view-transition-new(target) {
+ background-color: blue;
+}
+::view-transition-new(*) {
+ color: blue;
+}
+
+::view-transition-new(root):only-child {
+ background-color: red;
+}
+::view-transition-new(target):only-child {
+ background-color: red;
+}
+::view-transition-new(*):only-child {
+ color: red;
+}
+
+#target {
+ contain: layout;
+}
+
+</style>
+<div id="target"></div>
+
+<script>
+let matchedColor = "rgb(255, 0, 0)";
+let notMatchedColor = "rgb(0, 0, 255)";
+
+promise_test(() => {
+ return new Promise(async (resolve, reject) => {
+ document.documentElement.style.viewTransitionName = "none";
+ target.style.viewTransitionName = "none";
+ let transition = document.startViewTransition(() => {
+ document.documentElement.style.viewTransitionName = "root";
+ });
+
+ transition.ready.then(() => {
+ let style = getComputedStyle(
+ document.documentElement, ":view-transition-new(root)");
+ if (style.backgroundColor == matchedColor && style.color == matchedColor)
+ resolve();
+ else
+ reject(style.backgroundColor + " and " + style.color);
+ });
+ });
+}, ":only-child should match because ::view-transition-old is not generated (none to root)");
+
+promise_test(() => {
+ return new Promise(async (resolve, reject) => {
+ document.documentElement.style.viewTransitionName = "root";
+ target.style.viewTransitionName = "none";
+ let transition = document.startViewTransition();
+
+ transition.ready.then(() => {
+ let style = getComputedStyle(
+ document.documentElement, ":view-transition-new(root)");
+ if (style.backgroundColor == notMatchedColor && style.color == notMatchedColor)
+ resolve();
+ else
+ reject(style.backgroundColor + " and " + style.color);
+ });
+ });
+}, ":only-child should not match because ::view-transition-old is generated (root to root)");
+
+promise_test(() => {
+ return new Promise(async (resolve, reject) => {
+ document.documentElement.style.viewTransitionName = "none";
+ target.style.viewTransitionName = "root";
+ let transition = document.startViewTransition(() => {
+ document.documentElement.style.viewTransitionName = "root";
+ target.style.viewTransitionName = "none";
+ });
+
+ transition.ready.then(() => {
+ let style = getComputedStyle(
+ document.documentElement, ":view-transition-new(root)");
+ if (style.backgroundColor == notMatchedColor && style.color == notMatchedColor)
+ resolve();
+ else
+ reject(style.backgroundColor + " and " + style.color);
+ });
+ });
+}, ":only-child should not match because ::view-transition-old is generated (element to root)");
+
+promise_test(() => {
+ return new Promise(async (resolve, reject) => {
+ target.style.viewTransitionName = "none";
+ document.documentElement.style.viewTransitionName = "none";
+ let transition = document.startViewTransition(() => {
+ target.style.viewTransitionName = "target";
+ });
+
+ transition.ready.then(() => {
+ let style = getComputedStyle(
+ document.documentElement, ":view-transition-new(target)");
+ if (style.backgroundColor == matchedColor && style.color == matchedColor)
+ resolve();
+ else
+ reject(style.backgroundColor + " and " + style.color);
+ });
+ });
+}, ":only-child should match because ::view-transition-old is not generated (none to element)");
+
+promise_test(() => {
+ return new Promise(async (resolve, reject) => {
+ target.style.viewTransitionName = "none";
+ document.documentElement.style.viewTransitionName = "root";
+ let transition = document.startViewTransition(() => {
+ document.documentElement.style.viewTransitionName = "none";
+ target.style.viewTransitionName = "element";
+ });
+
+ transition.ready.then(() => {
+ let style = getComputedStyle(
+ document.documentElement, ":view-transition-new(root)");
+ if (style.backgroundColor == notMatchedColor && style.color == notMatchedColor)
+ resolve();
+ else
+ reject(style.backgroundColor + " and " + style.color);
+ });
+ });
+}, ":only-child should not match because ::view-transition-old is generated (root to element)");
+
+promise_test(() => {
+ return new Promise(async (resolve, reject) => {
+ target.style.viewTransitionName = "target";
+ document.documentElement.style.viewTransitionName = "none";
+ let transition = document.startViewTransition();
+
+ transition.ready.then(() => {
+ let style = getComputedStyle(
+ document.documentElement, ":view-transition-new(target)");
+ if (style.backgroundColor == notMatchedColor && style.color == notMatchedColor)
+ resolve();
+ else
+ reject(style.backgroundColor + " and " + style.color);
+ });
+ });
+}, ":only-child should not match because ::view-transition-old is generated (element to element)");
+</script>
diff --git a/testing/web-platform/tests/css/css-view-transitions/only-child-no-transition.html b/testing/web-platform/tests/css/css-view-transitions/only-child-no-transition.html
new file mode 100644
index 0000000000..7dc2bf1217
--- /dev/null
+++ b/testing/web-platform/tests/css/css-view-transitions/only-child-no-transition.html
@@ -0,0 +1,39 @@
+<!DOCTYPE html>
+<html class=reftest-wait>
+<title>View transitions: :only-child style queries without transition shouldn't crash</title>
+<link rel="help" href="https://github.com/WICG/view-transitions">
+<link rel="author" href="mailto:khushalsagar@chromium.org">
+
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+
+<style>
+::view-transition:only-child,
+::view-transition-group(*):only-child,
+::view-transition-image-pair(*):only-child,
+::view-transition-old(*):only-child,
+::view-transition-new(*):only-child {
+ background-color: blue;
+}
+</style>
+
+<script>
+promise_test(() => {
+ return new Promise(async (resolve, reject) => {
+ let elements = [
+ "view-transition",
+ "view-transition-group(foo)",
+ "view-transition-image-pair(foo)",
+ "view-transition-old(foo)",
+ "view-transition-old(foo)"
+ ];
+
+ for (let i = 0; i < elements.length; i++) {
+ let style = window.getComputedStyle(document.documentElement, elements[i]);
+ if (style.backgroundColor == "rgb(0, 0, 255")
+ reject();
+ }
+ resolve();
+ });
+}, ":only-child style queries without transition shouldn't crash");
+</script>
diff --git a/testing/web-platform/tests/css/css-view-transitions/only-child-old.html b/testing/web-platform/tests/css/css-view-transitions/only-child-old.html
new file mode 100644
index 0000000000..4ca6fed20c
--- /dev/null
+++ b/testing/web-platform/tests/css/css-view-transitions/only-child-old.html
@@ -0,0 +1,153 @@
+<!DOCTYPE html>
+<html class=reftest-wait>
+<title>View transitions: ensure :only-child is supported on view-transition-old</title>
+<link rel="help" href="https://github.com/WICG/view-transitions">
+<link rel="author" href="mailto:khushalsagar@chromium.org">
+
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+
+<style>
+::view-transition-old(root) {
+ background-color: blue;
+}
+::view-transition-old(target) {
+ background-color: blue;
+}
+::view-transition-old(*) {
+ color: blue;
+}
+
+::view-transition-old(root):only-child {
+ background-color: red;
+}
+::view-transition-old(target):only-child {
+ background-color: red;
+}
+::view-transition-old(*):only-child {
+ color: red;
+}
+
+#target {
+ contain: layout;
+}
+
+</style>
+<div id="target"></div>
+
+<script>
+let matchedColor = "rgb(255, 0, 0)";
+let notMatchedColor = "rgb(0, 0, 255)";
+
+promise_test(() => {
+ return new Promise(async (resolve, reject) => {
+ document.documentElement.style.viewTransitionName = "root";
+ target.style.viewTransitionName = "none";
+ let transition = document.startViewTransition(() => {
+ document.documentElement.style.viewTransitionName = "none";
+ });
+
+ transition.ready.then(() => {
+ let style = getComputedStyle(
+ document.documentElement, ":view-transition-old(root)");
+ if (style.backgroundColor == matchedColor && style.color == matchedColor)
+ resolve();
+ else
+ reject(style.backgroundColor + " and " + style.color);
+ });
+ });
+}, ":only-child should match because ::view-transition-new is not generated (root to none)");
+
+promise_test(() => {
+ return new Promise(async (resolve, reject) => {
+ document.documentElement.style.viewTransitionName = "root";
+ target.style.viewTransitionName = "none";
+ let transition = document.startViewTransition();
+
+ transition.ready.then(() => {
+ let style = getComputedStyle(
+ document.documentElement, ":view-transition-old(root)");
+ if (style.backgroundColor == notMatchedColor && style.color == notMatchedColor)
+ resolve();
+ else
+ reject(style.backgroundColor + " and " + style.color);
+ });
+ });
+}, ":only-child should not match because ::view-transition-new is generated (root to root)");
+
+promise_test(() => {
+ return new Promise(async (resolve, reject) => {
+ document.documentElement.style.viewTransitionName = "root";
+ target.style.viewTransitionName = "none";
+ let transition = document.startViewTransition(() => {
+ document.documentElement.style.viewTransitionName = "none";
+ target.style.viewTransitionName = "root";
+ });
+
+ transition.ready.then(() => {
+ let style = getComputedStyle(
+ document.documentElement, ":view-transition-old(root)");
+ if (style.backgroundColor == notMatchedColor && style.color == notMatchedColor)
+ resolve();
+ else
+ reject(style.backgroundColor + " and " + style.color);
+ });
+ });
+}, ":only-child should not match because ::view-transition-new is generated (root to element)");
+
+promise_test(() => {
+ return new Promise(async (resolve, reject) => {
+ target.style.viewTransitionName = "target";
+ document.documentElement.style.viewTransitionName = "none";
+ let transition = document.startViewTransition(() => {
+ target.style.viewTransitionName = "none";
+ });
+
+ transition.ready.then(() => {
+ let style = getComputedStyle(
+ document.documentElement, ":view-transition-old(target)");
+ if (style.backgroundColor == matchedColor && style.color == matchedColor)
+ resolve();
+ else
+ reject(style.backgroundColor + " and " + style.color);
+ });
+ });
+}, ":only-child should match because ::view-transition-new is not generated (element to none)");
+
+promise_test(() => {
+ return new Promise(async (resolve, reject) => {
+ target.style.viewTransitionName = "root";
+ document.documentElement.style.viewTransitionName = "none";
+ let transition = document.startViewTransition(() => {
+ document.documentElement.style.viewTransitionName = "root";
+ target.style.viewTransitionName = "none";
+ });
+
+ transition.ready.then(() => {
+ let style = getComputedStyle(
+ document.documentElement, ":view-transition-old(root)");
+ if (style.backgroundColor == notMatchedColor && style.color == notMatchedColor)
+ resolve();
+ else
+ reject(style.backgroundColor + " and " + style.color);
+ });
+ });
+}, ":only-child should not match because ::view-transition-new is generated (element to root)");
+
+promise_test(() => {
+ return new Promise(async (resolve, reject) => {
+ target.style.viewTransitionName = "target";
+ document.documentElement.style.viewTransitionName = "none";
+ let transition = document.startViewTransition();
+
+ transition.ready.then(() => {
+ let style = getComputedStyle(
+ document.documentElement, ":view-transition-old(target)");
+ if (style.backgroundColor == notMatchedColor && style.color == notMatchedColor)
+ resolve();
+ else
+ reject(style.backgroundColor + " and " + style.color);
+ });
+ });
+}, ":only-child should not match because ::view-transition-new is generated (element to element)");
+</script>
diff --git a/testing/web-platform/tests/css/css-view-transitions/only-child-view-transition.html b/testing/web-platform/tests/css/css-view-transitions/only-child-view-transition.html
new file mode 100644
index 0000000000..d338a042ca
--- /dev/null
+++ b/testing/web-platform/tests/css/css-view-transitions/only-child-view-transition.html
@@ -0,0 +1,33 @@
+<!DOCTYPE html>
+<html class=reftest-wait>
+<title>View transitions: ensure :only-child is supported on view-transition</title>
+<link rel="help" href="https://github.com/WICG/view-transitions">
+<link rel="author" href="mailto:khushalsagar@chromium.org">
+
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+
+<style>
+::view-transition {
+ background-color: red;
+}
+::view-transition:only-child {
+ background-color: blue;
+}
+</style>
+
+<script>
+promise_test(() => {
+ return new Promise(async (resolve, reject) => {
+ let transition = document.startViewTransition();
+ transition.ready.then(() => {
+ let style = getComputedStyle(
+ document.documentElement, ":view-transition");
+ if (style.backgroundColor == "rgb(255, 0, 0)")
+ resolve();
+ else
+ reject(style.backgroundColor);
+ });
+ });
+}, ":only-child is not supported on view-transition");
+</script>
diff --git a/testing/web-platform/tests/css/css-view-transitions/parsing/view-transition-name-computed.html b/testing/web-platform/tests/css/css-view-transitions/parsing/view-transition-name-computed.html
new file mode 100644
index 0000000000..4a13ed5d2e
--- /dev/null
+++ b/testing/web-platform/tests/css/css-view-transitions/parsing/view-transition-name-computed.html
@@ -0,0 +1,24 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>CSS View Transitions: view-transition-name with computed values</title>
+<link rel="author" title="Vladimir Levin" href="mailto:vmpstr@chromium.org">
+<link rel="help" href="https://drafts.csswg.org/css-view-transitions-1/">
+<meta name="assert" content="view-transition-name supports custom keywords.">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/css/support/computed-testcommon.js"></script>
+</head>
+<body>
+<div id=target></div>
+<div id=scratch></div>
+<script>
+
+test_computed_value("view-transition-name", "none");
+test_computed_value("view-transition-name", "foo");
+test_computed_value("view-transition-name", "bar");
+test_computed_value("view-transition-name", "baz");
+</script>
+</body>
+</html>
diff --git a/testing/web-platform/tests/css/css-view-transitions/parsing/view-transition-name-valid.html b/testing/web-platform/tests/css/css-view-transitions/parsing/view-transition-name-valid.html
new file mode 100644
index 0000000000..2fd384449f
--- /dev/null
+++ b/testing/web-platform/tests/css/css-view-transitions/parsing/view-transition-name-valid.html
@@ -0,0 +1,21 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>CSS View Transitions Test: view-transition-name with valid values</title>
+<link rel="author" title="Vladimir Levin" href="mailto:vmpstr@chromium.org">
+<link rel="help" href="https://drafts.csswg.org/css-view-transitions-1/">
+<meta name="assert" content="view-transition-name supports custom tags">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/css/support/parsing-testcommon.js"></script>
+</head>
+<body>
+<script>
+test_valid_value("view-transition-name", "none");
+test_valid_value("view-transition-name", "foo");
+test_valid_value("view-transition-name", "bar");
+test_valid_value("view-transition-name", "baz");
+</script>
+</body>
+</html>
diff --git a/testing/web-platform/tests/css/css-view-transitions/pseudo-computed-style-stays-in-sync-with-new-element.html b/testing/web-platform/tests/css/css-view-transitions/pseudo-computed-style-stays-in-sync-with-new-element.html
new file mode 100644
index 0000000000..103dc31930
--- /dev/null
+++ b/testing/web-platform/tests/css/css-view-transitions/pseudo-computed-style-stays-in-sync-with-new-element.html
@@ -0,0 +1,42 @@
+<!DOCTYPE html>
+<html>
+<title>View transitions: computed style on pseudo-element stays in sync with the DOM element</title>
+<link rel="help" href="https://www.w3.org/TR/css-view-transitions-1/">
+<link rel="author" href="mailto:khushalsagar@chromium.org">
+
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+
+<style>
+div {
+ width: 100px;
+ height: 100px;
+ background: blue;
+ view-transition-name: target;
+ contain: paint;
+}
+</style>
+
+<div id=first></div>
+
+<script>
+promise_test(async t => {
+ assert_implements(document.startViewTransition, "Missing document.startViewTransition");
+ return new Promise(async (resolve, reject) => {
+ let transition = document.startViewTransition();
+ await transition.domUpdated;
+ await transition.ready;
+
+ let viewbox = window.getComputedStyle(
+ document.documentElement, "::view-transition-new(target)").objectViewBox;
+ assert_equals(viewbox, "none", "incorrect viewbox " + viewbox);
+
+ first.style.filter = "blur(5px)";
+ viewbox = window.getComputedStyle(
+ document.documentElement, "::view-transition-new(target)").objectViewBox;
+ assert_not_equals(viewbox, "none", "incorrect viewbox " + viewbox);
+
+ transition.finished.then(resolve, reject);
+ });
+}, "computed style on pseudo-element stays in sync with the DOM element");
+</script>
diff --git a/testing/web-platform/tests/css/css-view-transitions/pseudo-get-computed-style.html b/testing/web-platform/tests/css/css-view-transitions/pseudo-get-computed-style.html
new file mode 100644
index 0000000000..45d2559b3e
--- /dev/null
+++ b/testing/web-platform/tests/css/css-view-transitions/pseudo-get-computed-style.html
@@ -0,0 +1,94 @@
+<!DOCTYPE html>
+<html>
+<title>Shared transitions: check pseudo element's display property</title>
+<link rel="help" href="https://github.com/WICG/view-transitions">
+<link rel="author" href="mailto:vmpstr@chromium.org">
+
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+
+<style>
+div {
+ width: 100px;
+ height: 100px;
+ background: blue;
+ contain: paint;
+ view-transition-name: target;
+}
+::view-transition-image-pair(target) {
+ position: fixed;
+}
+</style>
+
+<div id=target></div>
+
+<script>
+promise_test(() => {
+ assert_implements(document.startViewTransition, "Missing document.startViewTransition");
+ return new Promise(async (resolve, reject) => {
+ let transition = document.startViewTransition(() => {
+ assert_equals(getComputedStyle(document.documentElement, ":view-transition").position, "fixed", ":view-transition");
+ assert_equals(getComputedStyle(document.documentElement, ":view-transition-group(target)").position, "absolute", "container(target)");
+ assert_equals(getComputedStyle(document.documentElement, ":view-transition-image-pair(target)").position, "absolute", "wrapper(target)");
+
+ assert_equals(getComputedStyle(document.documentElement, ":view-transition-old(target)").position, "absolute", "outgoing(target)");
+
+ assert_equals(getComputedStyle(document.documentElement, ":view-transition-group(root)").position, "absolute", "container(root)");
+ assert_equals(getComputedStyle(document.documentElement, ":view-transition-image-pair(root)").position, "absolute", "wrapper(root)");
+ assert_equals(getComputedStyle(document.documentElement, ":view-transition-old(root)").position, "absolute", "outgoing(root)");
+
+ requestAnimationFrame(() => {
+ assert_equals(getComputedStyle(document.documentElement, ":view-transition").position, "fixed", "raf :view-transition");
+ assert_equals(getComputedStyle(document.documentElement, ":view-transition-group(target)").position, "absolute", "raf container(target)");
+ assert_equals(getComputedStyle(document.documentElement, ":view-transition-image-pair(target)").position, "fixed", "raf wrapper(target)");
+
+ assert_equals(getComputedStyle(document.documentElement, ":view-transition-old(target)").position, "absolute", "raf outgoing(target)");
+
+ assert_equals(getComputedStyle(document.documentElement, ":view-transition-group(root)").position, "absolute", "raf container(root)");
+ assert_equals(getComputedStyle(document.documentElement, ":view-transition-image-pair(root)").position, "absolute", "raf wrapper(root)");
+ assert_equals(getComputedStyle(document.documentElement, ":view-transition-old(root)").position, "absolute", "raf outgoing(root)");
+ });
+ });
+ await transition.finished;
+ resolve();
+ });
+}, "position property of pseudo elements");
+
+promise_test(() => {
+ assert_implements(document.startViewTransition, "Missing document.startViewTransition");
+ return new Promise(async (resolve, reject) => {
+ let transition = document.startViewTransition(() => {
+ assert_equals(getComputedStyle(document.documentElement, ":view-transition").position, "fixed");
+ assert_equals(getComputedStyle(document.documentElement, ":view-transition-group(target)").position, "absolute");
+ assert_equals(getComputedStyle(document.documentElement, ":view-transition-image-pair(target)").position, "absolute");
+
+ assert_equals(getComputedStyle(document.documentElement, ":view-transition-old(target)").position, "absolute");
+
+ assert_equals(getComputedStyle(document.documentElement, ":view-transition-group(root)").position, "absolute");
+ assert_equals(getComputedStyle(document.documentElement, ":view-transition-image-pair(root)").position, "absolute");
+ assert_equals(getComputedStyle(document.documentElement, ":view-transition-old(root)").position, "absolute");
+ });
+
+ assert_equals(getComputedStyle(document.documentElement, ":view-transition").position, "fixed");
+ assert_equals(getComputedStyle(document.documentElement, ":view-transition-group(target)").position, "absolute");
+ assert_equals(getComputedStyle(document.documentElement, ":view-transition-image-pair(target)").position, "fixed");
+
+ assert_equals(getComputedStyle(document.documentElement, ":view-transition-old(target)").position, "absolute");
+ assert_equals(getComputedStyle(document.documentElement, ":view-transition-new(target)").position, "absolute");
+
+ assert_equals(getComputedStyle(document.documentElement, ":view-transition-group(root)").position, "absolute");
+ assert_equals(getComputedStyle(document.documentElement, ":view-transition-image-pair(root)").position, "absolute");
+ assert_equals(getComputedStyle(document.documentElement, ":view-transition-old(root)").position, "absolute");
+ assert_equals(getComputedStyle(document.documentElement, ":view-transition-new(root)").position, "absolute");
+
+ assert_equals(getComputedStyle(document.documentElement, ":view-transition-group(target)").position, "absolute");
+
+ await transition.finished;
+
+ // With custom ua sheets not applying to non-existing pseudo, the value should be the default (not absolute)
+ assert_not_equals(getComputedStyle(document.documentElement, ":view-transition-group(target)").position, "absolute");
+
+ resolve();
+ });
+}, "position property of pseudo elements with prepare api");
+</script>
diff --git a/testing/web-platform/tests/css/css-view-transitions/ready_resolves_after_dom_before_raf.html b/testing/web-platform/tests/css/css-view-transitions/ready_resolves_after_dom_before_raf.html
new file mode 100644
index 0000000000..3bc1822314
--- /dev/null
+++ b/testing/web-platform/tests/css/css-view-transitions/ready_resolves_after_dom_before_raf.html
@@ -0,0 +1,51 @@
+<!DOCTYPE html>
+<html>
+<title>Shared transitions: promise resolution ordering</title>
+<link rel="help" href="https://github.com/WICG/view-transitions">
+<link rel="author" href="mailto:vmpstr@chromium.org">
+
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+
+<style>
+div {
+ width: 100px;
+ height: 100px;
+ background: blue;
+ contain: paint;
+ view-transition-name: target;
+}
+.green {
+ background: green;
+}
+</style>
+
+<div id=target></div>
+
+<script>
+promise_test(async t => {
+ assert_implements(document.startViewTransition, "Missing document.startViewTransition");
+ return new Promise((resolve, reject) => {
+ let dom_change_ran = false;
+ let transition = document.startViewTransition(() => {
+ target.classList.add("green");
+ dom_change_ran = true;
+ });
+
+ let dom_updated_resolved = false;
+ transition.domUpdated.then(() => {
+ if (!dom_change_ran)
+ reject();
+ // If there's a rAF before ready resolves, we fail.
+ requestAnimationFrame(reject);
+ dom_updated_resolved = true;
+ });
+
+ transition.ready.then(() => {
+ if (!dom_updated_resolved)
+ reject();
+ resolve();
+ });
+ });
+}, "domUpdated resolves, then ready resolves with no rAF in between");
+</script>
diff --git a/testing/web-platform/tests/css/css-view-transitions/root-captured-as-different-tag-ref.html b/testing/web-platform/tests/css/css-view-transitions/root-captured-as-different-tag-ref.html
new file mode 100644
index 0000000000..1222d6440b
--- /dev/null
+++ b/testing/web-platform/tests/css/css-view-transitions/root-captured-as-different-tag-ref.html
@@ -0,0 +1,19 @@
+<!DOCTYPE html>
+<title>Shared transitions: capture root elements (ref)</title>
+<link rel="help" href="https://github.com/WICG/view-transitions">
+<link rel="author" href="mailto:vmpstr@chromium.org">
+<style>
+.box {
+ background: lightblue;
+ width: 100px;
+ height: 100px;
+ contain: paint;
+ position: absolute;
+ font-size: 30pt;
+}
+#e1 {
+ top: 20px;
+ left: 20px;
+}
+</style>
+<div id=e1 class=box></div>
diff --git a/testing/web-platform/tests/css/css-view-transitions/root-captured-as-different-tag.html b/testing/web-platform/tests/css/css-view-transitions/root-captured-as-different-tag.html
new file mode 100644
index 0000000000..a8f3493d67
--- /dev/null
+++ b/testing/web-platform/tests/css/css-view-transitions/root-captured-as-different-tag.html
@@ -0,0 +1,56 @@
+<!DOCTYPE html>
+<html class=reftest-wait>
+<title>Shared transitions: capture root elements</title>
+<link rel="help" href="https://github.com/WICG/view-transitions">
+<link rel="author" href="mailto:vmpstr@chromium.org">
+<link rel="match" href="old-content-captures-root-ref.html">
+<meta name="fuzzy" content="old-content-captures-root-ref.html:0-1;0-500">
+<script src="/common/reftest-wait.js"></script>
+<style>
+:root { view-transition-name: another-root; }
+.box {
+ background: lightblue;
+ width: 100px;
+ height: 100px;
+ contain: paint;
+ position: absolute;
+ font-size: 30pt;
+}
+#e1 {
+ top: 20px;
+ left: 20px;
+}
+#shared {
+ contain: paint;
+ width: 100px;
+ height: 100px;
+ background: red;
+ view-transition-name: shared;
+}
+
+div.dst { background: lightgreen; }
+/* We're verifying what we capture, so just display the old contents for 5 minutes. */
+html::view-transition { background: pink; }
+html::view-transition-group(shared) { animation-duration: 300s; }
+html::view-transition-image-pair(shared) { visibility: hidden }
+html::view-transition-old(another-root) { animation: unset; opacity: 1 }
+html::view-transition-new(another-root) { animation: unset; opacity: 0 }
+
+/* This shouldn't apply, so just make it red. */
+html::view-transition-group(root) { animation: unset; opacity: 1; background: red; }
+html::view-transition-image-pair(root) { visibility: hidden; }
+</style>
+<div id=e1 class=box></div>
+<div id=shared></div>
+<script>
+failIfNot(document.startViewTransition, "Missing document.startViewTransition");
+
+async function runTest() {
+ document.startViewTransition(() => {
+ e1.classList.add("dst");
+ document.body.style.background = "red";
+ requestAnimationFrame(() => requestAnimationFrame(takeScreenshot));
+ });
+}
+onload = () => requestAnimationFrame(() => requestAnimationFrame(runTest));
+</script>
diff --git a/testing/web-platform/tests/css/css-view-transitions/root-scrollbar-with-fixed-background-ref.html b/testing/web-platform/tests/css/css-view-transitions/root-scrollbar-with-fixed-background-ref.html
new file mode 100644
index 0000000000..d7014c4100
--- /dev/null
+++ b/testing/web-platform/tests/css/css-view-transitions/root-scrollbar-with-fixed-background-ref.html
@@ -0,0 +1,33 @@
+<!DOCTYPE html >
+<title>Shared transitions: capture root element with scrollbar (ref)</title>
+<link rel="help" href="https://github.com/WICG/view-transitions">
+<link rel="author" href="mailto:khushalsagar@chromium.org">
+
+<style>
+#container {
+ background: lightblue;
+}
+#first {
+ width: 10px;
+ background: linear-gradient(green, blue);
+ height: 1000px;
+}
+body {
+ margin: 0px;
+ padding: 0px;
+ filter: invert(1);
+}
+</style>
+
+ <div id=container>
+ <div id=first></div>
+ </div>
+
+<script>
+ function scrollContainer() {
+ document.documentElement.scrollTop = 500;
+ }
+
+ onload = scrollContainer();
+</script>
+</html>
diff --git a/testing/web-platform/tests/css/css-view-transitions/root-scrollbar-with-fixed-background.html b/testing/web-platform/tests/css/css-view-transitions/root-scrollbar-with-fixed-background.html
new file mode 100644
index 0000000000..9a4684c347
--- /dev/null
+++ b/testing/web-platform/tests/css/css-view-transitions/root-scrollbar-with-fixed-background.html
@@ -0,0 +1,67 @@
+<!DOCTYPE html>
+<html class=reftest-wait style="background: lightblue;">
+<title>When the root element has scrollbars, these should be excluded in snapshot</title>
+<link rel="help" href="https://github.com/WICG/view-transitions">
+<link rel="author" href="mailto:khushalsagar@chromium.org">
+<link rel="match" href="root-scrollbar-with-fixed-background-ref.html">
+
+<script src="/common/rendering-utils.js"></script>
+<script src="/common/reftest-wait.js"></script>
+
+<style>
+#hide {
+ position: absolute;
+ top: 0px;
+ left: 0px;
+ width: 10px;
+ height: 10px;
+ background: red;
+ contain: paint;
+ view-transition-name: hide;
+}
+#first {
+ width: 10px;
+ background: linear-gradient(green, blue);
+ height: 1000px;
+}
+body {
+ margin: 0px;
+ padding: 0px;
+}
+
+/* Set a no-op animation to screenshot the pseudo transition DOM. */
+html::view-transition-group(hide) {
+ animation-duration: 300s;
+ opacity: 0;
+}
+html::view-transition-new(*) {
+ animation: unset;
+ filter: invert(1);
+ height: 100%;
+}
+html::view-transition-old(*) {
+ animation: unset;
+ opacity: 0;
+ height: 100%;
+}
+</style>
+
+<div id=hide></div>
+<div id=first></div>
+
+<script>
+failIfNot(document.startViewTransition, "Missing document.startViewTransition");
+
+async function runTest() {
+ await waitForAtLeastOneFrame();
+
+ document.documentElement.scrollTop = 500;
+ document.startViewTransition(() => {
+ requestAnimationFrame(() => requestAnimationFrame(takeScreenshot));
+ });
+}
+
+onload = requestAnimationFrame(runTest);
+</script>
+
+</html>
diff --git a/testing/web-platform/tests/css/css-view-transitions/root-style-change-during-animation-ref.html b/testing/web-platform/tests/css/css-view-transitions/root-style-change-during-animation-ref.html
new file mode 100644
index 0000000000..964b3b8d7e
--- /dev/null
+++ b/testing/web-platform/tests/css/css-view-transitions/root-style-change-during-animation-ref.html
@@ -0,0 +1,20 @@
+<!DOCTYPE html>
+<html>
+<title>Shared transitions: root element style changes during transition</title>
+<link rel="help" href="https://github.com/WICG/view-transitions">
+<link rel="author" href="mailto:vmpstr@chromium.org">
+<style>
+#target {
+ width: 100px;
+ height: 100px;
+ contain: paint;
+ background: green;
+}
+
+body {
+ background: grey;
+}
+</style>
+
+<div id=target></div>
+
diff --git a/testing/web-platform/tests/css/css-view-transitions/root-style-change-during-animation.html b/testing/web-platform/tests/css/css-view-transitions/root-style-change-during-animation.html
new file mode 100644
index 0000000000..b030d38ab1
--- /dev/null
+++ b/testing/web-platform/tests/css/css-view-transitions/root-style-change-during-animation.html
@@ -0,0 +1,65 @@
+<!DOCTYPE html>
+<html class=reftest-wait>
+<title>Shared transitions: root element style changes during transition</title>
+<link rel="help" href="https://github.com/WICG/view-transitions">
+<link rel="author" href="mailto:vmpstr@chromium.org">
+<link rel="match" href="root-style-change-during-animation-ref.html">
+<script src="/common/reftest-wait.js"></script>
+<style>
+#target {
+ width: 100px;
+ height: 100px;
+ contain: paint;
+ background: blue;
+ view-transition-name: target;
+}
+
+#hidden {
+ background: pink;
+ width: 10px;
+ height: 10px;
+ view-transition-name: hidden;
+ contain: paint;
+}
+
+html::view-transition {
+ background: grey;
+}
+
+html::view-transition-group(hidden) {
+ animation-duration: 500s;
+ visibility: hidden;
+}
+
+html::view-transition-group(root) {
+ visibility: hidden;
+}
+
+.test::view-transition-group(target) {
+ background: green;
+}
+.test::view-transition-image-pair(target) {
+ visibility: hidden;
+}
+</style>
+
+<div id=target></div>
+<div id=hidden></div>
+
+<script>
+failIfNot(document.startViewTransition, "Missing document.startViewTransition");
+
+function flipClass() {
+ document.documentElement.classList.add("test");
+ requestAnimationFrame(takeScreenshot);
+}
+
+async function runTest() {
+ document.startViewTransition(() => {
+ hidden.style.width="20px";
+ requestAnimationFrame(() => requestAnimationFrame(flipClass));
+ });
+}
+onload = () => requestAnimationFrame(() => requestAnimationFrame(runTest));
+</script>
+
diff --git a/testing/web-platform/tests/css/css-view-transitions/root-to-shared-animation-end-ref.html b/testing/web-platform/tests/css/css-view-transitions/root-to-shared-animation-end-ref.html
new file mode 100644
index 0000000000..24b50fa65e
--- /dev/null
+++ b/testing/web-platform/tests/css/css-view-transitions/root-to-shared-animation-end-ref.html
@@ -0,0 +1,26 @@
+<!DOCTYPE html>
+<html>
+<title>Root to shared animation test (ref)</title>
+<link rel="help" href="https://github.com/WICG/view-transitions">
+<link rel="author" href="mailto:vmpstr@chromium.org">
+
+<style>
+body, html { padding: 0; margin: 0 }
+body {
+ background: yellow;
+}
+.background {
+ background: lightgreen;
+ width: 400px;
+ height: 300px;
+}
+.item {
+ background: blue;
+ width: 200px;
+ height: 200px;
+}
+</style>
+
+<div class=background>
+ <div class=item></div>
+</div>
diff --git a/testing/web-platform/tests/css/css-view-transitions/root-to-shared-animation-end.html b/testing/web-platform/tests/css/css-view-transitions/root-to-shared-animation-end.html
new file mode 100644
index 0000000000..6ba07bd9e6
--- /dev/null
+++ b/testing/web-platform/tests/css/css-view-transitions/root-to-shared-animation-end.html
@@ -0,0 +1,53 @@
+<!DOCTYPE html>
+<html class=reftest-wait>
+<link rel="help" href="https://github.com/WICG/view-transitions">
+<link rel="author" href="mailto:vmpstr@chromium.org">
+<link rel="match" href="root-to-shared-animation-end-ref.html">
+
+<script src="/common/reftest-wait.js"></script>
+
+<style>
+body, html { padding: 0; margin: 0 }
+body {
+ background: lightgreen;
+}
+#box {
+ width: 400px;
+ height: 400px;
+ background: blue;
+ contain: paint;
+}
+.hidden {
+ contain: paint;
+ width: 10px;
+ height: 10px;
+ background: red;
+ view-transition-name: hidden;
+}
+
+html::view-transition-group(hidden) { animation-duration: 300s; }
+html::view-transition-image-pair(hidden) { visibility: hidden; }
+
+html::view-transition-group(root) { animation-duration: 0s; }
+html::view-transition-new(*) { animation: unset; opacity: 0; }
+html::view-transition-old(*) { animation: unset; opacity: 1; }
+</style>
+
+<div id=box></div>
+<div class=hidden></div>
+
+<script>
+failIfNot(document.startViewTransition, "Missing document.startViewTransition");
+
+async function runTest() {
+ document.startViewTransition(() => {
+ document.documentElement.style.viewTransitionName = "none";
+ document.body.style.background = "yellow";
+ box.style.viewTransitionName = "root";
+
+ requestAnimationFrame(() => requestAnimationFrame(takeScreenshot));
+ });
+}
+onload = () => requestAnimationFrame(() => requestAnimationFrame(runTest));
+</script>
+
diff --git a/testing/web-platform/tests/css/css-view-transitions/root-to-shared-animation-incoming-ref.html b/testing/web-platform/tests/css/css-view-transitions/root-to-shared-animation-incoming-ref.html
new file mode 100644
index 0000000000..3075d2480c
--- /dev/null
+++ b/testing/web-platform/tests/css/css-view-transitions/root-to-shared-animation-incoming-ref.html
@@ -0,0 +1,13 @@
+<!DOCTYPE html>
+<html>
+<title>Root to shared animation test (ref)</title>
+<link rel="help" href="https://github.com/WICG/view-transitions">
+<link rel="author" href="mailto:vmpstr@chromium.org">
+
+<style>
+body {
+ background: blue;
+ padding: 0;
+ margin: 0;
+}
+
diff --git a/testing/web-platform/tests/css/css-view-transitions/root-to-shared-animation-incoming.html b/testing/web-platform/tests/css/css-view-transitions/root-to-shared-animation-incoming.html
new file mode 100644
index 0000000000..0620e911cf
--- /dev/null
+++ b/testing/web-platform/tests/css/css-view-transitions/root-to-shared-animation-incoming.html
@@ -0,0 +1,44 @@
+<!DOCTYPE html>
+<html class=reftest-wait>
+<link rel="help" href="https://github.com/WICG/view-transitions">
+<link rel="author" href="mailto:vmpstr@chromium.org">
+<link rel="match" href="root-to-shared-animation-incoming-ref.html">
+
+<script src="/common/reftest-wait.js"></script>
+
+<style>
+body {
+ background: lightgreen;
+ padding: 0;
+ margin: 0;
+}
+#box {
+ width: 100px;
+ height: 120px;
+ background: blue;
+ contain: paint;
+}
+
+html::view-transition-group(*) { animation-delay: 300s; }
+html::view-transition-new(*) { animation: unset; opacity: 1; }
+html::view-transition-old(*) { animation: unset; opacity: 0; }
+</style>
+
+<div id=box></div>
+
+<script>
+failIfNot(document.startViewTransition, "Missing document.startViewTransition");
+
+async function runTest() {
+ document.startViewTransition(() => {
+ document.documentElement.style.viewTransitionName = "none";
+ box.style.viewTransitionName = "root";
+ // We should not see the "live" body at all.
+ document.body.style.background = "red";
+
+ requestAnimationFrame(() => requestAnimationFrame(takeScreenshot));
+ });
+}
+onload = () => requestAnimationFrame(() => requestAnimationFrame(runTest));
+</script>
+
diff --git a/testing/web-platform/tests/css/css-view-transitions/root-to-shared-animation-start-ref.html b/testing/web-platform/tests/css/css-view-transitions/root-to-shared-animation-start-ref.html
new file mode 100644
index 0000000000..d04ab3f767
--- /dev/null
+++ b/testing/web-platform/tests/css/css-view-transitions/root-to-shared-animation-start-ref.html
@@ -0,0 +1,21 @@
+<!DOCTYPE html>
+<html>
+<title>Root to shared animation test (ref)</title>
+<link rel="help" href="https://github.com/WICG/view-transitions">
+<link rel="author" href="mailto:vmpstr@chromium.org">
+
+<style>
+body {
+ background: lightgreen;
+ padding: 0;
+ margin: 0;
+}
+#box {
+ width: 100px;
+ height: 120px;
+ background: blue;
+ contain: paint;
+}
+</style>
+
+<div id=box></div>
diff --git a/testing/web-platform/tests/css/css-view-transitions/root-to-shared-animation-start.html b/testing/web-platform/tests/css/css-view-transitions/root-to-shared-animation-start.html
new file mode 100644
index 0000000000..0a1cb9617e
--- /dev/null
+++ b/testing/web-platform/tests/css/css-view-transitions/root-to-shared-animation-start.html
@@ -0,0 +1,44 @@
+<!DOCTYPE html>
+<html class=reftest-wait>
+<link rel="help" href="https://github.com/WICG/view-transitions">
+<link rel="author" href="mailto:vmpstr@chromium.org">
+<link rel="match" href="root-to-shared-animation-start-ref.html">
+
+<script src="/common/reftest-wait.js"></script>
+
+<style>
+body {
+ background: lightgreen;
+ padding: 0;
+ margin: 0;
+}
+#box {
+ width: 100px;
+ height: 120px;
+ background: blue;
+ contain: paint;
+}
+
+html::view-transition-group(*) { animation-delay: 300s; }
+html::view-transition-new(*) { animation: unset; opacity: 0; }
+html::view-transition-old(*) { animation: unset; opacity: 1; }
+</style>
+
+<div id=box></div>
+
+<script>
+failIfNot(document.startViewTransition, "Missing document.startViewTransition");
+
+async function runTest() {
+ document.startViewTransition(() => {
+ document.documentElement.style.viewTransitionName = "none";
+ box.style.viewTransitionName = "root";
+ // We should not see the "live" body at all.
+ document.body.style.background = "red";
+
+ requestAnimationFrame(() => requestAnimationFrame(takeScreenshot));
+ });
+}
+onload = () => requestAnimationFrame(() => requestAnimationFrame(runTest));
+</script>
+
diff --git a/testing/web-platform/tests/css/css-view-transitions/scroller-child-abspos-ref.html b/testing/web-platform/tests/css/css-view-transitions/scroller-child-abspos-ref.html
new file mode 100644
index 0000000000..fd84030f71
--- /dev/null
+++ b/testing/web-platform/tests/css/css-view-transitions/scroller-child-abspos-ref.html
@@ -0,0 +1,40 @@
+<!DOCTYPE html>
+<title>View transitions: scroller child element (ref)</title>
+<link rel="help" href="https://www.w3.org/TR/css-view-transitions-1/">
+<link rel="author" href="mailto:vmpstr@chromium.org">
+
+<style>
+#target {
+ contain: layout;
+ width: 200px;
+ height: 200px;
+ background: yellow;
+}
+#scroller {
+ overflow: scroll;
+ width: 100px;
+ height: 100px;
+ background: blue;
+ isolation: isolate;
+}
+
+#child {
+ position: absolute;
+ width: 100px;
+ height: 100px;
+ background: green;
+ top: 200px;
+}
+</style>
+
+<div id="target">
+ <div id="scroller">
+ <div id="child"></div>
+ </div>
+</div>
+
+<script>
+onload = () => { scroller.scrollTop = 300; };
+</script>
+
+
diff --git a/testing/web-platform/tests/css/css-view-transitions/scroller-child-abspos.html b/testing/web-platform/tests/css/css-view-transitions/scroller-child-abspos.html
new file mode 100644
index 0000000000..952a2679aa
--- /dev/null
+++ b/testing/web-platform/tests/css/css-view-transitions/scroller-child-abspos.html
@@ -0,0 +1,61 @@
+<!DOCTYPE html>
+<html class=reftest-wait>
+<title>View transitions: scroller child element</title>
+<link rel="help" href="https://www.w3.org/TR/css-view-transitions-1/">
+<link rel="author" href="mailto:vmpstr@chromium.org">
+<link rel="match" href="scroller-child-abspos-ref.html">
+<meta name="fuzzy" content="scroller-child-abspos-ref.html:0-5;0-800">
+<script src="/common/reftest-wait.js"></script>
+
+<style>
+#target {
+ contain: layout;
+ view-transition-name: target;
+ width: 200px;
+ height: 200px;
+ background: yellow;
+}
+#scroller {
+ overflow: scroll;
+ width: 100px;
+ height: 100px;
+ background: blue;
+ isolation: isolate;
+}
+
+#child {
+ position: absolute;
+ width: 100px;
+ height: 100px;
+ background: green;
+ top: 200px;
+}
+
+html::view-transition-container(root) { animation-duration: 300s; }
+html::view-transition-old(target) {
+ animation: unset;
+ opacity: 1;
+}
+html::view-transition-new(target) {
+ animation: unset;
+ opacity: 0;
+}
+</style>
+
+<div id="target">
+ <div id="scroller">
+ <div id="child"></div>
+ </div>
+</div>
+
+<script>
+function runTest() {
+ scroller.scrollTop = 300;
+
+ let transition = document.startViewTransition();
+ transition.ready.then(() => requestAnimationFrame(takeScreenshot));
+}
+
+onload = () => requestAnimationFrame(() => requestAnimationFrame(runTest));
+</script>
+
diff --git a/testing/web-platform/tests/css/css-view-transitions/scroller-child-ref.html b/testing/web-platform/tests/css/css-view-transitions/scroller-child-ref.html
new file mode 100644
index 0000000000..be7e69ac31
--- /dev/null
+++ b/testing/web-platform/tests/css/css-view-transitions/scroller-child-ref.html
@@ -0,0 +1,38 @@
+<!DOCTYPE html>
+<title>View transitions: scroller child element (ref)</title>
+<link rel="help" href="https://www.w3.org/TR/css-view-transitions-1/">
+<link rel="author" href="mailto:vmpstr@chromium.org">
+
+<style>
+#target {
+ contain: layout;
+ width: 500px;
+ height: 500px;
+ background: yellow;
+}
+#scroller {
+ overflow: scroll;
+ width: 100px;
+ height: 100px;
+ background: blue;
+}
+
+#child {
+ position: relative;
+ width: 2000px;
+ height: 2000px;
+ background: green;
+}
+</style>
+
+<div id="target">
+ <div id="scroller">
+ <div id="child"></div>
+ </div>
+</div>
+
+<script>
+onload = () => { scroller.scrollTop = 300; };
+</script>
+
+
diff --git a/testing/web-platform/tests/css/css-view-transitions/scroller-child.html b/testing/web-platform/tests/css/css-view-transitions/scroller-child.html
new file mode 100644
index 0000000000..2c8a0c4477
--- /dev/null
+++ b/testing/web-platform/tests/css/css-view-transitions/scroller-child.html
@@ -0,0 +1,59 @@
+<!DOCTYPE html>
+<html class=reftest-wait>
+<title>View transitions: scroller child element</title>
+<link rel="help" href="https://www.w3.org/TR/css-view-transitions-1/">
+<link rel="author" href="mailto:vmpstr@chromium.org">
+<link rel="match" href="scroller-child-ref.html">
+<meta name="fuzzy" content="scroller-child-ref.html:0-5;0-800">
+<script src="/common/reftest-wait.js"></script>
+
+<style>
+#target {
+ contain: layout;
+ view-transition-name: target;
+ width: 500px;
+ height: 500px;
+ background: yellow;
+}
+#scroller {
+ overflow: scroll;
+ width: 100px;
+ height: 100px;
+ background: blue;
+}
+
+#child {
+ position: relative;
+ width: 2000px;
+ height: 2000px;
+ background: green;
+}
+
+html::view-transition-container(root) { animation-duration: 300s; }
+html::view-transition-old(target) {
+ animation: unset;
+ opacity: 1;
+}
+html::view-transition-new(target) {
+ animation: unset;
+ opacity: 0;
+}
+</style>
+
+<div id="target">
+ <div id="scroller">
+ <div id="child"></div>
+ </div>
+</div>
+
+<script>
+function runTest() {
+ scroller.scrollTop = 300;
+
+ let transition = document.startViewTransition();
+ transition.ready.then(() => requestAnimationFrame(takeScreenshot));
+}
+
+onload = () => requestAnimationFrame(() => requestAnimationFrame(runTest));
+</script>
+
diff --git a/testing/web-platform/tests/css/css-view-transitions/scroller-ref.html b/testing/web-platform/tests/css/css-view-transitions/scroller-ref.html
new file mode 100644
index 0000000000..9a764e74c7
--- /dev/null
+++ b/testing/web-platform/tests/css/css-view-transitions/scroller-ref.html
@@ -0,0 +1,31 @@
+<!DOCTYPE html>
+<title>View transitions: scroller element (ref)</title>
+<link rel="help" href="https://www.w3.org/TR/css-view-transitions-1/">
+<link rel="author" href="mailto:vmpstr@chromium.org">
+
+<style>
+#scroller {
+ overflow: scroll;
+ width: 100px;
+ height: 100px;
+ background: blue;
+ contain: layout;
+}
+
+#child {
+ position: relative;
+ width: 1000px;
+ height: 1000px;
+ background: green;
+}
+</style>
+
+<div id="scroller">
+ <div id="child"></div>
+</div>
+
+<script>
+onload = () => { scroller.scrollTop = 300; };
+</script>
+
+
diff --git a/testing/web-platform/tests/css/css-view-transitions/scroller.html b/testing/web-platform/tests/css/css-view-transitions/scroller.html
new file mode 100644
index 0000000000..ecc413b255
--- /dev/null
+++ b/testing/web-platform/tests/css/css-view-transitions/scroller.html
@@ -0,0 +1,52 @@
+<!DOCTYPE html>
+<html class=reftest-wait>
+<title>View transitions: scroller element</title>
+<link rel="help" href="https://www.w3.org/TR/css-view-transitions-1/">
+<link rel="author" href="mailto:vmpstr@chromium.org">
+<link rel="match" href="scroller-ref.html">
+<meta name="fuzzy" content="scroller-ref.html:0-5;0-10">
+<script src="/common/reftest-wait.js"></script>
+
+<style>
+#scroller {
+ overflow: scroll;
+ width: 100px;
+ height: 100px;
+ background: blue;
+ contain: layout;
+ view-transition-name: target;
+}
+
+#child {
+ position: relative;
+ width: 1000px;
+ height: 1000px;
+ background: green;
+}
+
+html::view-transition-container(root) { animation-duration: 300s; }
+html::view-transition-old(target) {
+ animation: unset;
+ opacity: 1;
+}
+html::view-transition-new(target) {
+ animation: unset;
+ opacity: 0;
+}
+</style>
+
+<div id="scroller">
+ <div id="child"></div>
+</div>
+
+<script>
+function runTest() {
+ scroller.scrollTop = 300;
+
+ let transition = document.startViewTransition();
+ transition.ready.then(() => requestAnimationFrame(takeScreenshot));
+}
+
+onload = () => requestAnimationFrame(() => requestAnimationFrame(runTest));
+</script>
+
diff --git a/testing/web-platform/tests/css/css-view-transitions/set-current-time-ref.html b/testing/web-platform/tests/css/css-view-transitions/set-current-time-ref.html
new file mode 100644
index 0000000000..2cf8742768
--- /dev/null
+++ b/testing/web-platform/tests/css/css-view-transitions/set-current-time-ref.html
@@ -0,0 +1,15 @@
+<!DOCTYPE html>
+<title>View transitions: set current time (reference)</title>
+<link rel="help" href="https://www.w3.org/TR/css-view-transitions-1/">
+<link rel="author" href="mailto:vmpstr@chromium.org">
+<style>
+.target {
+ width: 100px;
+ height: 100px;
+ contain: layout;
+ background: blue;
+ opacity: 0.5;
+}
+</style>
+
+<div class=target></div>
diff --git a/testing/web-platform/tests/css/css-view-transitions/set-current-time-transform-ref.html b/testing/web-platform/tests/css/css-view-transitions/set-current-time-transform-ref.html
new file mode 100644
index 0000000000..2e977ce262
--- /dev/null
+++ b/testing/web-platform/tests/css/css-view-transitions/set-current-time-transform-ref.html
@@ -0,0 +1,40 @@
+<!DOCTYPE html>
+<html class=reftest-wait>
+<title>View transitions: set current time</title>
+<link rel="help" href="https://www.w3.org/TR/css-view-transitions-1/">
+<link rel="author" href="mailto:vmpstr@chromium.org">
+<script src="/common/reftest-wait.js"></script>
+<style>
+@keyframes move {
+ from {
+ transform: translate(500px);
+ }
+}
+#target {
+ width: 100px;
+ height: 100px;
+ contain: layout;
+ background: blue;
+ view-transition-name: target;
+ position: relative;
+ left: 100px;
+
+ animation-name: move;
+ animation-duration: 1s;
+ animation-timing-function: linear;
+ animation-play-state: paused;
+}
+</style>
+
+<div id=target></div>
+
+<script>
+function runReference() {
+ document.getAnimations().forEach((animation) => {
+ animation.currentTime = 500;
+ });
+ takeScreenshot();
+}
+onload = () => requestAnimationFrame(() => requestAnimationFrame(runReference));
+</script>
+
diff --git a/testing/web-platform/tests/css/css-view-transitions/set-current-time-transform.html b/testing/web-platform/tests/css/css-view-transitions/set-current-time-transform.html
new file mode 100644
index 0000000000..9958a0bdca
--- /dev/null
+++ b/testing/web-platform/tests/css/css-view-transitions/set-current-time-transform.html
@@ -0,0 +1,61 @@
+<!DOCTYPE html>
+<html class=reftest-wait>
+<title>View transitions: set current time</title>
+<link rel="help" href="https://www.w3.org/TR/css-view-transitions-1/">
+<link rel="author" href="mailto:vmpstr@chromium.org">
+<link rel="match" href="set-current-time-transform-ref.html">
+<script src="/common/reftest-wait.js"></script>
+<style>
+:root { view-transition-name: unset; }
+#target {
+ width: 100px;
+ height: 100px;
+ contain: layout;
+ background: blue;
+ view-transition-name: target;
+ position: relative;
+}
+.left {
+ left: 0;
+}
+.right {
+ left: 100px;
+}
+
+html::view-transition-group(*) {
+ animation: unset;
+}
+html::view-transition-old(*) {
+ animation: unset;
+ opacity: 0;
+}
+@keyframes move {
+ from {
+ transform: translate(500px);
+ }
+}
+html::view-transition-new(target) {
+ animation-name: move;
+ animation-duration: 1s;
+ animation-timing-function: linear;
+ animation-play-state: paused;
+}
+</style>
+
+<div id=target class=left></div>
+
+<script>
+async function runTest() {
+ let transition = document.startViewTransition(() => target.classList.replace("left", "right"));
+ transition.ready.then(() => {
+ requestAnimationFrame(() => requestAnimationFrame(() => {
+ document.getAnimations().forEach((animation) => {
+ animation.currentTime = 500;
+ });
+ requestAnimationFrame(takeScreenshot);
+ }));
+ });
+}
+onload = () => requestAnimationFrame(() => requestAnimationFrame(runTest));
+</script>
+
diff --git a/testing/web-platform/tests/css/css-view-transitions/set-current-time.html b/testing/web-platform/tests/css/css-view-transitions/set-current-time.html
new file mode 100644
index 0000000000..efb5ffb8ae
--- /dev/null
+++ b/testing/web-platform/tests/css/css-view-transitions/set-current-time.html
@@ -0,0 +1,47 @@
+<!DOCTYPE html>
+<html class=reftest-wait>
+<title>View transitions: set current time</title>
+<link rel="help" href="https://www.w3.org/TR/css-view-transitions-1/">
+<link rel="author" href="mailto:vmpstr@chromium.org">
+<link rel="match" href="set-current-time-ref.html">
+<script src="/common/reftest-wait.js"></script>
+<style>
+:root { view-transition-name: unset; }
+.target {
+ width: 100px;
+ height: 100px;
+ contain: layout;
+ background: blue;
+ view-transition-name: target;
+}
+
+html::view-transition-group(*) {
+ animation: unset;
+}
+html::view-transition-old(*) {
+ animation: unset;
+}
+html::view-transition-new(target) {
+ animation-duration: 1s;
+ animation-timing-function: linear;
+ animation-play-state: paused;
+}
+</style>
+
+<div id=target></div>
+
+<script>
+async function runTest() {
+ let transition = document.startViewTransition(() => target.classList.add("target"));
+ transition.ready.then(() => {
+ requestAnimationFrame(() => requestAnimationFrame(() => {
+ document.getAnimations().forEach((animation) => {
+ animation.currentTime = 500;
+ });
+ requestAnimationFrame(takeScreenshot);
+ }));
+ });
+}
+onload = () => requestAnimationFrame(() => requestAnimationFrame(runTest));
+</script>
+
diff --git a/testing/web-platform/tests/css/css-view-transitions/set-universal-specificity-ref.html b/testing/web-platform/tests/css/css-view-transitions/set-universal-specificity-ref.html
new file mode 100644
index 0000000000..e6afd805fb
--- /dev/null
+++ b/testing/web-platform/tests/css/css-view-transitions/set-universal-specificity-ref.html
@@ -0,0 +1,17 @@
+<!DOCTYPE html>
+<title>Shared transitions: universal specificity (ref)</title>
+<link rel="help" href="https://github.com/WICG/view-transitions">
+<link rel="author" href="mailto:vmpstr@chromium.org">
+<style>
+body {
+ background: pink;
+}
+div {
+ contain: paint;
+ width: 100px;
+ height: 100px;
+ background: blue;
+ border: 10px solid black;
+}
+</style>
+<div></div>
diff --git a/testing/web-platform/tests/css/css-view-transitions/set-universal-specificity.html b/testing/web-platform/tests/css/css-view-transitions/set-universal-specificity.html
new file mode 100644
index 0000000000..80dc8272b5
--- /dev/null
+++ b/testing/web-platform/tests/css/css-view-transitions/set-universal-specificity.html
@@ -0,0 +1,45 @@
+<!DOCTYPE html>
+<html class=reftest-wait>
+<title>Shared transitions: universal specificity</title>
+<link rel="help" href="https://github.com/WICG/view-transitions">
+<link rel="author" href="mailto:vmpstr@chromium.org">
+<link rel="match" href="set-universal-specificity-ref.html">
+<script src="/common/reftest-wait.js"></script>
+<style>
+#shared {
+ contain: paint;
+ width: 100px;
+ height: 100px;
+ background: blue;
+ view-transition-name: shared;
+}
+
+/* We're verifying what we capture, so just display the old contents for 5 minutes. */
+html::view-transition { background: pink; }
+html::view-transition-group(shared) { animation-duration: 300s; }
+
+html::view-transition-old(shared) {
+ animation: unset;
+ opacity: 1;
+ border: 10px solid black;
+}
+html::view-transition-old(*) {
+ border: 10px solid red;
+}
+
+html::view-transition-new(shared) { animation: unset; opacity: 0; }
+
+html::view-transition-old(root) { animation: unset; opacity: 0; }
+html::view-transition-new(root) { animation: unset; opacity: 0 }
+</style>
+<div id=shared></div>
+<script>
+failIfNot(document.startViewTransition, "Missing document.startViewTransition");
+
+async function runTest() {
+ document.startViewTransition(() => {
+ requestAnimationFrame(() => requestAnimationFrame(takeScreenshot));
+ });
+}
+onload = () => requestAnimationFrame(() => requestAnimationFrame(runTest));
+</script>
diff --git a/testing/web-platform/tests/css/css-view-transitions/shared-transition-author-style.manual.html b/testing/web-platform/tests/css/css-view-transitions/shared-transition-author-style.manual.html
new file mode 100644
index 0000000000..2e0dc49d78
--- /dev/null
+++ b/testing/web-platform/tests/css/css-view-transitions/shared-transition-author-style.manual.html
@@ -0,0 +1,94 @@
+<!DOCTYPE html>
+<html>
+<title>Shared transitions of different elements and shapes</title>
+<link rel="help" href="https://github.com/vmpstr/view-transitions">
+<link rel="author" href="mailto:vmpstr@chromium.org">
+
+<style>
+body {
+ background: lightpink;
+ overflow: hidden;
+}
+
+input {
+ position: absolute;
+ left: 8px;
+ top: 8px;
+ z-index: 10;
+}
+
+.top {
+ top: 0px;
+ background: green;
+}
+.bottom {
+ bottom: 0px;
+ background: blue;
+}
+
+div {
+ position: absolute;
+ left: 0px;
+ right: 0px;
+ height: 40vh;
+ contain: paint;
+}
+</style>
+
+<input id=toggle type=button value="Toggle!"></input>
+<div id=target class=top>
+The div should alternate being at the bottom and at the top.
+The color at the top is green and bottom is blue.
+During the animation, the div has an (x, y) offset and its
+content is a blend of green and blue. There is also a grey
+background with a slight offset from the top.
+</div>
+
+<script>
+let classes = ["top", "bottom"]
+let i = 0;
+
+let transitionStyle =
+ `html::view-transition {
+ top: 50px;
+ }
+
+ html::view-transition-group(root) {
+ background-color: grey;
+ }
+
+ html::view-transition-group(target) {
+ left: 50px;
+ }
+
+ html::view-transition-old(target) {
+ opacity: 0.5;
+ animation-name: none;
+ }
+
+ html::view-transition-new(target) {
+ opacity: 0.5;
+ }
+ `
+
+let pseudoStyle = document.createElement('style');
+pseudoStyle.appendChild(document.createTextNode(transitionStyle));
+
+async function runAnimation() {
+ target.style.viewTransitionName = "target";
+ let t = document.startViewTransition(() => {
+ target.classList.remove(classes[i]);
+ i = (i + 1) % classes.length;
+ target.classList.add(classes[i]);
+
+ document.head.appendChild(pseudoStyle);
+ });
+ await t.finished;
+ document.head.removeChild(pseudoStyle)
+}
+
+function init() {
+ toggle.addEventListener("click", runAnimation);
+}
+onload = init;
+</script>
diff --git a/testing/web-platform/tests/css/css-view-transitions/shared-transition-half.manual.html b/testing/web-platform/tests/css/css-view-transitions/shared-transition-half.manual.html
new file mode 100644
index 0000000000..d78df70cb8
--- /dev/null
+++ b/testing/web-platform/tests/css/css-view-transitions/shared-transition-half.manual.html
@@ -0,0 +1,60 @@
+<!DOCTYPE html>
+<html>
+<title>Shared transitions of different elements and shapes</title>
+<link rel="help" href="https://github.com/vmpstr/view-transitions">
+<link rel="author" href="mailto:vmpstr@chromium.org">
+
+<style>
+body {
+ background: lightpink;
+ overflow: hidden;
+}
+
+input {
+ position: absolute;
+ left: 8px;
+ top: 8px;
+ z-index: 10;
+}
+
+.top {
+ top: 0px;
+}
+.bottom {
+ bottom: 0px;
+}
+
+div {
+ position: absolute;
+ left: 0px;
+ right: 0px;
+ height: 40vh;
+ background: green;
+ contain: paint;
+}
+</style>
+
+<input id=toggle type=button value="Toggle!"></input>
+<div id=target class=top>
+The green div should alternate being at the bottom and at the top.
+Other than green and pink background no other colors should appear.
+</div>
+
+<script>
+let classes = ["top", "bottom"]
+let i = 0;
+async function runAnimation() {
+ target.style.viewTransitionName = "target";
+ let t = document.startViewTransition(() => {
+ target.classList.remove(classes[i]);
+ i = (i + 1) % classes.length;
+ target.classList.add(classes[i]);
+ });
+ await t.finished;
+}
+
+function init() {
+ toggle.addEventListener("click", runAnimation);
+}
+onload = init;
+</script>
diff --git a/testing/web-platform/tests/css/css-view-transitions/shared-transition-shapes.manual.html b/testing/web-platform/tests/css/css-view-transitions/shared-transition-shapes.manual.html
new file mode 100644
index 0000000000..6b22a53fb4
--- /dev/null
+++ b/testing/web-platform/tests/css/css-view-transitions/shared-transition-shapes.manual.html
@@ -0,0 +1,80 @@
+<!DOCTYPE html>
+<html>
+<title>Shared transitions of different elements and shapes</title>
+<link rel="help" href="https://github.com/vmpstr/view-transitions">
+<link rel="author" href="mailto:vmpstr@chromium.org">
+
+<style>
+body {
+ background: lightpink;
+}
+
+#container {
+ width: max-content;
+ position: relative;
+}
+
+.left {
+ left: 50px;
+}
+.right {
+ left: 550px;
+}
+
+div {
+ margin: 10px;
+ contain: paint;
+}
+
+.square {
+ width: 100px;
+ height: 100px;
+ background: green;
+}
+.rounded {
+ width: 100px;
+ height: 100px;
+ background: green;
+ border-radius: 20%;
+}
+.translucent {
+ opacity: 0.5;
+}
+.text {
+ width: 100px;
+ height: 100px;
+}
+</style>
+
+<input id=toggle type=button value="Toggle!"></input>
+<span>Same shape should move right and left</span>
+<div id=container class=left>
+ <div id=e1 class=square></div>
+ <div id=e2 class=rounded></div>
+ <div id=e3 class="square translucent"></div>
+ <div id=e4 class="rounded translucent"></div>
+ <div id=e5 class=text>Lorem Ipsum</div>
+</div>
+
+<script>
+let classes = ["left", "right"]
+let i = 0;
+async function runAnimation() {
+ e1.style.viewTransitionName = "e1";
+ e2.style.viewTransitionName = "e2";
+ e3.style.viewTransitionName = "e3";
+ e4.style.viewTransitionName = "e4";
+ e5.style.viewTransitionName = "e5";
+ let t = document.startViewTransition(() => {
+ container.classList.remove(classes[i]);
+ i = (i + 1) % classes.length;
+ container.classList.add(classes[i]);
+ });
+ await t.finished;
+}
+
+function init() {
+ toggle.addEventListener("click", runAnimation);
+}
+onload = init;
+</script>
diff --git a/testing/web-platform/tests/css/css-view-transitions/style-inheritance.html b/testing/web-platform/tests/css/css-view-transitions/style-inheritance.html
new file mode 100644
index 0000000000..70788842be
--- /dev/null
+++ b/testing/web-platform/tests/css/css-view-transitions/style-inheritance.html
@@ -0,0 +1,56 @@
+<!DOCTYPE html>
+<html>
+<title>View transitions: ensure correct style inheritance for pseudo tree</title>
+<link rel="help" href="https://github.com/WICG/view-transitions">
+<link rel="author" href="mailto:khushalsagar@chromium.org">
+
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+
+<style>
+::view-transition {
+ background-color: red;
+}
+
+::view-transition-group(*) {
+ background-color: inherit;
+ color: blue;
+ animation-duration: 0.321s;
+}
+
+::view-transition-image-pair(*) {
+ color: inherit;
+ overflow-x: clip;
+}
+
+::view-transition-old(*), ::view-transition-new(*) {
+ overflow-x: inherit;
+}
+</style>
+
+<script>
+promise_test(() => {
+ assert_implements(document.startViewTransition, "Missing document.startViewTransition");
+ return new Promise(async (resolve, reject) => {
+ let transition = document.startViewTransition();
+ transition.ready.then(() => {
+ assert_equals(getComputedStyle(document.documentElement, ":view-transition").backgroundColor, "rgb(255, 0, 0)", ":view-transition");
+
+ assert_equals(getComputedStyle(document.documentElement, ":view-transition-group(root)").backgroundColor, "rgb(255, 0, 0)", "group");
+ assert_equals(getComputedStyle(document.documentElement, ":view-transition-group(root)").color, "rgb(0, 0, 255)", "group");
+ assert_equals(getComputedStyle(document.documentElement, ":view-transition-group(root)").animationDuration, "0.321s", "group");
+
+ assert_equals(getComputedStyle(document.documentElement, ":view-transition-image-pair(root)").color, "rgb(0, 0, 255)", "wrapper");
+ assert_equals(getComputedStyle(document.documentElement, ":view-transition-image-pair(root)").overflowX, "clip", "wrapper");
+ assert_equals(getComputedStyle(document.documentElement, ":view-transition-image-pair(root)").animationDuration, "0.321s", "wrapper");
+
+ assert_equals(getComputedStyle(document.documentElement, ":view-transition-old(root)").overflowX, "clip", "outgoing");
+ assert_equals(getComputedStyle(document.documentElement, ":view-transition-old(root)").animationDuration, "0.321s", "outgoing");
+ assert_equals(getComputedStyle(document.documentElement, ":view-transition-new(root)").overflowX, "clip", "incoming");
+ assert_equals(getComputedStyle(document.documentElement, ":view-transition-new(root)").animationDuration, "0.321s", "incoming");
+ });
+ await transition.finished;
+ resolve();
+ });
+}, "style inheritance of pseudo elements");
+</script>
diff --git a/testing/web-platform/tests/css/css-view-transitions/support/frame-helper.html b/testing/web-platform/tests/css/css-view-transitions/support/frame-helper.html
new file mode 100644
index 0000000000..d5bc43e7b8
--- /dev/null
+++ b/testing/web-platform/tests/css/css-view-transitions/support/frame-helper.html
@@ -0,0 +1,25 @@
+<!doctype html>
+
+<style>
+div {
+ width: 100px;
+ height: 100px;
+ background: green;
+}
+html { height: 50%; }
+::view-transition-group(*) { animation-duration: 500s }
+</style>
+
+<div></div>
+
+<script>
+function run() {
+ document.startViewTransition(() => {
+ requestAnimationFrame(() => requestAnimationFrame(() => {
+ window.parent.postMessage({}, "*");
+ }));
+ });
+}
+onload = requestAnimationFrame(() => requestAnimationFrame(run));
+</script>
+
diff --git a/testing/web-platform/tests/css/css-view-transitions/synchronous-callback-skipped-before-run.html b/testing/web-platform/tests/css/css-view-transitions/synchronous-callback-skipped-before-run.html
new file mode 100644
index 0000000000..d1ada87e9d
--- /dev/null
+++ b/testing/web-platform/tests/css/css-view-transitions/synchronous-callback-skipped-before-run.html
@@ -0,0 +1,37 @@
+<!DOCTYPE html>
+<html>
+<title>View transitions: skipTransition() invoked before a synchronous updateDOM callback is invoked</title>
+<link rel="help" href="https://www.w3.org/TR/css-view-transitions-1/">
+<link rel="author" href="mailto:khushalsagar@chromium.org">
+
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+
+<style>
+div {
+ width: 100px;
+ height: 100px;
+ background: blue;
+ contain: paint;
+}
+</style>
+
+<div id=first></div>
+
+<script>
+promise_test(async t => {
+ assert_implements(document.startViewTransition, "Missing document.startViewTransition");
+ return new Promise(async (resolve, reject) => {
+ let transition = document.startViewTransition(() => {
+ first.style.viewTransitionName = "target";
+ });
+ transition.skipTransition();
+ await transition.finished;
+
+ if (window.getComputedStyle(first).viewTransitionName == "target")
+ resolve();
+ else
+ reject();
+ });
+}, "finished promise should be resolved if skipTransition() is invoked before a synchronous domUpdated callback is dispatched");
+</script>
diff --git a/testing/web-platform/tests/css/css-view-transitions/transition-skipped-after-animation-started.html b/testing/web-platform/tests/css/css-view-transitions/transition-skipped-after-animation-started.html
new file mode 100644
index 0000000000..56c477a55f
--- /dev/null
+++ b/testing/web-platform/tests/css/css-view-transitions/transition-skipped-after-animation-started.html
@@ -0,0 +1,37 @@
+<!DOCTYPE html>
+<html>
+<title>View transitions: skipTransition() after animations have started running should resolve finished promise</title>
+<link rel="help" href="https://www.w3.org/TR/css-view-transitions-1/">
+<link rel="author" href="mailto:khushalsagar@chromium.org">
+
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+
+<style>
+div {
+ width: 100px;
+ height: 100px;
+ background: blue;
+ contain: paint;
+ view-transition-name: target;
+}
+
+::view-transition-group(target) {
+ animation-duration: 300s;
+}
+</style>
+
+<div id=first></div>
+
+<script>
+promise_test(async t => {
+ assert_implements(document.startViewTransition, "Missing document.startViewTransition");
+ return new Promise(async (resolve, reject) => {
+ let transition = document.startViewTransition();
+ await transition.ready;
+ transition.skipTransition();
+ await transition.finished;
+ resolve();
+ });
+}, "skipTransition() after animations have started running should resolve finished promise");
+</script>
diff --git a/testing/web-platform/tests/css/css-view-transitions/transition-skipped-from-invalid-callback.html b/testing/web-platform/tests/css/css-view-transitions/transition-skipped-from-invalid-callback.html
new file mode 100644
index 0000000000..0dd098cbdf
--- /dev/null
+++ b/testing/web-platform/tests/css/css-view-transitions/transition-skipped-from-invalid-callback.html
@@ -0,0 +1,46 @@
+<!DOCTYPE html>
+<html>
+<title>View transitions: transition skipped in animation phase</title>
+<link rel="help" href="https://www.w3.org/TR/css-view-transitions-1/">
+<link rel="author" href="mailto:khushalsagar@chromium.org">
+
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+
+<style>
+div {
+ width: 100px;
+ height: 100px;
+ background: blue;
+ contain: paint;
+ view-transition-name: target;
+}
+
+::view-transition-group(target) {
+ animation-duration: 300s;
+}
+</style>
+
+<div id=first></div>
+
+<script>
+promise_test(async t => {
+ assert_implements(document.startViewTransition, "Missing document.startViewTransition");
+ return new Promise(async (resolve, reject) => {
+ let transition = document.startViewTransition(() => {
+ let foo = bar;
+ });
+
+ let readyRejected = false;
+ transition.ready.then(reject, () => { readyRejected = true; });
+
+ let domUpdateRejected = false;
+ transition.domUpdated.then(reject, () => { domUpdateRejected = true; });
+ transition.finished.then(reject, () => {
+ assert_true(readyRejected, "ready not rejected");
+ assert_true(domUpdateRejected, "dom update not rejected");
+ resolve();
+ });
+ });
+}, "transition skipped because callback has invalid syntax");
+</script>
diff --git a/testing/web-platform/tests/css/css-view-transitions/unset-and-initial-view-transition-name.html b/testing/web-platform/tests/css/css-view-transitions/unset-and-initial-view-transition-name.html
new file mode 100644
index 0000000000..4ff5c05316
--- /dev/null
+++ b/testing/web-platform/tests/css/css-view-transitions/unset-and-initial-view-transition-name.html
@@ -0,0 +1,50 @@
+<!DOCTYPE html>
+<html>
+<title>View transitions: validates that view-transition-name: unset or initial are ignored</title>
+<link rel="help" href="https://www.w3.org/TR/css-view-transitions-1/">
+<link rel="author" href="mailto:khushalsagar@chromium.org">
+
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+
+<style>
+#first {
+ width: 100px;
+ height: 100px;
+ background: blue;
+ contain: paint;
+ view-transition-name: target;
+}
+#second {
+ width: 100px;
+ height: 100px;
+ background: blue;
+ view-transition-name: unset;
+}
+#third {
+ width: 100px;
+ height: 100px;
+ background: blue;
+ view-transition-name: initial;
+}
+</style>
+
+<div id=first></div>
+<div id=second></div>
+<div id=third></div>
+
+<script>
+promise_test(async t => {
+ assert_implements(document.startViewTransition, "Missing document.startViewTransition");
+ return new Promise(async (resolve, reject) => {
+ let transition = document.startViewTransition();
+ await transition.domUpdated;
+
+ // Elements with view-transition-name: initial and unset don't have
+ // containment. Because they are ignored they don't cause the transition to
+ // be skipped.
+ await transition.ready;
+ transition.finished.then(resolve, reject);
+ });
+}, "validates that view-transition-name: unset or initial are ignored");
+</script>
diff --git a/testing/web-platform/tests/css/css-view-transitions/view-transition-name-on-added-element.html b/testing/web-platform/tests/css/css-view-transitions/view-transition-name-on-added-element.html
new file mode 100644
index 0000000000..643121e818
--- /dev/null
+++ b/testing/web-platform/tests/css/css-view-transitions/view-transition-name-on-added-element.html
@@ -0,0 +1,37 @@
+<!DOCTYPE html>
+<html>
+<title>View transitions: ensures view-transition-name is tracked on element added by script</title>
+<link rel="help" href="https://www.w3.org/TR/css-view-transitions-1/">
+<link rel="author" href="mailto:khushalsagar@chromium.org">
+
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+
+<style>
+#first {
+ width: 100px;
+ height: 100px;
+ background: blue;
+ view-transition-name: first;
+}
+</style>
+<body>
+ <div>
+ <div id=first></div>
+ </div>
+</body>
+<script>
+promise_test(async t => {
+ assert_implements(document.startViewTransition, "Missing document.startViewTransition");
+ return new Promise((resolve, reject) => {
+ // Remove and add an uncontained element. Even though this element doesn't
+ // create a stacking context its verified during the transition.
+ const element = document.getElementById("first");
+ element.remove();
+ document.body.appendChild(element);
+
+ let transition = document.startViewTransition();
+ transition.ready.then(reject, resolve);
+ });
+}, "view-transition-name on an element added by script should be visited when discovering named elements");
+</script>
diff --git a/testing/web-platform/tests/css/css-view-transitions/view-transition-name-on-removed-element.html b/testing/web-platform/tests/css/css-view-transitions/view-transition-name-on-removed-element.html
new file mode 100644
index 0000000000..36beb30828
--- /dev/null
+++ b/testing/web-platform/tests/css/css-view-transitions/view-transition-name-on-removed-element.html
@@ -0,0 +1,36 @@
+<!DOCTYPE html>
+<html>
+<title>View transitions: ensures view-transition-name is not tracked on element removed by script</title>
+<link rel="help" href="https://www.w3.org/TR/css-view-transitions-1/">
+<link rel="author" href="mailto:khushalsagar@chromium.org">
+
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+
+<style>
+#first {
+ width: 100px;
+ height: 100px;
+ background: blue;
+ view-transition-name: first;
+}
+</style>
+<body>
+ <div>
+ <div id=first></div>
+ </div>
+</body>
+<script>
+promise_test(async t => {
+ assert_implements(document.startViewTransition, "Missing document.startViewTransition");
+ return new Promise(async (resolve, reject) => {
+ // Remove an uncontained element. Because this element is not visited when
+ // discovering named elements, the transition is not skipped.
+ first.remove();
+
+ let transition = document.startViewTransition();
+ await transition.ready;
+ transition.finished.then(resolve, reject);
+ });
+}, "view-transition-name on an element removed by script should not be visited when discovering named elements");
+</script>
diff --git a/testing/web-platform/tests/css/css-view-transitions/web-animations-api-ref.html b/testing/web-platform/tests/css/css-view-transitions/web-animations-api-ref.html
new file mode 100644
index 0000000000..b97396c491
--- /dev/null
+++ b/testing/web-platform/tests/css/css-view-transitions/web-animations-api-ref.html
@@ -0,0 +1,26 @@
+<!DOCTYPE html>
+<title>Shared transitions: one element captured for two tags (ref)</title>
+<link rel="help" href="https://github.com/WICG/view-transitions">
+<link rel="author" href="mailto:vmpstr@chromium.org">
+<style>
+div {
+ position: fixed;
+ top: 0;
+ left: 0;
+}
+#first {
+ background: blue;
+ width: 100px;
+ height: 100px;
+ transform: translate(100px);
+}
+#second {
+ background: green;
+ width: 100px;
+ height: 100px;
+ transform: translate(150px);
+}
+</style>
+<div id=first></div>
+<div id=second></div>
+
diff --git a/testing/web-platform/tests/css/css-view-transitions/web-animations-api.html b/testing/web-platform/tests/css/css-view-transitions/web-animations-api.html
new file mode 100644
index 0000000000..b9d62fabc6
--- /dev/null
+++ b/testing/web-platform/tests/css/css-view-transitions/web-animations-api.html
@@ -0,0 +1,53 @@
+<!DOCTYPE html>
+<html class=reftest-wait>
+<title>Shared transitions: capture opacity elements</title>
+<link rel="help" href="https://github.com/WICG/view-transitions">
+<link rel="author" href="mailto:khushalsagar@chromium.org">
+<link rel="match" href="web-animations-api-ref.html">
+<meta name="fuzzy" content="web-animations-api-ref.html:0-2;0-500">
+
+<script src="/common/reftest-wait.js"></script>
+<style>
+#first {
+ background: blue;
+ width: 100px;
+ height: 100px;
+ contain: paint;
+}
+#second {
+ background: green;
+ width: 100px;
+ height: 100px;
+ contain: paint;
+}
+
+/* Unset all animations since the test drives it using WA-API */
+html::view-transition-group(*),
+html::view-transition-image-pair(*),
+html::view-transition-new(*),
+html::view-transition-old(*) {
+ animation: unset;
+}
+</style>
+<div id=first></div>
+<div id=second></div>
+<script>
+failIfNot(document.startViewTransition, "Missing document.startViewTransition");
+
+function setAnimation() {
+ document.documentElement.animate({ transform: ['translate(100px)', 'translate(100px)'] }, { duration: 10000, pseudoElement: '::view-transition-group(first)'});
+ document.documentElement.animate({ transform: ['translate(150px)', 'translate(150px)'] }, { duration: 10000, pseudoElement: '::view-transition-group(second)'});
+ requestAnimationFrame(takeScreenshot);
+}
+
+async function runTest() {
+ first.style.viewTransitionName = "first";
+ document.startViewTransition(() => {
+ first.style.viewTransitionName = "";
+ second.style.viewTransitionName = "second";
+ requestAnimationFrame(setAnimation);
+ });
+}
+onload = () => requestAnimationFrame(() => requestAnimationFrame(runTest));
+</script>
+