mirror of
https://github.com/servo/servo.git
synced 2025-08-13 01:15:34 +01:00
Update web-platform-tests to revision b'b728032f59a396243864b0f8584e7211e3632005'
This commit is contained in:
parent
ace9b32b1c
commit
df68c4e5d1
15632 changed files with 514865 additions and 155000 deletions
|
@ -19,11 +19,21 @@ test_valid_value('animation',
|
|||
test_valid_value('animation',
|
||||
'1s linear 1s 2 reverse forwards paused anim auto',
|
||||
'1s linear 1s 2 reverse forwards paused anim');
|
||||
test_valid_value('animation',
|
||||
'1s linear 1s 2 reverse forwards paused anim scroll()');
|
||||
|
||||
test_invalid_value('animation',
|
||||
'1s linear 1s 2 reverse forwards paused anim initial');
|
||||
test_invalid_value('animation',
|
||||
'1s linear 1s 2 reverse forwards paused anim 2000');
|
||||
test_invalid_value('animation',
|
||||
'1s linear 1s 2 reverse forwards paused anim scroll(abc block)');
|
||||
test_invalid_value('animation',
|
||||
'1s linear 1s 2 reverse forwards paused anim scroll(inline abc)');
|
||||
test_invalid_value('animation',
|
||||
'1s linear 1s 2 reverse forwards paused anim scroll(abc)');
|
||||
test_invalid_value('animation',
|
||||
'1s linear 1s 2 reverse forwards paused anim scroll("string")');
|
||||
|
||||
test_computed_value('animation',
|
||||
'1s linear 1s 2 reverse forwards paused anim');
|
||||
|
|
|
@ -22,7 +22,7 @@ test_computed_value('animation-timeline', 'auto, auto');
|
|||
test_computed_value('animation-timeline', 'none, none');
|
||||
test_computed_value('animation-timeline', 'auto, none');
|
||||
test_computed_value('animation-timeline', 'none, auto');
|
||||
test_computed_value('animation-timeline', '"test"');
|
||||
test_computed_value('animation-timeline', '"test"', ["test", '"test"']);
|
||||
test_computed_value('animation-timeline', '"none"');
|
||||
test_computed_value('animation-timeline', '"auto"');
|
||||
test_computed_value('animation-timeline', '"initial"');
|
||||
|
@ -31,7 +31,7 @@ test_computed_value('animation-timeline', '"unset"');
|
|||
test_computed_value('animation-timeline', '"revert"');
|
||||
test_computed_value('animation-timeline', 'test');
|
||||
test_computed_value('animation-timeline', 'test1, test2');
|
||||
test_computed_value('animation-timeline', 'test1, "test2", none, test3, auto');
|
||||
test_computed_value('animation-timeline', 'test1, "test2", none, test3, auto', ["test1, test2, none, test3, auto", 'test1, "test2", none, test3, auto']);
|
||||
|
||||
test(() => {
|
||||
let style = getComputedStyle(document.getElementById('target'));
|
||||
|
@ -42,4 +42,19 @@ test(() => {
|
|||
let style = document.getElementById('target').style;
|
||||
assert_not_equals(style.cssText.indexOf('animation-timeline'), -1);
|
||||
}, 'The animation-timeline property shows up in CSSStyleDeclaration.cssText');
|
||||
|
||||
// https://drafts.csswg.org/scroll-animations-1/#scroll-notation
|
||||
//
|
||||
// animation-timeline: scroll(<axis>? <scroller>?);
|
||||
// <axis> = block | inline | vertical | horizontal
|
||||
// <scroller> = root | nearest
|
||||
test_computed_value('animation-timeline', 'scroll()');
|
||||
test_computed_value('animation-timeline', 'scroll(block)', 'scroll()');
|
||||
test_computed_value('animation-timeline', 'scroll(inline)');
|
||||
test_computed_value('animation-timeline', 'scroll(horizontal)');
|
||||
test_computed_value('animation-timeline', 'scroll(vertical)');
|
||||
test_computed_value('animation-timeline', 'scroll(root)');
|
||||
test_computed_value('animation-timeline', 'scroll(nearest)', 'scroll()');
|
||||
test_computed_value('animation-timeline', 'scroll(inline nearest)', 'scroll(inline)');
|
||||
test_computed_value('animation-timeline', 'scroll(vertical root)');
|
||||
</script>
|
||||
|
|
|
@ -4,39 +4,30 @@
|
|||
<script src="/resources/testharnessreport.js"></script>
|
||||
<script src="/web-animations/testcommon.js"></script>
|
||||
<style>
|
||||
#scrollers {
|
||||
main {
|
||||
overflow: hidden;
|
||||
height: 0px;
|
||||
}
|
||||
#scrollers > div {
|
||||
overflow: scroll;
|
||||
main > div {
|
||||
overflow: hidden;
|
||||
width: 100px;
|
||||
height: 100px;
|
||||
}
|
||||
#scrollers > div > div {
|
||||
main > div > div {
|
||||
height: 200px;
|
||||
}
|
||||
@keyframes expand {
|
||||
from { width: 100px; }
|
||||
to { width: 200px; }
|
||||
}
|
||||
@scroll-timeline timeline1 {
|
||||
source: selector(#scroller1);
|
||||
orientation: auto;
|
||||
start: 0px;
|
||||
end: 100px;
|
||||
#scroller1 {
|
||||
scroll-timeline: timeline1;
|
||||
}
|
||||
@scroll-timeline timeline2 {
|
||||
source: selector(#scroller2);
|
||||
orientation: auto;
|
||||
start: 0px;
|
||||
end: 100px;
|
||||
#scroller2 {
|
||||
scroll-timeline: timeline2;
|
||||
}
|
||||
@scroll-timeline timeline3 {
|
||||
source: selector(#scroller3);
|
||||
orientation: auto;
|
||||
start: 0px;
|
||||
end: 100px;
|
||||
#scroller3 {
|
||||
scroll-timeline: timeline3;
|
||||
}
|
||||
#element {
|
||||
width: 0px;
|
||||
|
@ -51,13 +42,13 @@
|
|||
#element { animation-play-state: paused; }
|
||||
}
|
||||
</style>
|
||||
<div id=scrollers>
|
||||
<main>
|
||||
<div id=scroller1><div></div></div>
|
||||
<div id=scroller2><div></div></div>
|
||||
<div id=scroller3><div></div></div>
|
||||
<div id=scroller4><div></div></div>
|
||||
</div>
|
||||
<div id=container></div>
|
||||
<div id=container></div>
|
||||
</main>
|
||||
<script>
|
||||
// Force layout of scrollers.
|
||||
scroller1.offsetTop;
|
|
@ -5,17 +5,14 @@
|
|||
<script src="/resources/testharnessreport.js"></script>
|
||||
<script src="/web-animations/testcommon.js"></script>
|
||||
<style>
|
||||
#scrollers {
|
||||
main > div {
|
||||
overflow: hidden;
|
||||
height: 0px;
|
||||
}
|
||||
#scrollers > div {
|
||||
overflow: scroll;
|
||||
width: 100px;
|
||||
height: 100px;
|
||||
}
|
||||
#scrollers > div > div {
|
||||
main > div > div {
|
||||
height: 200px;
|
||||
width: 200px;
|
||||
}
|
||||
|
||||
@keyframes top {
|
||||
|
@ -35,25 +32,17 @@
|
|||
to { right: 200px; }
|
||||
}
|
||||
|
||||
@scroll-timeline top_timeline {
|
||||
source: selector(#scroller1);
|
||||
start: 0px;
|
||||
end: 100px;
|
||||
#top_scroller {
|
||||
scroll-timeline: block top_timeline;
|
||||
}
|
||||
@scroll-timeline bottom_timeline {
|
||||
source: selector(#scroller1);
|
||||
start: 0px;
|
||||
end: 80px;
|
||||
#bottom_scroller {
|
||||
scroll-timeline: inline bottom_timeline;
|
||||
}
|
||||
@scroll-timeline left_timeline {
|
||||
source: selector(#scroller2);
|
||||
start: 0px;
|
||||
end: 100px;
|
||||
#left_scroller {
|
||||
scroll-timeline: block left_timeline;
|
||||
}
|
||||
@scroll-timeline right_timeline {
|
||||
source: selector(#scroller2);
|
||||
start: 20px;
|
||||
end: 60px;
|
||||
#right_scroller {
|
||||
scroll-timeline: inline right_timeline;
|
||||
}
|
||||
|
||||
#element {
|
||||
|
@ -67,25 +56,35 @@
|
|||
#element { animation-play-state: paused; }
|
||||
}
|
||||
</style>
|
||||
<div id=scrollers>
|
||||
<div id=scroller1><div></div></div>
|
||||
<div id=scroller2><div></div></div>
|
||||
</div>
|
||||
<div id=element></div>
|
||||
<main>
|
||||
<div id=top_scroller><div></div></div>
|
||||
<div id=bottom_scroller><div></div></div>
|
||||
<div id=left_scroller><div></div></div>
|
||||
<div id=right_scroller><div></div></div>
|
||||
<div id=element></div>
|
||||
</main>
|
||||
<script>
|
||||
// Force layout of scrollers.
|
||||
scroller1.offsetTop;
|
||||
scroller2.offsetTop;
|
||||
top_scroller.offsetTop;
|
||||
bottom_scroller.offsetTop;
|
||||
left_scroller.offsetTop;
|
||||
right_scroller.offsetTop;
|
||||
|
||||
scroller1.scrollTop = 20;
|
||||
scroller2.scrollTop = 40;
|
||||
top_scroller.scrollTop = 20;
|
||||
top_scroller.scrollLeft = 40;
|
||||
bottom_scroller.scrollTop = 20;
|
||||
bottom_scroller.scrollLeft = 40;
|
||||
left_scroller.scrollTop = 60;
|
||||
left_scroller.scrollLeft = 80;
|
||||
right_scroller.scrollTop = 60;
|
||||
right_scroller.scrollLeft = 80;
|
||||
|
||||
promise_test(async (t) => {
|
||||
await waitForNextFrame();
|
||||
assert_equals(getComputedStyle(element).top, '120px');
|
||||
assert_equals(getComputedStyle(element).bottom, '125px');
|
||||
assert_equals(getComputedStyle(element).left, '140px');
|
||||
assert_equals(getComputedStyle(element).right, '150px');
|
||||
assert_equals(getComputedStyle(element).bottom, '140px');
|
||||
assert_equals(getComputedStyle(element).left, '160px');
|
||||
assert_equals(getComputedStyle(element).right, '180px');
|
||||
}, 'animation-timeline works with multiple timelines');
|
||||
|
||||
</script>
|
||||
|
|
|
@ -0,0 +1,440 @@
|
|||
<!DOCTYPE html>
|
||||
<title>The animation-timeline: scroll-timeline-name</title>
|
||||
<meta name="viewport" content="width=device-width,initial-scale=1,minimum-scale=1">
|
||||
<link rel="help" src="https://drafts.csswg.org/scroll-animations-1/rewrite#scroll-timelines-named">
|
||||
<link rel="help" src="https://github.com/w3c/csswg-drafts/issues/6674">
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
<script src="/web-animations/testcommon.js"></script>
|
||||
<script src="support/testcommon.js"></script>
|
||||
<style>
|
||||
@keyframes anim {
|
||||
from { translate: 50px; }
|
||||
to { translate: 150px; }
|
||||
}
|
||||
#target {
|
||||
width: 100px;
|
||||
height: 100px;
|
||||
}
|
||||
.square {
|
||||
width: 100px;
|
||||
height: 100px;
|
||||
}
|
||||
.square-container {
|
||||
width: 300px;
|
||||
height: 300px;
|
||||
}
|
||||
.scroller {
|
||||
overflow: scroll;
|
||||
}
|
||||
.content {
|
||||
inline-size: 100%;
|
||||
block-size: 100%;
|
||||
padding-inline-end: 100px;
|
||||
padding-block-end: 100px;
|
||||
}
|
||||
</style>
|
||||
<body>
|
||||
<div id="log"></div>
|
||||
<script>
|
||||
"use strict";
|
||||
|
||||
function createScroller(t, scrollerSizeClass) {
|
||||
let scroller = document.createElement('div');
|
||||
let className = scrollerSizeClass || 'square';
|
||||
scroller.className = `scroller ${className}`;
|
||||
let content = document.createElement('div');
|
||||
content.className = 'content';
|
||||
|
||||
scroller.appendChild(content);
|
||||
|
||||
t.add_cleanup(function() {
|
||||
content.remove();
|
||||
scroller.remove();
|
||||
});
|
||||
|
||||
return scroller;
|
||||
}
|
||||
|
||||
function createTarget(t) {
|
||||
let target = document.createElement('div');
|
||||
target.id = 'target';
|
||||
|
||||
t.add_cleanup(function() {
|
||||
target.remove();
|
||||
});
|
||||
|
||||
return target;
|
||||
}
|
||||
|
||||
function createScrollerAndTarget(t, scrollerSizeClass) {
|
||||
return [createScroller(t, scrollerSizeClass), createTarget(t)];
|
||||
}
|
||||
|
||||
// -------------------------
|
||||
// Test scroll-timeline-name
|
||||
// -------------------------
|
||||
|
||||
promise_test(async t => {
|
||||
let target = document.createElement('div');
|
||||
target.id = 'target';
|
||||
target.className = 'scroller';
|
||||
let content = document.createElement('div');
|
||||
content.className = 'content';
|
||||
|
||||
// <div id='target' class='scroller'>
|
||||
// <div id='content'></div>
|
||||
// </div>
|
||||
document.body.appendChild(target);
|
||||
target.appendChild(content);
|
||||
|
||||
target.style.scrollTimelineName = 'timeline';
|
||||
target.style.animation = "anim 10s linear timeline";
|
||||
|
||||
target.scrollTop = 50; // 50%, in [0, 100].
|
||||
await waitForNextFrame();
|
||||
assert_equals(getComputedStyle(target).translate, '100px');
|
||||
|
||||
content.remove();
|
||||
target.remove();
|
||||
}, 'scroll-timeline-name is referenceable in animation-timeline on the ' +
|
||||
'declaring element itself');
|
||||
|
||||
promise_test(async t => {
|
||||
let [parent, target] = createScrollerAndTarget(t, 'square-container');
|
||||
|
||||
// <div id='parent' class='scroller'>
|
||||
// <div id='target'></div>
|
||||
// <div id='content'></div>
|
||||
// </div>
|
||||
document.body.appendChild(parent);
|
||||
parent.insertBefore(target, parent.firstElementChild);
|
||||
|
||||
parent.style.scrollTimelineName = 'timeline';
|
||||
target.style.animation = "anim 10s linear timeline";
|
||||
|
||||
parent.scrollTop = 100; // 50%, in [0, 200].
|
||||
await waitForNextFrame();
|
||||
assert_equals(getComputedStyle(target).translate, '100px');
|
||||
}, "scroll-timeline-name is referenceable in animation-timeline on that " +
|
||||
"element's descendants");
|
||||
|
||||
promise_test(async t => {
|
||||
let [sibling, target] = createScrollerAndTarget(t);
|
||||
|
||||
// <div id='sibling' class='scroller'> ... </div>
|
||||
// <div id='target'></div>
|
||||
document.body.appendChild(sibling);
|
||||
document.body.appendChild(target);
|
||||
|
||||
sibling.style.scrollTimelineName = 'timeline';
|
||||
target.style.animation = "anim 10s linear timeline";
|
||||
|
||||
sibling.scrollTop = 50; // 50%, in [0, 100].
|
||||
await waitForNextFrame();
|
||||
assert_equals(getComputedStyle(target).translate, '100px');
|
||||
}, "scroll-timeline-name is referenceable in animation-timeline on that " +
|
||||
"element's following siblings");
|
||||
|
||||
promise_test(async t => {
|
||||
let [sibling, target] = createScrollerAndTarget(t);
|
||||
let parent = document.createElement('div');
|
||||
|
||||
// <div id='sibling' class='scroller'> ... </div>
|
||||
// <div id='parent'>
|
||||
// <div id='target'></div>
|
||||
// </div>
|
||||
document.body.appendChild(sibling);
|
||||
document.body.appendChild(parent);
|
||||
parent.appendChild(target);
|
||||
|
||||
sibling.style.scrollTimelineName = 'timeline';
|
||||
target.style.animation = "anim 10s linear timeline";
|
||||
|
||||
sibling.scrollTop = 50; // 50%, in [0, 100].
|
||||
await waitForNextFrame();
|
||||
assert_equals(getComputedStyle(target).translate, '100px');
|
||||
|
||||
parent.remove();
|
||||
}, "scroll-timeline-name is referenceable in animation-timeline on that " +
|
||||
"element's following siblings' descendants");
|
||||
|
||||
// FIXME: We may use global scope for scroll-timeline-name.
|
||||
// See https://github.com/w3c/csswg-drafts/issues/7047
|
||||
promise_test(async t => {
|
||||
let [sibling, target] = createScrollerAndTarget(t);
|
||||
|
||||
// <div id='target'></div>
|
||||
// <div id='sibling' class='scroller'> ... </div>
|
||||
document.body.appendChild(target);
|
||||
document.body.appendChild(sibling);
|
||||
|
||||
sibling.style.scrollTimelineName = 'timeline';
|
||||
target.style.animation = "anim 10s linear timeline";
|
||||
|
||||
sibling.scrollTop = 50; // 50%, in [0, 100].
|
||||
await waitForNextFrame();
|
||||
assert_equals(getComputedStyle(target).translate, '50px',
|
||||
'Animation with unknown timeline name holds current time at zero');
|
||||
}, "scroll-timeline-name is not referenceable in animation-timeline on that " +
|
||||
"element's previous siblings");
|
||||
|
||||
promise_test(async t => {
|
||||
let [sibling, target] = createScrollerAndTarget(t);
|
||||
let parent = document.createElement('div');
|
||||
parent.className = 'scroller square-container';
|
||||
let content = document.createElement('div');
|
||||
content.className = 'content';
|
||||
|
||||
// <div id='parent' class='scroller'>
|
||||
// <div id='sibling' class='scroller'> ... </div>
|
||||
// <div id='target'></div>
|
||||
// <div id='content'></div>
|
||||
// </div>
|
||||
document.body.appendChild(parent);
|
||||
parent.appendChild(sibling);
|
||||
parent.appendChild(target);
|
||||
parent.appendChild(content);
|
||||
|
||||
parent.style.scrollTimelineName = 'timeline';
|
||||
parent.style.scrollTimelineAxis = 'inline';
|
||||
sibling.style.scrollTimelineName = 'timeline';
|
||||
target.style.animation = "anim 10s linear timeline";
|
||||
|
||||
parent.scrollTop = 50; // 25%, in [0, 200].
|
||||
sibling.scrollTop = 50; // 50%, in [0, 100].
|
||||
await waitForNextFrame();
|
||||
assert_equals(getComputedStyle(target).translate, '100px');
|
||||
|
||||
content.remove();
|
||||
parent.remove();
|
||||
}, 'scroll-timeline-name is matched based on tree order, which considers ' +
|
||||
'siblings closer than parents');
|
||||
|
||||
promise_test(async t => {
|
||||
let sibling = document.createElement('div');
|
||||
sibling.className = 'square';
|
||||
sibling.style.overflowX = 'clip'; // This makes overflow-y be clip as well.
|
||||
let target = document.createElement('div');
|
||||
target.id = 'target';
|
||||
|
||||
// <div id='sibling' style='overflow-x: clip'></div>
|
||||
// <div id='target'></div>
|
||||
document.body.appendChild(sibling);
|
||||
document.body.appendChild(target);
|
||||
|
||||
sibling.style.scrollTimelineName = 'timeline';
|
||||
target.style.animation = "anim 10s linear timeline";
|
||||
|
||||
sibling.scrollTop = 50; // 50%, in [0, 100].
|
||||
await waitForNextFrame();
|
||||
assert_equals(getComputedStyle(target).translate, 'none',
|
||||
'Animation with an unresolved current time');
|
||||
|
||||
target.remove();
|
||||
sibling.remove();
|
||||
}, 'scroll-timeline-name on an element which is not a scroll-container');
|
||||
|
||||
promise_test(async t => {
|
||||
let [sibling, target] = createScrollerAndTarget(t);
|
||||
let main = document.createElement('div');
|
||||
main.id = 'name';
|
||||
|
||||
// <div id='main'>
|
||||
// <div id='sibling' class='scroller'> ... </div>
|
||||
// <div id='target'></div>
|
||||
// </div>
|
||||
document.body.appendChild(main);
|
||||
main.appendChild(sibling);
|
||||
main.appendChild(target);
|
||||
|
||||
target.style.animation = 'anim 10s linear timeline';
|
||||
sibling.scrollTop = 50; // 50%, in [50, 150].
|
||||
await waitForNextFrame();
|
||||
|
||||
// Unknown animation-timeline, current time held at zero.
|
||||
assert_equals(getComputedStyle(target).translate, '50px');
|
||||
|
||||
// Ensure that #main (an ancestor of the scroller) needs style recalc.
|
||||
main.style.background = 'lightgray';
|
||||
sibling.style.scrollTimelineName = 'timeline';
|
||||
await waitForCSSScrollTimelineStyle();
|
||||
assert_equals(getComputedStyle(target).translate, '100px');
|
||||
|
||||
main.remove();
|
||||
}, 'scroll-timeline-name affects subsequent siblings when changed');
|
||||
|
||||
promise_test(async t => {
|
||||
let target = createTarget(t);
|
||||
|
||||
// <div id='target'></div>
|
||||
document.body.appendChild(target);
|
||||
|
||||
target.style.animation = 'anim 10s linear timeline';
|
||||
|
||||
// Unknown animation-timeline, current time held at zero.
|
||||
assert_equals(getComputedStyle(target).translate, '50px');
|
||||
|
||||
let scroller = createScroller(t);
|
||||
// <div class='scroller'> ... </div>
|
||||
// <div id='target'></div>
|
||||
document.body.insertBefore(scroller, target);
|
||||
scroller.style.scrollTimelineName = 'timeline';
|
||||
|
||||
await waitForNextFrame();
|
||||
assert_equals(getComputedStyle(target).translate, '50px');
|
||||
|
||||
// Ensure that time is not just held at zero.
|
||||
scroller.scrollTop = 50; // 50%, in [50, 150].
|
||||
await waitForNextFrame();
|
||||
assert_equals(getComputedStyle(target).translate, '100px');
|
||||
}, 'scroll-timeline-name on inserted element affects subsequent siblings');
|
||||
|
||||
promise_test(async t => {
|
||||
let [scroller, target] = createScrollerAndTarget(t);
|
||||
|
||||
// <div class='scroller'> ... </div>
|
||||
// <div id='target'></div>
|
||||
document.body.appendChild(scroller);
|
||||
document.body.appendChild(target);
|
||||
|
||||
scroller.scrollTop = 50; // 50%, in [50, 150].
|
||||
await waitForNextFrame();
|
||||
|
||||
scroller.style.scrollTimelineName = 'timeline';
|
||||
target.style.animation = 'anim 10s linear timeline';
|
||||
await waitForCSSScrollTimelineStyle();
|
||||
|
||||
assert_equals(getComputedStyle(target).translate, '100px');
|
||||
|
||||
// This effectively removes the CSS-created ScrollTimeline on this element,
|
||||
// thus invoking "setting the timeline of an animation" [1] with a null-
|
||||
// timeline on affected elements. This in turn causes the current time to
|
||||
// become unresolved [2], ultimately resulting in no effect value.
|
||||
//
|
||||
// [1] https://drafts.csswg.org/web-animations-1/#setting-the-timeline
|
||||
// [2] https://drafts.csswg.org/web-animations-1/#the-current-time-of-an-animation
|
||||
scroller.remove();
|
||||
await waitForNextFrame();
|
||||
assert_equals(getComputedStyle(target).translate, 'none');
|
||||
}, 'scroll-timeline-name on removed element affects subsequent siblings');
|
||||
|
||||
promise_test(async t => {
|
||||
let [scroller, target] = createScrollerAndTarget(t);
|
||||
|
||||
// <div class='scroller' style='display:none'> ... </div>
|
||||
// <div id='target'></div>
|
||||
scroller.style.display = 'none';
|
||||
document.body.appendChild(scroller);
|
||||
document.body.appendChild(target);
|
||||
|
||||
scroller.style.scrollTimelineName = 'timeline';
|
||||
target.style.animation = 'anim 10s linear timeline';
|
||||
|
||||
// Unknown animation-timeline, current time held at zero.
|
||||
assert_equals(getComputedStyle(target).translate, '50px');
|
||||
|
||||
scroller.style.display = 'block';
|
||||
scroller.scrollTop = 50; // 50%, in [50, 150].
|
||||
await waitForNextFrame();
|
||||
|
||||
assert_equals(getComputedStyle(target).translate, '100px');
|
||||
}, 'scroll-timeline-name on element leaving display:none affects subsequent siblings');
|
||||
|
||||
promise_test(async t => {
|
||||
let [scroller, target] = createScrollerAndTarget(t);
|
||||
|
||||
// <div class='scroller'> ... </div>
|
||||
// <div id='target'></div>
|
||||
document.body.appendChild(scroller);
|
||||
document.body.appendChild(target);
|
||||
|
||||
scroller.scrollTop = 50; // 50%, in [50, 150].
|
||||
await waitForNextFrame();
|
||||
|
||||
scroller.style.scrollTimelineName = 'timeline';
|
||||
target.style.animation = 'anim 10s linear timeline';
|
||||
await waitForCSSScrollTimelineStyle();
|
||||
|
||||
assert_equals(getComputedStyle(target).translate, '100px');
|
||||
|
||||
// See comment in the test "scroll-timeline-name on removed element ..." for
|
||||
// an explantation of this result. (Setting display:none is similar to
|
||||
// removing the element).
|
||||
scroller.style.display = 'none';
|
||||
await waitForNextFrame();
|
||||
assert_equals(getComputedStyle(target).translate, 'none');
|
||||
}, 'scroll-timeline-name on element becoming display:none affects subsequent siblings');
|
||||
|
||||
// TODO: Add more tests which change scroll-timeline-name property.
|
||||
// Those animations which use this timeline should be restyled propertly.
|
||||
|
||||
// -------------------------
|
||||
// Test scroll-timeline-axis
|
||||
// -------------------------
|
||||
|
||||
promise_test(async t => {
|
||||
let [scroller, target] = createScrollerAndTarget(t);
|
||||
scroller.style.writingMode = 'vertical-lr';
|
||||
|
||||
document.body.appendChild(scroller);
|
||||
document.body.appendChild(target);
|
||||
|
||||
scroller.style.scrollTimeline = 'timeline block';
|
||||
target.style.animation = "anim 10s linear timeline";
|
||||
|
||||
scroller.scrollLeft = 50;
|
||||
await waitForNextFrame();
|
||||
assert_equals(getComputedStyle(target).translate, '100px');
|
||||
}, 'scroll-timeline-axis is block');
|
||||
|
||||
promise_test(async t => {
|
||||
let [scroller, target] = createScrollerAndTarget(t);
|
||||
scroller.style.writingMode = 'vertical-lr';
|
||||
|
||||
document.body.appendChild(scroller);
|
||||
document.body.appendChild(target);
|
||||
|
||||
scroller.style.scrollTimeline = 'timeline inline';
|
||||
target.style.animation = "anim 10s linear timeline";
|
||||
|
||||
scroller.scrollTop = 50;
|
||||
await waitForNextFrame();
|
||||
assert_equals(getComputedStyle(target).translate, '100px');
|
||||
}, 'scroll-timeline-axis is inline');
|
||||
|
||||
promise_test(async t => {
|
||||
let [scroller, target] = createScrollerAndTarget(t);
|
||||
scroller.style.writingMode = 'vertical-lr';
|
||||
|
||||
document.body.appendChild(scroller);
|
||||
document.body.appendChild(target);
|
||||
|
||||
scroller.style.scrollTimeline = 'timeline horizontal';
|
||||
target.style.animation = "anim 10s linear timeline";
|
||||
|
||||
scroller.scrollLeft = 50;
|
||||
await waitForNextFrame();
|
||||
assert_equals(getComputedStyle(target).translate, '100px');
|
||||
}, 'scroll-timeline-axis is horizontal');
|
||||
|
||||
promise_test(async t => {
|
||||
let [scroller, target] = createScrollerAndTarget(t);
|
||||
scroller.style.writingMode = 'vertical-lr';
|
||||
|
||||
document.body.appendChild(scroller);
|
||||
document.body.appendChild(target);
|
||||
|
||||
scroller.style.scrollTimeline = 'timeline vertical';
|
||||
target.style.animation = "anim 10s linear timeline";
|
||||
|
||||
scroller.scrollTop = 50;
|
||||
await waitForNextFrame();
|
||||
assert_equals(getComputedStyle(target).translate, '100px');
|
||||
}, 'scroll-timeline-axis is vertical');
|
||||
|
||||
// TODO: Add more tests which change scroll-timeline-axis property.
|
||||
// Those animations which use this timeline should be restyled properly.
|
||||
|
||||
</script>
|
||||
</body>
|
|
@ -16,7 +16,7 @@ test_valid_value('animation-timeline', 'auto, auto');
|
|||
test_valid_value('animation-timeline', 'none, none');
|
||||
test_valid_value('animation-timeline', 'auto, none');
|
||||
test_valid_value('animation-timeline', 'none, auto');
|
||||
test_valid_value('animation-timeline', '"test"');
|
||||
test_valid_value('animation-timeline', '"test"', ["test", '"test"']);
|
||||
test_valid_value('animation-timeline', '"none"');
|
||||
test_valid_value('animation-timeline', '"auto"');
|
||||
test_valid_value('animation-timeline', '"initial"');
|
||||
|
@ -25,7 +25,7 @@ test_valid_value('animation-timeline', '"unset"');
|
|||
test_valid_value('animation-timeline', '"revert"');
|
||||
test_valid_value('animation-timeline', 'test');
|
||||
test_valid_value('animation-timeline', 'test1, test2');
|
||||
test_valid_value('animation-timeline', 'test1, "test2", none, test3, auto');
|
||||
test_valid_value('animation-timeline', 'test1, "test2", none, test3, auto', ["test1, test2, none, test3, auto", 'test1, "test2", none, test3, auto']);
|
||||
|
||||
test_invalid_value('animation-timeline', '10px');
|
||||
test_invalid_value('animation-timeline', 'auto auto');
|
||||
|
@ -34,4 +34,25 @@ test_invalid_value('animation-timeline', 'foo bar');
|
|||
test_invalid_value('animation-timeline', '"foo" "bar"');
|
||||
test_invalid_value('animation-timeline', 'rgb(1, 2, 3)');
|
||||
test_invalid_value('animation-timeline', '#fefefe');
|
||||
|
||||
// https://drafts.csswg.org/scroll-animations-1/#scroll-notation
|
||||
//
|
||||
// animation-timeline: scroll(<axis>? <scroller>?);
|
||||
// <axis> = block | inline | vertical | horizontal
|
||||
// <scroller> = root | nearest
|
||||
test_valid_value('animation-timeline', 'scroll()');
|
||||
test_valid_value('animation-timeline', 'scroll(block)', 'scroll()');
|
||||
test_valid_value('animation-timeline', 'scroll(inline)');
|
||||
test_valid_value('animation-timeline', 'scroll(horizontal)');
|
||||
test_valid_value('animation-timeline', 'scroll(vertical)');
|
||||
test_valid_value('animation-timeline', 'scroll(root)');
|
||||
test_valid_value('animation-timeline', 'scroll(nearest)', 'scroll()');
|
||||
test_valid_value('animation-timeline', 'scroll(inline nearest)', 'scroll(inline)');
|
||||
test_valid_value('animation-timeline', 'scroll(vertical root)');
|
||||
|
||||
test_invalid_value('animation-timeline', 'scroll(root block)');
|
||||
test_invalid_value('animation-timeline', 'scroll(abc root)');
|
||||
test_invalid_value('animation-timeline', 'scroll(abc)');
|
||||
test_invalid_value('animation-timeline', 'scroll(vertical abc)');
|
||||
test_invalid_value('animation-timeline', 'scroll("string")');
|
||||
</script>
|
||||
|
|
|
@ -0,0 +1,140 @@
|
|||
<!DOCTYPE html>
|
||||
<title>The animation-timeline: scroll() notation</title>
|
||||
<meta name="viewport" content="width=device-width,initial-scale=1,minimum-scale=1">
|
||||
<link rel="help" src="https://drafts.csswg.org/scroll-animations-1/rewrite#scroll-notation">
|
||||
<link rel="help" src="https://github.com/w3c/csswg-drafts/issues/6674">
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
<script src="/web-animations/testcommon.js"></script>
|
||||
<style>
|
||||
@keyframes anim {
|
||||
from { translate: 50px; }
|
||||
to { translate: 150px; }
|
||||
}
|
||||
html {
|
||||
min-height: 100vh;
|
||||
/* This makes the max scrollable ragne be 100px in root element */
|
||||
padding-bottom: 100px;
|
||||
}
|
||||
#container {
|
||||
width: 300px;
|
||||
height: 300px;
|
||||
overflow: scroll;
|
||||
}
|
||||
#target {
|
||||
width: 100px;
|
||||
/* This makes the max scrollable ragne be 100px in the block direction */
|
||||
height: 100px;
|
||||
}
|
||||
/* large block content */
|
||||
.block-content {
|
||||
block-size: 100%;
|
||||
}
|
||||
/* large inline content */
|
||||
.inline-content {
|
||||
inline-size: 100%;
|
||||
block-size: 5px;
|
||||
/* This makes the max scrollable ragne be 100px in the inline direction */
|
||||
padding-inline-end: 100px;
|
||||
}
|
||||
</style>
|
||||
<body>
|
||||
<div id="log"></div>
|
||||
<script>
|
||||
"use strict";
|
||||
|
||||
const root = document.scrollingElement;
|
||||
const createTargetWithStuff = function(t, contentClass) {
|
||||
let container = document.createElement('div');
|
||||
container.id = 'container';
|
||||
let target = document.createElement('div');
|
||||
target.id = 'target';
|
||||
let content = document.createElement('div');
|
||||
content.className = contentClass;
|
||||
|
||||
// <div id='container'>
|
||||
// <div id='target'></div>
|
||||
// <div class=contentClass></div>
|
||||
// </div>
|
||||
document.body.appendChild(container);
|
||||
container.appendChild(target);
|
||||
container.appendChild(content);
|
||||
|
||||
if (t && typeof t.add_cleanup === 'function') {
|
||||
t.add_cleanup(() => {
|
||||
content.remove();
|
||||
target.remove();
|
||||
container.remove();
|
||||
});
|
||||
}
|
||||
|
||||
return [container, target];
|
||||
};
|
||||
|
||||
async function scrollLeft(element, value) {
|
||||
element.scrollLeft = value;
|
||||
await waitForNextFrame();
|
||||
}
|
||||
|
||||
async function scrollTop(element, value) {
|
||||
element.scrollTop = value;
|
||||
await waitForNextFrame();
|
||||
}
|
||||
|
||||
promise_test(async t => {
|
||||
let [container, div] = createTargetWithStuff(t, 'block-content');
|
||||
div.style.animation = "anim 10s linear scroll(nearest)";
|
||||
|
||||
await scrollTop(root, 50);
|
||||
assert_equals(getComputedStyle(div).translate, '50px');
|
||||
|
||||
await scrollTop(container, 50);
|
||||
assert_equals(getComputedStyle(div).translate, '100px');
|
||||
|
||||
await scrollTop(root, 0);
|
||||
}, 'animation-timeline: scroll(nearest)');
|
||||
|
||||
promise_test(async t => {
|
||||
let [container, div] = createTargetWithStuff(t, 'block-content');
|
||||
div.style.animation = "anim 10s linear scroll(root)";
|
||||
|
||||
await scrollTop(container, 50);
|
||||
assert_equals(getComputedStyle(div).translate, '50px');
|
||||
|
||||
await scrollTop(root, 50);
|
||||
assert_equals(getComputedStyle(div).translate, '100px');
|
||||
|
||||
await scrollTop(root, 0);
|
||||
}, 'animation-timeline: scroll(root)');
|
||||
|
||||
promise_test(async t => {
|
||||
let [container, div] = createTargetWithStuff(t, 'inline-content');
|
||||
div.style.animation = "anim 10s linear scroll(inline)";
|
||||
|
||||
await scrollLeft(container, 50);
|
||||
assert_equals(getComputedStyle(div).translate, '100px');
|
||||
}, 'animation-timeline: scroll(inline)');
|
||||
|
||||
promise_test(async t => {
|
||||
let [container, div] = createTargetWithStuff(t, 'block-content');
|
||||
container.style.writingMode = 'vertical-lr';
|
||||
div.style.animation = "anim 10s linear scroll(horizontal)";
|
||||
|
||||
await scrollLeft(container, 50);
|
||||
assert_equals(getComputedStyle(div).translate, '100px');
|
||||
}, 'animation-timeline: scroll(horizontal)');
|
||||
|
||||
promise_test(async t => {
|
||||
let [container, div] = createTargetWithStuff(t, 'inline-content');
|
||||
container.style.writingMode = 'vertical-lr';
|
||||
div.style.animation = "anim 10s linear scroll(vertical)";
|
||||
|
||||
await scrollTop(container, 50);
|
||||
assert_equals(getComputedStyle(div).translate, '100px');
|
||||
}, 'animation-timeline: scroll(vertical)');
|
||||
|
||||
// TODO: Add more tests which change the overflow property of the container for
|
||||
// scroll(nearest)
|
||||
|
||||
</script>
|
||||
</body>
|
|
@ -1,61 +0,0 @@
|
|||
<!DOCTYPE html>
|
||||
<link rel="help" src="https://drafts.csswg.org/scroll-animations-1/#scroll-timeline-at-rule">
|
||||
<link rel="help" src="https://drafts.csswg.org/scroll-animations-1/#phase-algorithm">
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
<script src="/web-animations/testcommon.js"></script>
|
||||
<style>
|
||||
#scroller {
|
||||
overflow: scroll;
|
||||
width: 100px;
|
||||
height: 100px;
|
||||
}
|
||||
#contents {
|
||||
height: 200px;
|
||||
}
|
||||
@keyframes expand {
|
||||
from { width: 100px; }
|
||||
to { width: 200px; }
|
||||
}
|
||||
#element {
|
||||
width: 0px;
|
||||
}
|
||||
/* Ensure stable expectations if feature is not supported */
|
||||
@supports not (animation-timeline:foo) {
|
||||
#element { animation-play-state: paused; }
|
||||
}
|
||||
</style>
|
||||
<div id=scroller>
|
||||
<div id=contents></div>
|
||||
</div>
|
||||
<div id=container></div>
|
||||
<script>
|
||||
promise_test(async (t) => {
|
||||
try {
|
||||
// Make sure scroller has a layout box.
|
||||
await waitForNextFrame();
|
||||
|
||||
container.innerHTML = `
|
||||
<div id=element></div>
|
||||
<style>
|
||||
@scroll-timeline timeline {
|
||||
source: selector(#scroller);
|
||||
start: 50px;
|
||||
end: 100px;
|
||||
}
|
||||
#element {
|
||||
animation: expand 10s linear;
|
||||
animation-timeline: timeline;
|
||||
}
|
||||
</style>
|
||||
`;
|
||||
// Animation should not apply in before phase.
|
||||
assert_equals(getComputedStyle(element).width, '0px');
|
||||
await waitForNextFrame();
|
||||
// Animation should still not apply.
|
||||
assert_equals(getComputedStyle(element).width, '0px');
|
||||
} finally {
|
||||
container.innerHTML = '';
|
||||
}
|
||||
}, 'Animation does not apply when timeline phase is before');
|
||||
</script>
|
|
@ -1,48 +0,0 @@
|
|||
<!DOCTYPE html>
|
||||
<link rel="help" src="https://drafts.csswg.org/scroll-animations-1/#scroll-timeline-at-rule">
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
<script src="/web-animations/testcommon.js"></script>
|
||||
<style>
|
||||
#scroller {
|
||||
overflow: scroll;
|
||||
width: 100px;
|
||||
height: 100px;
|
||||
}
|
||||
#contents {
|
||||
height: 200px;
|
||||
}
|
||||
@keyframes expand {
|
||||
from { width: 100px; }
|
||||
to { width: 200px; }
|
||||
}
|
||||
@scroll-timeline timeline {
|
||||
source: selector(#scroller);
|
||||
start: 0px;
|
||||
end: 100px;
|
||||
}
|
||||
@scroll-timeline timeline {
|
||||
source: selector(#scroller);
|
||||
start: 0px;
|
||||
end: 50px;
|
||||
}
|
||||
#element {
|
||||
animation: expand 10s linear;
|
||||
animation-timeline: timeline;
|
||||
}
|
||||
/* Ensure stable expectations if feature is not supported */
|
||||
@supports not (animation-timeline:foo) {
|
||||
#element { animation-play-state: paused; }
|
||||
}
|
||||
</style>
|
||||
<div id=scroller>
|
||||
<div id=contents></div>
|
||||
</div>
|
||||
<div id=element></div>
|
||||
<script>
|
||||
promise_test(async (t) => {
|
||||
scroller.scrollTop = 25;
|
||||
await waitForNextFrame();
|
||||
assert_equals(getComputedStyle(element).width, '150px');
|
||||
}, 'Latest @scroll-timeline rule wins');
|
||||
</script>
|
|
@ -1,60 +0,0 @@
|
|||
<html class="reftest-wait">
|
||||
<title>The default scroll-timeline at rule in quirks mode</title>
|
||||
<link rel="help" href="https://drafts.csswg.org/scroll-animations-1/#scroll-timeline-at-rule">
|
||||
<link rel="help" href="https://drafts.csswg.org/css-animations-2/#animation-timeline">
|
||||
<meta name="assert" content="CSS animation correctly updates values when using the default scroll-timeline at rule">
|
||||
<link rel="match" href="at-scroll-timeline-default-descriptors-ref.html">
|
||||
|
||||
<style>
|
||||
@keyframes update {
|
||||
from { transform: translateY(0px); }
|
||||
to { transform: translateY(200px); }
|
||||
}
|
||||
|
||||
@scroll-timeline test-timeline {
|
||||
source: auto;
|
||||
orientation: auto;
|
||||
scroll-offsets: none;
|
||||
}
|
||||
|
||||
html {
|
||||
min-height: 100%;
|
||||
padding-bottom: 100px;
|
||||
}
|
||||
|
||||
#box {
|
||||
width: 100px;
|
||||
height: 100px;
|
||||
background-color: green;
|
||||
animation: update 1s linear;
|
||||
animation-timeline: test-timeline;
|
||||
}
|
||||
|
||||
#covered {
|
||||
width: 100px;
|
||||
height: 100px;
|
||||
background-color: red;
|
||||
}
|
||||
|
||||
* {
|
||||
margin-top: 0px;
|
||||
margin-bottom: 0px;
|
||||
}
|
||||
</style>
|
||||
|
||||
<div id="box"></div>
|
||||
<div id="covered"></div>
|
||||
|
||||
<script>
|
||||
window.addEventListener('load', function() {
|
||||
const scroller = document.scrollingElement;
|
||||
|
||||
// Move the scroller to the halfway point.
|
||||
const maxScroll = scroller.scrollHeight - scroller.clientHeight;
|
||||
scroller.scrollTop = 0.5 * maxScroll;
|
||||
|
||||
window.requestAnimationFrame(() => {
|
||||
document.documentElement.classList.remove("reftest-wait");
|
||||
});
|
||||
});
|
||||
</script>
|
|
@ -1,247 +0,0 @@
|
|||
<!DOCTYPE html>
|
||||
<title>@scroll-timeline: Element-based offsets</title>
|
||||
<link rel="help" src="https://drafts.csswg.org/scroll-animations-1/#scroll-timeline-at-rule">
|
||||
<link rel="help" src="https://drafts.csswg.org/scroll-animations-1/#element-based-offset-section">
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
<script src="/web-animations/testcommon.js"></script>
|
||||
<style>
|
||||
#scroller {
|
||||
overflow: scroll;
|
||||
width: 100px;
|
||||
height: 100px;
|
||||
}
|
||||
.filler {
|
||||
height: 150px;
|
||||
background-color: darkgray;
|
||||
}
|
||||
.offset {
|
||||
height: 50px;
|
||||
background-color: green;
|
||||
}
|
||||
@keyframes expand {
|
||||
from { width: 100px; }
|
||||
to { width: 200px; }
|
||||
}
|
||||
@scroll-timeline timeline_start_start {
|
||||
source: selector(#scroller);
|
||||
start: selector(#offset1);
|
||||
end: selector(#offset2);
|
||||
}
|
||||
@scroll-timeline timeline_end_end {
|
||||
source: selector(#scroller);
|
||||
start: selector(#offset1) end;
|
||||
end: selector(#offset2) end;
|
||||
}
|
||||
@scroll-timeline timeline_end_start {
|
||||
source: selector(#scroller);
|
||||
start: selector(#offset1) end;
|
||||
end: selector(#offset2) start;
|
||||
}
|
||||
@scroll-timeline timeline_end_1_end {
|
||||
source: selector(#scroller);
|
||||
start: selector(#offset1) end 1;
|
||||
end: selector(#offset2) end;
|
||||
}
|
||||
@scroll-timeline timeline_end_start_05 {
|
||||
source: selector(#scroller);
|
||||
start: selector(#offset1) end;
|
||||
end: selector(#offset2) 0.5;
|
||||
}
|
||||
@scroll-timeline timeline_start_400px {
|
||||
source: selector(#scroller);
|
||||
start: selector(#offset1);
|
||||
end: 400px;
|
||||
}
|
||||
@scroll-timeline timeline_50px_end {
|
||||
source: selector(#scroller);
|
||||
start: 50px;
|
||||
end: selector(#offset2) end;
|
||||
}
|
||||
@scroll-timeline timeline_outside {
|
||||
source: selector(#scroller);
|
||||
start: selector(#offset_outside);
|
||||
end: auto;
|
||||
}
|
||||
@scroll-timeline timeline_display_none {
|
||||
source: selector(#scroller);
|
||||
start: selector(#offset_display_none);
|
||||
end: auto;
|
||||
}
|
||||
@scroll-timeline timeline_null_target {
|
||||
source: selector(#scroller);
|
||||
start: selector(#no_such_id);
|
||||
end: selector(#no_such_id);
|
||||
}
|
||||
|
||||
#container > div {
|
||||
width: 0px;
|
||||
animation-name: expand;
|
||||
animation-duration: 10s;
|
||||
animation-timing-function: linear;
|
||||
}
|
||||
/* Ensure stable expectations if feature is not supported */
|
||||
@supports not (animation-timeline:foo) {
|
||||
#container > div { animation-play-state: paused; }
|
||||
}
|
||||
#element_start_start { animation-timeline: timeline_start_start; }
|
||||
#element_end_end { animation-timeline: timeline_end_end; }
|
||||
#element_end_start { animation-timeline: timeline_end_start; }
|
||||
#element_end_1_end { animation-timeline: timeline_end_1_end; }
|
||||
#element_end_start_05 { animation-timeline: timeline_end_start_05; }
|
||||
#element_start_400px { animation-timeline: timeline_start_400px; }
|
||||
#element_50px_end { animation-timeline: timeline_50px_end; }
|
||||
#element_outside { animation-timeline: timeline_outside; }
|
||||
#element_display_none { animation-timeline: timeline_display_none; }
|
||||
#element_null_target { animation-timeline: timeline_null_target; }
|
||||
</style>
|
||||
<div id=scroller>
|
||||
<div id=contents>
|
||||
<div class=filler></div>
|
||||
<div class=offset id=offset1></div>
|
||||
<div class=filler></div>
|
||||
<div class=offset id=offset2></div>
|
||||
<div class=filler></div>
|
||||
</div>
|
||||
</div>
|
||||
<div id=offset_outside></div>
|
||||
<div id=offset_display_none style="display:none"></div>
|
||||
<div id=container>
|
||||
<div id=element_start_start></div>
|
||||
<div id=element_end_end></div>
|
||||
<div id=element_end_start></div>
|
||||
<div id=element_end_1_end></div>
|
||||
<div id=element_end_start_05></div>
|
||||
<div id=element_start_400px></div>
|
||||
<div id=element_50px_end></div>
|
||||
<div id=element_outside></div>
|
||||
<div id=element_display_none></div>
|
||||
<div id=element_null_target></div>
|
||||
</div>
|
||||
<script>
|
||||
|
||||
// The contents of the scroller looks approximately like this:
|
||||
//
|
||||
// +-------+
|
||||
// | |
|
||||
// | 150px | filler
|
||||
// | |
|
||||
// +-------+
|
||||
// +-------+
|
||||
// | 50px | #offset1
|
||||
// +-------+
|
||||
// +-------+
|
||||
// | |
|
||||
// | 150px | filler
|
||||
// | |
|
||||
// +-------+
|
||||
// +-------+
|
||||
// | 50px | #offset2
|
||||
// +-------+
|
||||
// +-------+
|
||||
// | |
|
||||
// | 150px | filler
|
||||
// | |
|
||||
// +-------+
|
||||
//
|
||||
// The height of the scrollport is 100px.
|
||||
|
||||
// Scrolls top to 'offset', waits for a frame, then call the provided
|
||||
// assertions function.
|
||||
function test_scroll(element, offset, assertions, description) {
|
||||
promise_test(async (t) => {
|
||||
scroller.scrollTop = offset;
|
||||
await waitForNextFrame();
|
||||
assertions();
|
||||
}, `${description} [${element.id}]`);
|
||||
}
|
||||
|
||||
// Tests that the computed value of 'width' on element is the expected value
|
||||
// after scrolling top to the specifed offset.
|
||||
function test_width_at_scroll_top(element, offset, expected) {
|
||||
test_scroll(element, offset, () => {
|
||||
assert_equals(getComputedStyle(element).width, expected);
|
||||
}, `Scroll at offset ${offset} updates animation correctly`);
|
||||
}
|
||||
|
||||
// [200, 400]
|
||||
test_width_at_scroll_top(element_start_start, 0, '0px');
|
||||
test_width_at_scroll_top(element_start_start, 199, '0px');
|
||||
test_width_at_scroll_top(element_start_start, 200, '100px');
|
||||
test_width_at_scroll_top(element_start_start, 300, '150px');
|
||||
test_width_at_scroll_top(element_start_start, 398, '199px');
|
||||
test_width_at_scroll_top(element_start_start, 400, '0px');
|
||||
|
||||
// [50, 250]
|
||||
test_width_at_scroll_top(element_end_end, 0, '0px');
|
||||
test_width_at_scroll_top(element_end_end, 49, '0px');
|
||||
test_width_at_scroll_top(element_end_end, 50, '100px');
|
||||
test_width_at_scroll_top(element_end_end, 150, '150px');
|
||||
test_width_at_scroll_top(element_end_end, 248, '199px');
|
||||
test_width_at_scroll_top(element_end_end, 250, '0px');
|
||||
|
||||
// [50, 400]
|
||||
test_width_at_scroll_top(element_end_start, 0, '0px');
|
||||
test_width_at_scroll_top(element_end_start, 49, '0px');
|
||||
test_width_at_scroll_top(element_end_start, 50, '100px');
|
||||
test_width_at_scroll_top(element_end_start, 225, '150px');
|
||||
test_width_at_scroll_top(element_end_start, 393, '198px');
|
||||
test_width_at_scroll_top(element_end_start, 400, '0px');
|
||||
|
||||
// [100, 250]
|
||||
test_width_at_scroll_top(element_end_1_end, 0, '0px');
|
||||
test_width_at_scroll_top(element_end_1_end, 99, '0px');
|
||||
test_width_at_scroll_top(element_end_1_end, 100, '100px');
|
||||
test_width_at_scroll_top(element_end_1_end, 175, '150px');
|
||||
test_width_at_scroll_top(element_end_1_end, 247, '198px');
|
||||
test_width_at_scroll_top(element_end_1_end, 250, '0px');
|
||||
|
||||
// [50, 375]
|
||||
test_width_at_scroll_top(element_end_start_05, 0, '0px');
|
||||
test_width_at_scroll_top(element_end_start_05, 49, '0px');
|
||||
test_width_at_scroll_top(element_end_start_05, 50, '100px');
|
||||
test_width_at_scroll_top(element_end_start_05, 206, '148px');
|
||||
test_width_at_scroll_top(element_end_start_05, 362, '196px');
|
||||
test_width_at_scroll_top(element_end_start_05, 375, '0px');
|
||||
|
||||
// [200, 300]
|
||||
test_width_at_scroll_top(element_start_400px, 0, '0px');
|
||||
test_width_at_scroll_top(element_start_400px, 199, '0px');
|
||||
test_width_at_scroll_top(element_start_400px, 200, '100px');
|
||||
test_width_at_scroll_top(element_start_400px, 300, '150px');
|
||||
test_width_at_scroll_top(element_start_400px, 398, '199px');
|
||||
test_width_at_scroll_top(element_start_400px, 400, '0px');
|
||||
|
||||
// [50, 250]
|
||||
test_width_at_scroll_top(element_50px_end, 0, '0px');
|
||||
test_width_at_scroll_top(element_50px_end, 49, '0px');
|
||||
test_width_at_scroll_top(element_50px_end, 50, '100px');
|
||||
test_width_at_scroll_top(element_50px_end, 150, '150px');
|
||||
test_width_at_scroll_top(element_50px_end, 248, '199px');
|
||||
test_width_at_scroll_top(element_50px_end, 250, '0px');
|
||||
|
||||
// Offset not a decendant of scroller (=> no effect value)
|
||||
test_width_at_scroll_top(element_outside, 0, '0px');
|
||||
test_width_at_scroll_top(element_outside, 100, '0px');
|
||||
test_width_at_scroll_top(element_outside, 200, '0px');
|
||||
test_width_at_scroll_top(element_outside, 300, '0px');
|
||||
test_width_at_scroll_top(element_outside, 400, '0px');
|
||||
test_width_at_scroll_top(element_outside, 450, '0px');
|
||||
|
||||
// Target of element-based offset has no layout box (=> no effect value)
|
||||
test_width_at_scroll_top(element_display_none, 0, '0px');
|
||||
test_width_at_scroll_top(element_display_none, 100, '0px');
|
||||
test_width_at_scroll_top(element_display_none, 200, '0px');
|
||||
test_width_at_scroll_top(element_display_none, 300, '0px');
|
||||
test_width_at_scroll_top(element_display_none, 400, '0px');
|
||||
test_width_at_scroll_top(element_display_none, 450, '0px');
|
||||
|
||||
// Target of element-based offset is null (=> no effect value)
|
||||
test_width_at_scroll_top(element_null_target, 0, '0px');
|
||||
test_width_at_scroll_top(element_null_target, 100, '0px');
|
||||
test_width_at_scroll_top(element_null_target, 200, '0px');
|
||||
test_width_at_scroll_top(element_null_target, 300, '0px');
|
||||
test_width_at_scroll_top(element_null_target, 400, '0px');
|
||||
test_width_at_scroll_top(element_null_target, 450, '0px');
|
||||
|
||||
</script>
|
|
@ -1,207 +0,0 @@
|
|||
<!DOCTYPE html>
|
||||
<title>@scroll-timeline element offset invalidation</title>
|
||||
<link rel="help" src="https://drafts.csswg.org/scroll-animations-1/#typedef-element-offset">
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
<script src="/web-animations/testcommon.js"></script>
|
||||
<style>
|
||||
#scroller {
|
||||
overflow: scroll;
|
||||
width: 100px;
|
||||
height: 100px;
|
||||
}
|
||||
#scroller > div {
|
||||
height: 50px;
|
||||
}
|
||||
@keyframes expand {
|
||||
from { width: 100px; }
|
||||
to { width: 200px; }
|
||||
}
|
||||
@scroll-timeline timeline {
|
||||
source: selector(#scroller);
|
||||
start: selector(#offset1) end;
|
||||
end: selector(#offset2) end;
|
||||
}
|
||||
#element {
|
||||
width: 0px;
|
||||
height: 20px;
|
||||
animation: expand 1000s linear;
|
||||
animation-timeline: timeline;
|
||||
}
|
||||
/* Ensure stable expectations if feature is not supported */
|
||||
@supports not (animation-timeline:foo) {
|
||||
#element { animation-play-state: paused; }
|
||||
}
|
||||
</style>
|
||||
<div id=scroller></div>
|
||||
<div id=element></div>
|
||||
<p class=sibling1></p>
|
||||
<p class=sibling2></p>
|
||||
<script>
|
||||
|
||||
function setup() {
|
||||
while (scroller.firstChild)
|
||||
scroller.firstChild.remove();
|
||||
for (let i = 0; i < 10; i++)
|
||||
scroller.append(document.createElement('div'));
|
||||
}
|
||||
|
||||
// The contents of the scroller look like this:
|
||||
//
|
||||
// +-------+
|
||||
// | 50px | div (0)
|
||||
// +-------+
|
||||
// +-------+
|
||||
// | 50px | div (1)
|
||||
// +-------+
|
||||
// +-------+
|
||||
// | 50px | div (2)
|
||||
// +-------+
|
||||
// +-------+
|
||||
// | 50px | div (3)
|
||||
// +-------+
|
||||
// +-------+
|
||||
// | 50px | div (4)
|
||||
// +-------+
|
||||
// +-------+
|
||||
// | 50px | div (5)
|
||||
// +-------+
|
||||
// +-------+
|
||||
// | 50px | div (6)
|
||||
// +-------+
|
||||
// +-------+
|
||||
// | 50px | div (7)
|
||||
// +-------+
|
||||
// +-------+
|
||||
// | 50px | div (8)
|
||||
// +-------+
|
||||
// +-------+
|
||||
// | 50px | div (9)
|
||||
// +-------+
|
||||
//
|
||||
// The height of the scrollport is 100px.
|
||||
|
||||
function invalidation_test(func, description) {
|
||||
promise_test(async (t) => {
|
||||
setup();
|
||||
await func();
|
||||
}, description);
|
||||
}
|
||||
|
||||
function remove(id) {
|
||||
let old_element = document.getElementById(id);
|
||||
if (old_element)
|
||||
old_element.removeAttribute('id');
|
||||
}
|
||||
|
||||
function reassign(id, element) {
|
||||
remove(id);
|
||||
element.setAttribute('id', id);
|
||||
}
|
||||
|
||||
async function assert_element_width_at_scroll(expected_width, scroll) {
|
||||
scroller.scrollTop = scroll;
|
||||
await waitForNextFrame();
|
||||
assert_equals(getComputedStyle(element).width, expected_width);
|
||||
}
|
||||
|
||||
invalidation_test(async () => {
|
||||
await assert_element_width_at_scroll('0px', 0);
|
||||
}, 'Offsets missing');
|
||||
|
||||
invalidation_test(async () => {
|
||||
// [50, 150]
|
||||
reassign('offset1', scroller.children[3]);
|
||||
reassign('offset2', scroller.children[5]);
|
||||
await assert_element_width_at_scroll('150px', 100);
|
||||
|
||||
// [100, 150]
|
||||
reassign('offset1', scroller.children[4]);
|
||||
await assert_element_width_at_scroll('100px', 100);
|
||||
}, 'Change first offset');
|
||||
|
||||
invalidation_test(async () => {
|
||||
// [50, 150]
|
||||
reassign('offset1', scroller.children[3]);
|
||||
reassign('offset2', scroller.children[5]);
|
||||
await assert_element_width_at_scroll('150px', 100);
|
||||
|
||||
// [50, 250]
|
||||
reassign('offset2', scroller.children[7]);
|
||||
await assert_element_width_at_scroll('125px', 100);
|
||||
}, 'Change second offset');
|
||||
|
||||
invalidation_test(async () => {
|
||||
// [50, 250]
|
||||
reassign('offset1', scroller.children[3]);
|
||||
reassign('offset2', scroller.children[7]);
|
||||
await assert_element_width_at_scroll('125px', 100);
|
||||
|
||||
// [0, 200]
|
||||
reassign('offset1', scroller.children[2]);
|
||||
reassign('offset2', scroller.children[4]);
|
||||
await assert_element_width_at_scroll('150px', 50);
|
||||
}, 'Change both offsets');
|
||||
|
||||
invalidation_test(async () => {
|
||||
// [50, 150]
|
||||
reassign('offset1', scroller.children[3]);
|
||||
reassign('offset2', scroller.children[5]);
|
||||
await assert_element_width_at_scroll('150px', 100);
|
||||
|
||||
remove('offset1');
|
||||
await assert_element_width_at_scroll('0px', 0);
|
||||
}, 'Remove first offset');
|
||||
|
||||
invalidation_test(async () => {
|
||||
// [50, 150]
|
||||
reassign('offset1', scroller.children[3]);
|
||||
reassign('offset2', scroller.children[5]);
|
||||
await assert_element_width_at_scroll('150px', 100);
|
||||
|
||||
remove('offset2');
|
||||
await assert_element_width_at_scroll('0px', 0);
|
||||
}, 'Remove second offset');
|
||||
|
||||
invalidation_test(async () => {
|
||||
// [50, 150]
|
||||
reassign('offset1', scroller.children[3]);
|
||||
reassign('offset2', scroller.children[5]);
|
||||
await assert_element_width_at_scroll('150px', 100);
|
||||
|
||||
remove('offset1');
|
||||
remove('offset2');
|
||||
await assert_element_width_at_scroll('0px', 0);
|
||||
}, 'Remove both offsets');
|
||||
|
||||
invalidation_test(async () => {
|
||||
// [50, 150]
|
||||
reassign('offset1', scroller.children[3]);
|
||||
reassign('offset2', scroller.children[5]);
|
||||
await assert_element_width_at_scroll('150px', 100);
|
||||
|
||||
reassign('offset1', document.querySelector('.sibling1'));
|
||||
await assert_element_width_at_scroll('0px', 0);
|
||||
}, 'Reassign first offset to sibling of scroller');
|
||||
|
||||
invalidation_test(async () => {
|
||||
// [50, 150]
|
||||
reassign('offset1', scroller.children[3]);
|
||||
reassign('offset2', scroller.children[5]);
|
||||
await assert_element_width_at_scroll('150px', 100);
|
||||
|
||||
reassign('offset2', document.querySelector('.sibling2'));
|
||||
await assert_element_width_at_scroll('0px', 0);
|
||||
}, 'Reassign second offset to sibling of scroller');
|
||||
|
||||
invalidation_test(async () => {
|
||||
// [50, 150]
|
||||
reassign('offset1', scroller.children[3]);
|
||||
reassign('offset2', scroller.children[5]);
|
||||
await assert_element_width_at_scroll('150px', 100);
|
||||
|
||||
reassign('offset1', document.querySelector('.sibling1'));
|
||||
reassign('offset2', document.querySelector('.sibling2'));
|
||||
await assert_element_width_at_scroll('0px', 0);
|
||||
}, 'Reassign both offsets to sibling of scroller');
|
||||
</script>
|
|
@ -1,186 +0,0 @@
|
|||
<!DOCTYPE html>
|
||||
<title>@scroll-timeline source invalidation</title>
|
||||
<link rel="help" src="https://drafts.csswg.org/scroll-animations-1/#scroll-timeline-at-rule">
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
<script src="/web-animations/testcommon.js"></script>
|
||||
<style>
|
||||
#scrollers {
|
||||
overflow: hidden;
|
||||
height: 0;
|
||||
}
|
||||
.scroller {
|
||||
overflow: scroll;
|
||||
width: 100px;
|
||||
height: 100px;
|
||||
}
|
||||
.contents {
|
||||
height: 200px;
|
||||
}
|
||||
@keyframes expand {
|
||||
from { width: 100px; }
|
||||
to { width: 200px; }
|
||||
}
|
||||
@scroll-timeline timeline {
|
||||
source: selector(#scroller);
|
||||
start: 0px;
|
||||
end: 100px;
|
||||
}
|
||||
#element {
|
||||
width: 0px;
|
||||
height: 20px;
|
||||
animation: expand 1000s linear;
|
||||
animation-timeline: timeline;
|
||||
}
|
||||
/* Ensure stable expectations if feature is not supported */
|
||||
@supports not (animation-timeline:foo) {
|
||||
#element { animation-play-state: paused; }
|
||||
}
|
||||
</style>
|
||||
<div id=scrollers></div>
|
||||
<div id=element></div>
|
||||
<script>
|
||||
|
||||
function createScroller() {
|
||||
let scroller = document.createElement('div');
|
||||
let contents = document.createElement('div');
|
||||
scroller.classList.add('scroller');
|
||||
contents.classList.add('contents');
|
||||
scroller.append(contents);
|
||||
return scroller;
|
||||
}
|
||||
|
||||
function wrapInDiv(element) {
|
||||
let div = document.createElement('div');
|
||||
div.append(element);
|
||||
return div;
|
||||
}
|
||||
|
||||
function scrollerAt(n) {
|
||||
return document.querySelectorAll('.scroller')[n];
|
||||
}
|
||||
|
||||
// Resets #scrollers to a state where it has three .scroller children with
|
||||
// scrollTop offsets 10, 20 and 30.
|
||||
function cleanup() {
|
||||
while (scrollers.firstChild)
|
||||
scrollers.firstChild.remove();
|
||||
|
||||
for (let i = 0; i < 3; i++)
|
||||
scrollers.append(createScroller());
|
||||
|
||||
scrollerAt(0).scrollTop = 10;
|
||||
scrollerAt(1).scrollTop = 20;
|
||||
scrollerAt(2).scrollTop = 30;
|
||||
}
|
||||
|
||||
// Do an initial "cleanup" to set up the first test.
|
||||
cleanup();
|
||||
|
||||
function invalidation_test(func, description) {
|
||||
promise_test(async (t) => {
|
||||
t.add_cleanup(cleanup);
|
||||
await func();
|
||||
}, description);
|
||||
}
|
||||
|
||||
invalidation_test(() => {
|
||||
assert_equals(getComputedStyle(element).width, '0px');
|
||||
}, 'Nonexistent source');
|
||||
|
||||
invalidation_test(() => {
|
||||
assert_equals(getComputedStyle(element).width, '0px');
|
||||
scrollerAt(0).setAttribute('id', 'scroller');
|
||||
assert_equals(getComputedStyle(element).width, '110px');
|
||||
scrollerAt(1).setAttribute('id', 'scroller'); // No effect
|
||||
assert_equals(getComputedStyle(element).width, '110px');
|
||||
scrollerAt(2).setAttribute('id', 'scroller'); // No effect
|
||||
assert_equals(getComputedStyle(element).width, '110px');
|
||||
}, 'Setting id attribute');
|
||||
|
||||
invalidation_test(() => {
|
||||
assert_equals(getComputedStyle(element).width, '0px');
|
||||
scrollerAt(0).setAttribute('id', 'scroller');
|
||||
assert_equals(getComputedStyle(element).width, '110px');
|
||||
scrollerAt(0).removeAttribute('id');
|
||||
assert_equals(getComputedStyle(element).width, '0px');
|
||||
}, 'Removing id attribute');
|
||||
|
||||
invalidation_test(() => {
|
||||
assert_equals(getComputedStyle(element).width, '0px');
|
||||
scrollerAt(2).setAttribute('id', 'scroller');
|
||||
assert_equals(getComputedStyle(element).width, '130px');
|
||||
scrollerAt(1).setAttribute('id', 'scroller');
|
||||
assert_equals(getComputedStyle(element).width, '120px');
|
||||
scrollerAt(0).setAttribute('id', 'scroller');
|
||||
assert_equals(getComputedStyle(element).width, '110px');
|
||||
}, 'Setting id attribute earlier in the tree');
|
||||
|
||||
invalidation_test(async () => {
|
||||
assert_equals(getComputedStyle(element).width, '0px');
|
||||
|
||||
// Appending a new element with id 'scroller' already set before
|
||||
// insertion into the tree.
|
||||
let scroller = createScroller();
|
||||
scroller.setAttribute('id', 'scroller');
|
||||
scrollers.append(scroller);
|
||||
|
||||
// Make sure |scroller| has a layout box.
|
||||
//
|
||||
// https://drafts.csswg.org/scroll-animations-1/#avoiding-cycles
|
||||
//
|
||||
// TODO: Depending on the outcome of Issue 5261, the call to offsetTop
|
||||
// might be unnecessary.
|
||||
// https://github.com/w3c/csswg-drafts/issues/5261
|
||||
scroller.offsetTop;
|
||||
await waitForNextFrame();
|
||||
|
||||
assert_equals(getComputedStyle(element).width, '100px');
|
||||
}, 'Appending a new element');
|
||||
|
||||
invalidation_test(async () => {
|
||||
assert_equals(getComputedStyle(element).width, '0px');
|
||||
|
||||
let scroller = createScroller();
|
||||
scroller.setAttribute('id', 'scroller');
|
||||
scrollers.append(wrapInDiv(wrapInDiv(scroller)));
|
||||
await waitForNextFrame();
|
||||
|
||||
assert_equals(getComputedStyle(element).width, '100px');
|
||||
}, 'Inserting a subtree with #scroller descendant');
|
||||
|
||||
invalidation_test(() => {
|
||||
assert_equals(getComputedStyle(element).width, '0px');
|
||||
|
||||
scrollerAt(0).setAttribute('id', 'scroller');
|
||||
scrollerAt(1).setAttribute('id', 'scroller');
|
||||
scrollerAt(2).setAttribute('id', 'scroller');
|
||||
assert_equals(getComputedStyle(element).width, '110px');
|
||||
|
||||
scrollerAt(0).remove();
|
||||
assert_equals(getComputedStyle(element).width, '120px');
|
||||
|
||||
scrollerAt(0).remove();
|
||||
assert_equals(getComputedStyle(element).width, '130px');
|
||||
|
||||
scrollerAt(0).remove();
|
||||
assert_equals(getComputedStyle(element).width, '0px');
|
||||
}, 'Removing source element');
|
||||
|
||||
invalidation_test(async () => {
|
||||
assert_equals(getComputedStyle(element).width, '0px');
|
||||
|
||||
// Create a chain: #scrollers -> div -> div -> #scroller
|
||||
let scroller = createScroller();
|
||||
let div = wrapInDiv(wrapInDiv(scroller));
|
||||
scrollers.append(div);
|
||||
scroller.setAttribute('id', 'scroller');
|
||||
scroller.scrollTop = 50;
|
||||
await waitForNextFrame();
|
||||
assert_equals(getComputedStyle(element).width, '150px');
|
||||
|
||||
div.remove();
|
||||
assert_equals(getComputedStyle(element).width, '0px');
|
||||
}, 'Removing ancestor of source element');
|
||||
|
||||
</script>
|
|
@ -1,131 +0,0 @@
|
|||
<!DOCTYPE html>
|
||||
<link rel="help" src="https://drafts.csswg.org/scroll-animations-1/#scroll-timeline-at-rule">
|
||||
<link rel="help" src="https://drafts.csswg.org/scroll-animations-1/#descdef-scroll-timeline-source">
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
<script src="/web-animations/testcommon.js"></script>
|
||||
<style>
|
||||
:root {
|
||||
height: 100vh;
|
||||
overflow: scroll;
|
||||
}
|
||||
body {
|
||||
height: 200vh;
|
||||
}
|
||||
.scroller {
|
||||
overflow: scroll;
|
||||
width: 100px;
|
||||
height: 100px;
|
||||
}
|
||||
#boxless {
|
||||
display: none;
|
||||
}
|
||||
.contents {
|
||||
height: 300px;
|
||||
}
|
||||
@keyframes expand {
|
||||
from { width: 100px; }
|
||||
to { width: 200px; }
|
||||
}
|
||||
@scroll-timeline timeline_source_none {
|
||||
source: none;
|
||||
start: 0px;
|
||||
end: 100px;
|
||||
}
|
||||
@scroll-timeline timeline_source_auto {
|
||||
source: auto;
|
||||
start: 0px;
|
||||
end: 100px;
|
||||
}
|
||||
@scroll-timeline timeline_source_selector {
|
||||
source: selector(#scroller);
|
||||
start: 0px;
|
||||
end: 100px;
|
||||
}
|
||||
@scroll-timeline timeline_source_unspecified {
|
||||
start: 0px;
|
||||
end: 100px;
|
||||
}
|
||||
@scroll-timeline timeline_source_nonexistent_id {
|
||||
source: selector(#doesnotexist);
|
||||
start: 0px;
|
||||
end: 100px;
|
||||
}
|
||||
@scroll-timeline timeline_source_no_layout_box {
|
||||
source: selector(#boxless);
|
||||
start: 0px;
|
||||
end: 100px;
|
||||
}
|
||||
#container > div {
|
||||
width: 0px;
|
||||
animation-name: expand;
|
||||
animation-duration: 10s;
|
||||
animation-timing-function: linear;
|
||||
}
|
||||
/* Ensure stable expectations if feature is not supported */
|
||||
@supports not (animation-timeline:foo) {
|
||||
#container > div { animation-play-state: paused; }
|
||||
}
|
||||
#element_source_none { animation-timeline: timeline_source_none; }
|
||||
#element_source_auto { animation-timeline: timeline_source_auto; }
|
||||
#element_source_unspecified { animation-timeline: timeline_source_unspecified; }
|
||||
#element_source_selector { animation-timeline: timeline_source_selector; }
|
||||
#element_source_nonexistent_id { animation-timeline: timeline_source_nonexistent_id; }
|
||||
#element_source_no_layout_box { animation-timeline: timeline_source_no_layout_box; }
|
||||
</style>
|
||||
<body>
|
||||
<div class=scroller id=scroller>
|
||||
<div class=contents></div>
|
||||
</div>
|
||||
<div class=scroller id=boxless>
|
||||
<div class=contents></div>
|
||||
</div>
|
||||
<div id=container>
|
||||
<div id=element_source_none></div>
|
||||
<div id=element_source_auto></div>
|
||||
<div id=element_source_unspecified></div>
|
||||
<div id=element_source_selector></div>
|
||||
<div id=element_source_nonexistent_id></div>
|
||||
<div id=element_source_no_layout_box></div>
|
||||
</div>
|
||||
<script>
|
||||
// Set progress of animations linked to #scroller to 75%.
|
||||
scroller.scrollTop = 75;
|
||||
// Set progress of animations linked to document.scrollingElement to 25%.
|
||||
document.scrollingElement.scrollTop = 25;
|
||||
|
||||
promise_test(async (t) => {
|
||||
await waitForNextFrame();
|
||||
assert_equals(getComputedStyle(element_source_none).width, '0px');
|
||||
}, 'Source none causes inactive timeline');
|
||||
|
||||
promise_test(async (t) => {
|
||||
await waitForNextFrame();
|
||||
assert_equals(getComputedStyle(element_source_auto).width, '125px');
|
||||
}, 'Source auto selects scrollingElement of the document');
|
||||
|
||||
promise_test(async (t) => {
|
||||
await waitForNextFrame();
|
||||
assert_equals(getComputedStyle(element_source_unspecified).width, '125px');
|
||||
}, 'Unspecified source behaves like auto');
|
||||
|
||||
promise_test(async (t) => {
|
||||
await waitForNextFrame();
|
||||
assert_equals(getComputedStyle(element_source_selector).width, '175px');
|
||||
}, 'Source selector(<id-selector>) selects an element');
|
||||
|
||||
promise_test(async (t) => {
|
||||
await waitForNextFrame();
|
||||
assert_equals(getComputedStyle(element_source_nonexistent_id).width, '0px');
|
||||
}, 'Unknown source causes inactive timeline');
|
||||
|
||||
promise_test(async (t) => {
|
||||
await waitForNextFrame();
|
||||
assert_equals(getComputedStyle(element_source_no_layout_box).width, '0px');
|
||||
}, 'Source with no layout box causes inactive timeline');
|
||||
|
||||
// TODO(https://github.com/w3c/csswg-drafts/issues/5289): Add tests for
|
||||
// sources that change when behavior is clarified.
|
||||
|
||||
</script>
|
||||
</body>
|
|
@ -1,191 +0,0 @@
|
|||
<!DOCTYPE html>
|
||||
<link rel="help" src="https://drafts.csswg.org/scroll-animations-1/#scroll-timeline-at-rule">
|
||||
<link rel="help" src="https://drafts.csswg.org/scroll-animations-1/#scroll-timeline-offset-section">
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
<script src="/web-animations/testcommon.js"></script>
|
||||
<style>
|
||||
#scroller {
|
||||
overflow: scroll;
|
||||
width: 100px;
|
||||
height: 100px;
|
||||
}
|
||||
#contents {
|
||||
height: 300px;
|
||||
}
|
||||
@keyframes expand {
|
||||
from { width: 100px; }
|
||||
to { width: 200px; }
|
||||
}
|
||||
@scroll-timeline timeline_0px_100px {
|
||||
source: selector(#scroller);
|
||||
start: 0px;
|
||||
end: 100px;
|
||||
}
|
||||
@scroll-timeline timeline_50px_100px {
|
||||
source: selector(#scroller);
|
||||
start: 50px;
|
||||
end: 100px;
|
||||
}
|
||||
@scroll-timeline timeline_auto_auto {
|
||||
source: selector(#scroller);
|
||||
start: auto;
|
||||
end: auto;
|
||||
}
|
||||
@scroll-timeline timeline_auto_auto_implicit {
|
||||
source: selector(#scroller);
|
||||
}
|
||||
@scroll-timeline timeline_50px_auto {
|
||||
source: selector(#scroller);
|
||||
start: 50px;
|
||||
end: auto;
|
||||
}
|
||||
@scroll-timeline timeline_auto_100px {
|
||||
source: selector(#scroller);
|
||||
start: auto;
|
||||
end: 100px;
|
||||
}
|
||||
@scroll-timeline timeline_25p_75p {
|
||||
source: selector(#scroller);
|
||||
start: 25%;
|
||||
end: 75%;
|
||||
}
|
||||
@scroll-timeline timeline_calc_calc {
|
||||
source: selector(#scroller);
|
||||
start: calc(25% + 10px);
|
||||
end: calc(75% + 10px);
|
||||
}
|
||||
#container > div {
|
||||
width: 0px;
|
||||
animation-name: expand;
|
||||
animation-duration: 10s;
|
||||
animation-timing-function: linear;
|
||||
}
|
||||
/* Ensure stable expectations if feature is not supported */
|
||||
@supports not (animation-timeline:foo) {
|
||||
#container > div { animation-play-state: paused; }
|
||||
}
|
||||
#element_0px_100px { animation-timeline: timeline_0px_100px; }
|
||||
#element_50px_100px { animation-timeline: timeline_50px_100px; }
|
||||
#element_auto_auto { animation-timeline: timeline_auto_auto; }
|
||||
#element_auto_auto_implicit { animation-timeline: timeline_auto_auto_implicit; }
|
||||
#element_50px_auto { animation-timeline: timeline_50px_auto; }
|
||||
#element_auto_100px { animation-timeline: timeline_auto_100px; }
|
||||
#element_25p_75p { animation-timeline: timeline_25p_75p; }
|
||||
#element_calc_calc { animation-timeline: timeline_calc_calc; }
|
||||
</style>
|
||||
<div id=scroller>
|
||||
<div id=contents></div>
|
||||
</div>
|
||||
<div id=container>
|
||||
<div id=element_0px_100px></div>
|
||||
<div id=element_50px_100px></div>
|
||||
<div id=element_auto_auto></div>
|
||||
<div id=element_auto_auto_implicit></div>
|
||||
<div id=element_50px_auto></div>
|
||||
<div id=element_auto_100px></div>
|
||||
<div id=element_25p_75p></div>
|
||||
<div id=element_calc_calc></div>
|
||||
</div>
|
||||
<script>
|
||||
|
||||
// Scrolls top to 'offset', waits for a frame, then call the provided
|
||||
// assertions function.
|
||||
function test_scroll(element, offset, assertions, description) {
|
||||
promise_test(async (t) => {
|
||||
scroller.scrollTop = offset;
|
||||
await waitForNextFrame();
|
||||
assertions();
|
||||
}, `${description} [${element.id}]`);
|
||||
}
|
||||
|
||||
// Tests that the computed value of 'width' on element is the expected value
|
||||
// after scrolling top to the specifed offset.
|
||||
function test_width_at_scroll_top(element, offset, expected) {
|
||||
test_scroll(element, offset, () => {
|
||||
assert_equals(getComputedStyle(element).width, expected);
|
||||
}, `Scroll at offset ${offset} updates animation correctly`);
|
||||
}
|
||||
|
||||
// Tests that the computed value of 'width' on element is (approximately)
|
||||
// the expected value after scrolling top to the offset specified by
|
||||
// 'fraction'. The 'fraction' parameter is either a number which maps [0, 1]
|
||||
// to the full scroll range, or a function which accepts the maximum scroll,
|
||||
// and returns a specific offset.
|
||||
function test_approximate_width_at_fraction(element, fraction, expected) {
|
||||
const max = scroller.scrollHeight - scroller.clientHeight;
|
||||
const offsetFunction = (typeof fraction == 'function') ? fraction : () => max * fraction;
|
||||
const resolvedOffset = Math.floor(offsetFunction(max));
|
||||
test_scroll(element, resolvedOffset, () => {
|
||||
assert_approx_equals(parseInt(getComputedStyle(element).width), parseInt(expected), 5);
|
||||
}, `Scroll at offset ${resolvedOffset} updates animation correctly`);
|
||||
}
|
||||
|
||||
// [0px, 100px]
|
||||
test_width_at_scroll_top(element_0px_100px, 0, '100px');
|
||||
test_width_at_scroll_top(element_0px_100px, 1, '101px');
|
||||
test_width_at_scroll_top(element_0px_100px, 50, '150px');
|
||||
test_width_at_scroll_top(element_0px_100px, 99, '199px');
|
||||
test_width_at_scroll_top(element_0px_100px, 100, '0px');
|
||||
test_width_at_scroll_top(element_0px_100px, 101, '0px');
|
||||
|
||||
// [50px, 100px]
|
||||
test_width_at_scroll_top(element_50px_100px, 0, '0px');
|
||||
test_width_at_scroll_top(element_50px_100px, 1, '0px');
|
||||
test_width_at_scroll_top(element_50px_100px, 49, '0px');
|
||||
test_width_at_scroll_top(element_50px_100px, 50, '100px');
|
||||
test_width_at_scroll_top(element_50px_100px, 51, '102px');
|
||||
test_width_at_scroll_top(element_50px_100px, 99, '198px');
|
||||
test_width_at_scroll_top(element_50px_100px, 100, '0px');
|
||||
test_width_at_scroll_top(element_50px_100px, 101, '0px');
|
||||
|
||||
// [auto, auto]
|
||||
test_approximate_width_at_fraction(element_auto_auto, 0, '100px');
|
||||
test_approximate_width_at_fraction(element_auto_auto, 0.1, '110px');
|
||||
test_approximate_width_at_fraction(element_auto_auto, 0.5, '150px');
|
||||
test_approximate_width_at_fraction(element_auto_auto, 0.9, '190px');
|
||||
test_approximate_width_at_fraction(element_auto_auto, 1, '200px');
|
||||
|
||||
// [auto, auto] (implicit)
|
||||
test_approximate_width_at_fraction(element_auto_auto_implicit, 0, '100px');
|
||||
test_approximate_width_at_fraction(element_auto_auto_implicit, 0.1, '110px');
|
||||
test_approximate_width_at_fraction(element_auto_auto_implicit, 0.5, '150px');
|
||||
test_approximate_width_at_fraction(element_auto_auto_implicit, 0.9, '190px');
|
||||
test_approximate_width_at_fraction(element_auto_auto_implicit, 1, '200px');
|
||||
|
||||
// [50px, auto]
|
||||
{
|
||||
let offset = (t) => (max => 50 * (1 - t) + max * t);
|
||||
test_width_at_scroll_top(element_50px_auto, 0, '0px');
|
||||
test_width_at_scroll_top(element_50px_auto, 49, '0px');
|
||||
test_width_at_scroll_top(element_50px_auto, 50, '100px');
|
||||
test_approximate_width_at_fraction(element_50px_auto, offset(0.5), '150px');
|
||||
test_approximate_width_at_fraction(element_50px_auto, offset(0.9), '190px');
|
||||
test_approximate_width_at_fraction(element_50px_auto, 1, '200px');
|
||||
}
|
||||
|
||||
// [auto, 100px]
|
||||
test_width_at_scroll_top(element_auto_100px, 0, '100px');
|
||||
test_width_at_scroll_top(element_auto_100px, 1, '101px');
|
||||
test_width_at_scroll_top(element_auto_100px, 50, '150px');
|
||||
test_width_at_scroll_top(element_auto_100px, 99, '199px');
|
||||
test_width_at_scroll_top(element_auto_100px, 100, '0px');
|
||||
|
||||
// [25%, 75%]
|
||||
test_approximate_width_at_fraction(element_25p_75p, 0, '0px');
|
||||
test_approximate_width_at_fraction(element_25p_75p, 0.1, '0px');
|
||||
test_approximate_width_at_fraction(element_25p_75p, 0.2, '0px');
|
||||
test_approximate_width_at_fraction(element_25p_75p, 0.35, '120px');
|
||||
test_approximate_width_at_fraction(element_25p_75p, 0.55, '160px');
|
||||
test_approximate_width_at_fraction(element_25p_75p, 0.8, '0px');
|
||||
test_approximate_width_at_fraction(element_25p_75p, 1, '0px');
|
||||
|
||||
// [calc(25% + 10px), calc(75% + 10px)]
|
||||
{
|
||||
let offset = (t) => (max => (max * 0.25 + 10) * (1 - t) + (max * 0.75 + 10) * t);
|
||||
test_approximate_width_at_fraction(element_calc_calc, offset(0), '0px');
|
||||
test_approximate_width_at_fraction(element_calc_calc, offset(0.5), '150px');
|
||||
test_approximate_width_at_fraction(element_calc_calc, offset(1.1), '0px');
|
||||
}
|
||||
|
||||
</script>
|
|
@ -1,44 +0,0 @@
|
|||
<!DOCTYPE html>
|
||||
<title>@scroll-timeline: Unknown Descriptors</title>
|
||||
<link rel="help" src="https://drafts.csswg.org/scroll-animations-1/#scroll-timeline-at-rule">
|
||||
<link rel="help" src="https://github.com/w3c/csswg-drafts/issues/5109">
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
<script src="/web-animations/testcommon.js"></script>
|
||||
<style>
|
||||
#scroller {
|
||||
overflow: scroll;
|
||||
width: 100px;
|
||||
height: 100px;
|
||||
}
|
||||
#contents {
|
||||
height: 200px;
|
||||
}
|
||||
@keyframes expand {
|
||||
from { width: 100px; }
|
||||
to { width: 200px; }
|
||||
}
|
||||
@scroll-timeline timeline {
|
||||
unknown: 100px;
|
||||
source: selector(#scroller);
|
||||
start: 0px;
|
||||
end: 100px;
|
||||
time-range: 10s;
|
||||
foo: bar;
|
||||
}
|
||||
#element {
|
||||
width: 0px;
|
||||
animation: expand 10s linear timeline;
|
||||
}
|
||||
</style>
|
||||
<div id=scroller>
|
||||
<div id=contents></div>
|
||||
</div>
|
||||
<div id=element></div>
|
||||
<script>
|
||||
promise_test(async (t) => {
|
||||
scroller.scrollTop = 50;
|
||||
await waitForNextFrame();
|
||||
assert_equals(getComputedStyle(element).width, '150px');
|
||||
}, 'Unknown descriptors do not invalidate the @scroll-timeline rule');
|
||||
</script>
|
|
@ -0,0 +1,241 @@
|
|||
<!DOCTYPE html>
|
||||
<title>The various animation longhands with progress based animations</title>
|
||||
<link rel="help" src="https://drafts.csswg.org/css-animations-2">
|
||||
<link rel="help" src="https://github.com/w3c/csswg-drafts/issues/4862">
|
||||
<link rel="help" src="https://github.com/w3c/csswg-drafts/issues/6674">
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
<script src="/web-animations/testcommon.js"></script>
|
||||
<script src="support/testcommon.js"></script>
|
||||
<style>
|
||||
@keyframes anim {
|
||||
from { translate: 0px; }
|
||||
to { translate: 100px; }
|
||||
}
|
||||
#container {
|
||||
width: 300px;
|
||||
height: 300px;
|
||||
overflow: scroll;
|
||||
}
|
||||
#target {
|
||||
width: 100px;
|
||||
height: 100px;
|
||||
translate: none;
|
||||
}
|
||||
</style>
|
||||
<body>
|
||||
<div id="log"></div>
|
||||
<script>
|
||||
"use strict";
|
||||
|
||||
const createTargetAndScroller = function(t) {
|
||||
let container = document.createElement('div');
|
||||
container.id = 'container';
|
||||
let target = document.createElement('div');
|
||||
target.id = 'target';
|
||||
let content = document.createElement('div');
|
||||
content.style.blockSize = '100%';
|
||||
|
||||
// The height of target is 100px and the content is 100%, so the scroll range
|
||||
// is [0, 100].
|
||||
|
||||
// <div id='container'>
|
||||
// <div id='target'></div>
|
||||
// <div style='block-size: 100%;'></div>
|
||||
// </div>
|
||||
document.body.appendChild(container);
|
||||
container.appendChild(target);
|
||||
container.appendChild(content);
|
||||
|
||||
if (t && typeof t.add_cleanup === 'function') {
|
||||
t.add_cleanup(() => {
|
||||
content.remove();
|
||||
target.remove();
|
||||
container.remove();
|
||||
});
|
||||
}
|
||||
|
||||
return [target, container];
|
||||
};
|
||||
|
||||
async function scrollTop(element, value) {
|
||||
element.scrollTop = value;
|
||||
await waitForNextFrame();
|
||||
}
|
||||
|
||||
// ------------------------------
|
||||
// Test animation-duration
|
||||
// ------------------------------
|
||||
|
||||
promise_test(async t => {
|
||||
let [target, scroller] = createTargetAndScroller(t);
|
||||
target.style.animation = '10s linear anim scroll(nearest)';
|
||||
|
||||
await scrollTop(scroller, 25); // [0, 100].
|
||||
assert_equals(getComputedStyle(target).translate, '25px');
|
||||
}, 'animation-duration');
|
||||
|
||||
promise_test(async t => {
|
||||
let [target, scroller] = createTargetAndScroller(t);
|
||||
target.style.animation = '0s linear anim scroll(nearest)';
|
||||
|
||||
await scrollTop(scroller, 25); // [0, 100].
|
||||
assert_equals(getComputedStyle(target).translate, '100px');
|
||||
}, 'animation-duration: 0s');
|
||||
|
||||
|
||||
// ------------------------------
|
||||
// Test animation-iteration-count
|
||||
// ------------------------------
|
||||
|
||||
promise_test(async t => {
|
||||
let [target, scroller] = createTargetAndScroller(t);
|
||||
target.style.animation = '10s linear anim scroll(nearest)';
|
||||
|
||||
await scrollTop(scroller, 25); // [0, 100].
|
||||
assert_equals(getComputedStyle(target).translate, '25px');
|
||||
|
||||
// Let animation become 50% in the 1st iteration.
|
||||
target.style.animationIterationCount = '2';
|
||||
await waitForCSSScrollTimelineStyle();
|
||||
assert_equals(getComputedStyle(target).translate, '50px');
|
||||
|
||||
// Let animation become 0% in the 2nd iteration.
|
||||
target.style.animationIterationCount = '4';
|
||||
await waitForCSSScrollTimelineStyle();
|
||||
assert_equals(getComputedStyle(target).translate, '0px');
|
||||
}, 'animation-iteration-count');
|
||||
|
||||
promise_test(async t => {
|
||||
let [target, scroller] = createTargetAndScroller(t);
|
||||
target.style.animation = '10s linear anim scroll(nearest)';
|
||||
target.style.animationIterationCount = '0';
|
||||
|
||||
await scrollTop(scroller, 25); // [0, 100].
|
||||
assert_equals(getComputedStyle(target).translate, '0px');
|
||||
}, 'animation-iteration-count: 0');
|
||||
|
||||
promise_test(async t => {
|
||||
let [target, scroller] = createTargetAndScroller(t);
|
||||
target.style.animation = '10s linear anim scroll(nearest)';
|
||||
target.style.animationIterationCount = 'infinite';
|
||||
|
||||
await scrollTop(scroller, 25); // [0, 100].
|
||||
assert_equals(getComputedStyle(target).translate, '100px');
|
||||
}, 'animation-iteration-count: infinite');
|
||||
|
||||
|
||||
// ------------------------------
|
||||
// Test animation-direction
|
||||
// ------------------------------
|
||||
|
||||
promise_test(async t => {
|
||||
let [target, scroller] = createTargetAndScroller(t);
|
||||
target.style.animation = '10s linear anim scroll(nearest)';
|
||||
|
||||
await scrollTop(scroller, 25) // [0, 100].
|
||||
assert_equals(getComputedStyle(target).translate, '25px');
|
||||
}, 'animation-direction: normal');
|
||||
|
||||
promise_test(async t => {
|
||||
let [target, scroller] = createTargetAndScroller(t);
|
||||
target.style.animation = '10s linear anim scroll(nearest)';
|
||||
target.style.animationDirection = 'reverse';
|
||||
|
||||
await scrollTop(scroller, 25); // 25% in the reversing direction.
|
||||
assert_equals(getComputedStyle(target).translate, '75px');
|
||||
}, 'animation-direction: reverse');
|
||||
|
||||
promise_test(async t => {
|
||||
let [target, scroller] = createTargetAndScroller(t);
|
||||
target.style.animation = '10s linear anim scroll(nearest)';
|
||||
target.style.animationIterationCount = '2';
|
||||
target.style.animationDirection = 'alternate';
|
||||
|
||||
await scrollTop(scroller, 10); // 20% in the 1st iteration.
|
||||
assert_equals(getComputedStyle(target).translate, '20px');
|
||||
|
||||
await scrollTop(scroller, 60); // 20% in the 2nd iteration (reversing direction).
|
||||
assert_equals(getComputedStyle(target).translate, '80px');
|
||||
}, 'animation-direction: alternate');
|
||||
|
||||
promise_test(async t => {
|
||||
let [target, scroller] = createTargetAndScroller(t);
|
||||
target.style.animation = '10s linear anim scroll(nearest)';
|
||||
target.style.animationIterationCount = '2';
|
||||
target.style.animationDirection = 'alternate-reverse';
|
||||
|
||||
await scrollTop(scroller, 10); // 20% in the 1st iteration (reversing direction).
|
||||
assert_equals(getComputedStyle(target).translate, '80px');
|
||||
|
||||
await scrollTop(scroller, 60); // 20% in the 2nd iteration.
|
||||
assert_equals(getComputedStyle(target).translate, '20px');
|
||||
}, 'animation-direction: alternate-reverse');
|
||||
|
||||
|
||||
// ------------------------------
|
||||
// Test animation-delay
|
||||
// ------------------------------
|
||||
|
||||
promise_test(async t => {
|
||||
let [target, scroller] = createTargetAndScroller(t);
|
||||
target.style.animation = '10s linear anim scroll(nearest)';
|
||||
|
||||
await scrollTop(scroller, 25); // [0, 100].
|
||||
assert_equals(getComputedStyle(target).translate, '25px');
|
||||
|
||||
// (start delay: 10s) (duration: 10s)
|
||||
// before active
|
||||
// |--------------------|--------------------|
|
||||
// 0px 50px 100px (The scroller)
|
||||
// 0% 100% (The iteration progress)
|
||||
|
||||
// Let animation be in before phase.
|
||||
target.style.animationDelay = '10s';
|
||||
target.style.animationDelayStart = '10s'; // crbug.com/1375994
|
||||
assert_equals(getComputedStyle(target).translate, 'none');
|
||||
|
||||
await scrollTop(scroller, 50); // The animation enters active phase.
|
||||
assert_equals(getComputedStyle(target).translate, '0px');
|
||||
|
||||
await scrollTop(scroller, 75); // The ieration progress is 50%.
|
||||
assert_equals(getComputedStyle(target).translate, '50px');
|
||||
}, 'animation-delay with a positive value');
|
||||
|
||||
promise_test(async t => {
|
||||
let [target, scroller] = createTargetAndScroller(t);
|
||||
target.style.animation = '10s linear anim scroll(nearest)';
|
||||
|
||||
// active
|
||||
// |--------------------|
|
||||
// 0px 100px (The scroller)
|
||||
// 50% 100% (The iteration progress)
|
||||
|
||||
await scrollTop(scroller, 20); // [0, 100].
|
||||
target.style.animationDelay = '-5s';
|
||||
target.style.animationDelayStart = '-5s'; // crbug.com/1375994
|
||||
await waitForCSSScrollTimelineStyle();
|
||||
assert_equals(getComputedStyle(target).translate, '60px');
|
||||
}, 'animation-delay with a negative value');
|
||||
|
||||
|
||||
// ------------------------------
|
||||
// Test animation-fill-mode
|
||||
// ------------------------------
|
||||
|
||||
promise_test(async t => {
|
||||
let [target, scroller] = createTargetAndScroller(t);
|
||||
target.style.animation = '10s linear anim scroll(nearest)';
|
||||
target.style.animationDelay = '10s';
|
||||
target.style.animationDelayStart = '10s'; // crbug.com/1375994
|
||||
|
||||
await scrollTop(scroller, 25);
|
||||
assert_equals(getComputedStyle(target).translate, 'none');
|
||||
|
||||
target.style.animationFillMode = 'backwards';
|
||||
await waitForCSSScrollTimelineStyle();
|
||||
assert_equals(getComputedStyle(target).translate, '0px');
|
||||
}, 'animation-fill-mode');
|
||||
|
||||
</script>
|
||||
</body>
|
|
@ -5,16 +5,12 @@
|
|||
<script src="/resources/testharnessreport.js"></script>
|
||||
<script src="/web-animations/testcommon.js"></script>
|
||||
<style>
|
||||
#scrollers {
|
||||
main > div {
|
||||
overflow: hidden;
|
||||
height: 0px;
|
||||
}
|
||||
#scrollers > div {
|
||||
overflow: scroll;
|
||||
width: 100px;
|
||||
height: 100px;
|
||||
}
|
||||
#scrollers > div > div {
|
||||
main > div > div {
|
||||
height: 200px;
|
||||
}
|
||||
|
||||
|
@ -23,10 +19,8 @@
|
|||
to { top: 200px; }
|
||||
}
|
||||
|
||||
@scroll-timeline top_timeline {
|
||||
source: selector(#scroller1);
|
||||
start: 0px;
|
||||
end: 100px;
|
||||
#scroller1 {
|
||||
scroll-timeline: top_timeline;
|
||||
}
|
||||
|
||||
#element {
|
||||
|
@ -40,19 +34,19 @@
|
|||
#element { animation-play-state: paused; }
|
||||
}
|
||||
</style>
|
||||
<div id=scrollers>
|
||||
<main>
|
||||
<div id=scroller1><div></div></div>
|
||||
</div>
|
||||
<div id=element></div>
|
||||
<div id=element></div>
|
||||
</main>
|
||||
<script>
|
||||
// Force layout of scrollers.
|
||||
scroller1.offsetTop;
|
||||
|
||||
scroller1.scrollTop = 20;
|
||||
|
||||
promise_test(async (t) => {
|
||||
await waitForNextFrame();
|
||||
assert_equals(getComputedStyle(element).top, '120px');
|
||||
}, 'progress based animation timeline works');
|
||||
|
||||
window.onload = async () => {
|
||||
promise_test(async (t) => {
|
||||
await waitForNextFrame();
|
||||
const anim = document.getAnimations()[0];
|
||||
await anim.ready;
|
||||
scroller1.scrollTop = 20;
|
||||
await waitForNextFrame();
|
||||
assert_equals(getComputedStyle(element).top, '120px');
|
||||
}, 'progress based animation timeline works');
|
||||
};
|
||||
</script>
|
||||
|
|
|
@ -0,0 +1,35 @@
|
|||
<!DOCTYPE html>
|
||||
<link rel="help" href="https://github.com/w3c/csswg-drafts/issues/6674">
|
||||
<link rel="help" href="https://drafts.csswg.org/scroll-animations-1/rewrite#scroll-timeline-axis">
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
<script src="/css/support/computed-testcommon.js"></script>
|
||||
</head>
|
||||
<style>
|
||||
#outer { scroll-timeline-axis: inline; }
|
||||
#target { scroll-timeline-axis: vertical; }
|
||||
</style>
|
||||
<div id="outer">
|
||||
<div id="target"></div>
|
||||
</div>
|
||||
<script>
|
||||
test_computed_value('scroll-timeline-axis', 'initial', 'block');
|
||||
test_computed_value('scroll-timeline-axis', 'inherit', 'inline');
|
||||
test_computed_value('scroll-timeline-axis', 'unset', 'block');
|
||||
test_computed_value('scroll-timeline-axis', 'revert', 'block');
|
||||
test_computed_value('scroll-timeline-axis', 'block');
|
||||
test_computed_value('scroll-timeline-axis', 'inline');
|
||||
test_computed_value('scroll-timeline-axis', 'vertical');
|
||||
test_computed_value('scroll-timeline-axis', 'horizontal');
|
||||
|
||||
test(() => {
|
||||
let style = getComputedStyle(document.getElementById('target'));
|
||||
assert_not_equals(Array.from(style).indexOf('scroll-timeline-axis'), -1);
|
||||
}, 'The scroll-timeline-axis property shows up in CSSStyleDeclaration enumeration');
|
||||
|
||||
test(() => {
|
||||
let style = document.getElementById('target').style;
|
||||
assert_not_equals(style.cssText.indexOf('scroll-timeline-axis'), -1);
|
||||
}, 'The scroll-timeline-axis property shows up in CSSStyleDeclaration.cssText');
|
||||
|
||||
</script>
|
|
@ -0,0 +1,27 @@
|
|||
<!DOCTYPE html>
|
||||
<link rel="help" href="https://github.com/w3c/csswg-drafts/issues/6674">
|
||||
<link rel="help" href="https://drafts.csswg.org/scroll-animations-1/rewrite#scroll-timeline-axis">
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
<script src="/css/support/parsing-testcommon.js"></script>
|
||||
</head>
|
||||
<div id="target"></div>
|
||||
|
||||
<script>
|
||||
|
||||
test_valid_value('scroll-timeline-axis', 'initial');
|
||||
test_valid_value('scroll-timeline-axis', 'inherit');
|
||||
test_valid_value('scroll-timeline-axis', 'unset');
|
||||
test_valid_value('scroll-timeline-axis', 'revert');
|
||||
|
||||
test_valid_value('scroll-timeline-axis', 'block');
|
||||
test_valid_value('scroll-timeline-axis', 'inline');
|
||||
test_valid_value('scroll-timeline-axis', 'vertical');
|
||||
test_valid_value('scroll-timeline-axis', 'horizontal');
|
||||
|
||||
test_invalid_value('scroll-timeline-axis', 'abc');
|
||||
test_invalid_value('scroll-timeline-axis', '10px');
|
||||
test_invalid_value('scroll-timeline-axis', 'auto');
|
||||
test_invalid_value('scroll-timeline-axis', 'none');
|
||||
|
||||
</script>
|
|
@ -1,70 +1,45 @@
|
|||
<!DOCTYPE html>
|
||||
<link rel="help" src="https://drafts.csswg.org/scroll-animations-1/#scroll-timeline-at-rule">
|
||||
<link rel="help" src="https://drafts.csswg.org/scroll-animations-1/#descdef-scroll-timeline-orientation">
|
||||
<meta name="viewport" content="width=device-width,initial-scale=1,minimum-scale=1">
|
||||
<link rel="help" src="https://drafts.csswg.org/scroll-animations-1/#scroll-timeline-axis">
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
<script src="/web-animations/testcommon.js"></script>
|
||||
<style>
|
||||
#scroller_horizontal_tb, #scroller_vertical_lr{
|
||||
overflow: scroll;
|
||||
.scroller {
|
||||
overflow: hidden;
|
||||
width: 100px;
|
||||
height: 100px;
|
||||
}
|
||||
#scroller_horizontal_tb {
|
||||
writing-mode: horizontal-tb;
|
||||
}
|
||||
#scroller_vertical_lr {
|
||||
writing-mode: vertical-lr;
|
||||
}
|
||||
.contents {
|
||||
height: 300px;
|
||||
width: 300px;
|
||||
height: 200px;
|
||||
width: 200px;
|
||||
}
|
||||
@keyframes expand {
|
||||
from { width: 100px; }
|
||||
to { width: 200px; }
|
||||
}
|
||||
@scroll-timeline timeline_auto {
|
||||
source: selector(#scroller_horizontal_tb);
|
||||
orientation: auto;
|
||||
start: 0px;
|
||||
end: 100px;
|
||||
#timeline_initial_axis {
|
||||
scroll-timeline: timeline_initial_axis;
|
||||
}
|
||||
@scroll-timeline timeline_vertical {
|
||||
source: selector(#scroller_horizontal_tb);
|
||||
orientation: vertical;
|
||||
start: 0px;
|
||||
end: 100px;
|
||||
#timeline_vertical {
|
||||
scroll-timeline: vertical timeline_vertical;
|
||||
}
|
||||
@scroll-timeline timeline_horizontal {
|
||||
source: selector(#scroller_horizontal_tb);
|
||||
orientation: horizontal;
|
||||
start: 0px;
|
||||
end: 100px;
|
||||
#timeline_horizontal {
|
||||
scroll-timeline: horizontal timeline_horizontal;
|
||||
}
|
||||
@scroll-timeline timeline_block_in_horizontal {
|
||||
source: selector(#scroller_horizontal_tb);
|
||||
orientation: block;
|
||||
start: 0px;
|
||||
end: 100px;
|
||||
#timeline_block_in_horizontal {
|
||||
scroll-timeline: block timeline_block_in_horizontal;
|
||||
}
|
||||
@scroll-timeline timeline_inline_in_horizontal {
|
||||
source: selector(#scroller_horizontal_tb);
|
||||
orientation: inline;
|
||||
start: 0px;
|
||||
end: 100px;
|
||||
#timeline_inline_in_horizontal {
|
||||
scroll-timeline: inline timeline_inline_in_horizontal;
|
||||
}
|
||||
@scroll-timeline timeline_block_in_vertical {
|
||||
source: selector(#scroller_vertical_lr);
|
||||
orientation: block;
|
||||
start: 0px;
|
||||
end: 100px;
|
||||
#timeline_block_in_vertical {
|
||||
scroll-timeline: block timeline_block_in_vertical;
|
||||
writing-mode: vertical-lr;
|
||||
}
|
||||
@scroll-timeline timeline_inline_in_vertical {
|
||||
source: selector(#scroller_vertical_lr);
|
||||
orientation: inline;
|
||||
start: 0px;
|
||||
end: 100px;
|
||||
#timeline_inline_in_vertical {
|
||||
scroll-timeline: inline timeline_inline_in_vertical;
|
||||
writing-mode: vertical-lr;
|
||||
}
|
||||
#container > div {
|
||||
width: 0px;
|
||||
|
@ -76,7 +51,7 @@
|
|||
@supports not (animation-timeline:foo) {
|
||||
#container > div { animation-play-state: paused; }
|
||||
}
|
||||
#element_auto { animation-timeline: timeline_auto; }
|
||||
#element_initial_axis { animation-timeline: timeline_initial_axis; }
|
||||
#element_vertical { animation-timeline: timeline_vertical; }
|
||||
#element_horizontal { animation-timeline: timeline_horizontal; }
|
||||
#element_block_in_horizontal { animation-timeline: timeline_block_in_horizontal; }
|
||||
|
@ -84,14 +59,15 @@
|
|||
#element_block_in_vertical { animation-timeline: timeline_block_in_vertical; }
|
||||
#element_inline_in_vertical { animation-timeline: timeline_inline_in_vertical; }
|
||||
</style>
|
||||
<div id=scroller_horizontal_tb>
|
||||
<div class=contents></div>
|
||||
</div>
|
||||
<div id=scroller_vertical_lr>
|
||||
<div class=contents></div>
|
||||
</div>
|
||||
<div class=scroller id=timeline_initial_axis><div class=contents></div></div>
|
||||
<div class=scroller id=timeline_vertical><div class=contents></div></div>
|
||||
<div class=scroller id=timeline_horizontal><div class=contents></div></div>
|
||||
<div class=scroller id=timeline_block_in_horizontal><div class=contents></div></div>
|
||||
<div class=scroller id=timeline_inline_in_horizontal><div class=contents></div></div>
|
||||
<div class=scroller id=timeline_block_in_vertical><div class=contents></div></div>
|
||||
<div class=scroller id=timeline_inline_in_vertical><div class=contents></div></div>
|
||||
<div id=container>
|
||||
<div id=element_auto></div>
|
||||
<div id=element_initial_axis></div>
|
||||
<div id=element_vertical></div>
|
||||
<div id=element_horizontal></div>
|
||||
<div id=element_block_in_horizontal></div>
|
||||
|
@ -101,47 +77,50 @@
|
|||
</div>
|
||||
<script>
|
||||
// Animations linked to vertical scroll-timelines are at 75% progress.
|
||||
scroller_horizontal_tb.scrollTop = 75;
|
||||
scroller_vertical_lr.scrollTop = 75;
|
||||
timeline_initial_axis.scrollTop = 75;
|
||||
timeline_vertical.scrollTop = 75;
|
||||
timeline_block_in_horizontal.scrollTop = 75;
|
||||
timeline_inline_in_vertical.scrollTop = 75;
|
||||
// Animations linked to horizontal scroll-timelines are at 25% progress.
|
||||
scroller_horizontal_tb.scrollLeft = 25;
|
||||
scroller_vertical_lr.scrollLeft = 25;
|
||||
timeline_horizontal.scrollLeft = 25;
|
||||
timeline_block_in_vertical.scrollLeft = 25;
|
||||
timeline_inline_in_horizontal.scrollLeft = 25;
|
||||
|
||||
promise_test(async (t) => {
|
||||
await waitForNextFrame();
|
||||
assert_equals(getComputedStyle(element_auto).width, '175px');
|
||||
}, 'Orientation auto behaves as expected');
|
||||
assert_equals(getComputedStyle(element_initial_axis).width, '175px');
|
||||
}, 'Initial axis');
|
||||
|
||||
promise_test(async (t) => {
|
||||
await waitForNextFrame();
|
||||
assert_equals(getComputedStyle(element_vertical).width, '175px');
|
||||
}, 'Orientation vertical behaves as expected');
|
||||
}, 'Vertical axis');
|
||||
|
||||
promise_test(async (t) => {
|
||||
await waitForNextFrame();
|
||||
assert_equals(getComputedStyle(element_horizontal).width, '125px');
|
||||
}, 'Orientation horizontal behaves as expected');
|
||||
}, 'Horizontal axis');
|
||||
|
||||
promise_test(async (t) => {
|
||||
await waitForNextFrame();
|
||||
assert_equals(getComputedStyle(element_block_in_horizontal).width, '175px');
|
||||
}, 'Orientation block behaves as expected in horizontal writing-mode');
|
||||
}, 'Block axis in horizontal writing-mode');
|
||||
|
||||
promise_test(async (t) => {
|
||||
await waitForNextFrame();
|
||||
assert_equals(getComputedStyle(element_inline_in_horizontal).width, '125px');
|
||||
}, 'Orientation inline behaves as expected in horizontal writing-mode');
|
||||
}, 'Inline axis in horizontal writing-mode');
|
||||
|
||||
promise_test(async (t) => {
|
||||
await waitForNextFrame();
|
||||
assert_equals(getComputedStyle(scroller_vertical_lr).writingMode, 'vertical-lr');
|
||||
assert_equals(getComputedStyle(timeline_block_in_vertical).writingMode, 'vertical-lr');
|
||||
assert_equals(getComputedStyle(element_block_in_vertical).width, '125px');
|
||||
}, 'Orientation block behaves as expected in vertical writing-mode');
|
||||
}, 'Block axis in vertical writing-mode');
|
||||
|
||||
promise_test(async (t) => {
|
||||
await waitForNextFrame();
|
||||
assert_equals(getComputedStyle(scroller_vertical_lr).writingMode, 'vertical-lr');
|
||||
assert_equals(getComputedStyle(timeline_inline_in_vertical).writingMode, 'vertical-lr');
|
||||
assert_equals(getComputedStyle(element_inline_in_vertical).width, '175px');
|
||||
}, 'Orientation inline behaves as expected in vertical writing-mode');
|
||||
}, 'Inline axis in vertical writing-mode');
|
||||
|
||||
</script>
|
|
@ -1,273 +0,0 @@
|
|||
<!DOCTYPE html>
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
<script src="/css/support/parsing-testcommon.js"></script>
|
||||
<div id="target"></div>
|
||||
<script>
|
||||
|
||||
// Runs a function while a stylesheet is temporarily inserted into the
|
||||
// document.
|
||||
function with_stylesheet(text, func) {
|
||||
let s = document.createElement('style');
|
||||
try {
|
||||
s.textContent = text;
|
||||
document.documentElement.append(s);
|
||||
func(s.sheet.rules);
|
||||
} finally {
|
||||
s.remove();
|
||||
}
|
||||
}
|
||||
|
||||
// Runs a test while a stylesheet is temporarily inserted into the
|
||||
// document.
|
||||
function test_stylesheet(text, func, description) {
|
||||
test(() => {
|
||||
with_stylesheet(text, func);
|
||||
}, description);
|
||||
}
|
||||
|
||||
function test_valid_rule(text, description) {
|
||||
test_stylesheet(text, (rules) => {
|
||||
assert_equals(rules.length, 1);
|
||||
assert_equals(rules[0].constructor.name, 'CSSScrollTimelineRule');
|
||||
}, description);
|
||||
}
|
||||
|
||||
function test_invalid_rule(text, description) {
|
||||
test_stylesheet(text, (rules) => {
|
||||
assert_equals(rules.length, 0);
|
||||
}, description);
|
||||
}
|
||||
|
||||
// Verify that for the _specifed_ value for a given _descriptor_, the _expected_
|
||||
// string can be observed via the equivalent attribute on CSSScrollTimelineRule.
|
||||
function test_descriptor(descriptor, specified, expected) {
|
||||
if (typeof(expected) == 'undefined')
|
||||
expected = specified;
|
||||
let attribute = descriptor.replaceAll(/\-./g, x => x[1].toUpperCase());
|
||||
test_stylesheet(`@scroll-timeline test { ${descriptor}:${specified}; }`, (rules) => {
|
||||
assert_equals(rules.length, 1);
|
||||
assert_equals(rules[0].constructor.name, 'CSSScrollTimelineRule');
|
||||
if (Array.isArray(expected)) {
|
||||
assert_in_array(rules[0][attribute], expected, "serialization should be sound");
|
||||
} else {
|
||||
assert_equals(rules[0][attribute], expected, "serialization should be canonical");
|
||||
}
|
||||
}, `CSSScrollTimelineRule.${attribute} ${specified}`);
|
||||
}
|
||||
|
||||
test_valid_rule('@scroll-timeline foo {}', 'Empty block');
|
||||
test_valid_rule('@scroll-timeline foo {', 'EOF ends block');
|
||||
test_valid_rule('@scroll-timeline "foo" {}', 'Timeline name can be a <string>');
|
||||
|
||||
test_invalid_rule('@scroll-timeline', 'Missing prelude');
|
||||
test_invalid_rule('@scroll-timeline foo', 'Missing block');
|
||||
test_invalid_rule('@scroll-timeline {}', 'Missing timeline name');
|
||||
test_invalid_rule('@scroll-timeline 123 {}', 'Timeline name must be an identifier');
|
||||
test_invalid_rule('@scroll-timeline none {}', 'Timeline name must match <custom-ident>');
|
||||
test_invalid_rule('@scroll-timeline NONE {}', 'Timeline name must match <custom-ident> (caps)');
|
||||
test_invalid_rule('@scroll-timeline NoNe {}', 'Timeline name must match <custom-ident> (mixed)');
|
||||
test_invalid_rule('@scroll-timeline initial {}', 'Timeline name may not be initial');
|
||||
test_invalid_rule('@scroll-timeline inherit {}', 'Timeline name may not be inherit');
|
||||
test_invalid_rule('@scroll-timeline unset {}', 'Timeline name may not be unset');
|
||||
test_invalid_rule('@scroll-timeline revert {}', 'Timeline name may not be revert');
|
||||
test_invalid_rule('@scroll-timeline default {}', 'Timeline name may not be default');
|
||||
test_invalid_rule('@scroll-timeline foo bar {}', 'Extra timeline name');
|
||||
|
||||
// CSSRule.type
|
||||
|
||||
test(() => {
|
||||
with_stylesheet(`@scroll-timeline valid { }`, (rules) => {
|
||||
assert_equals(rules.length, 1);
|
||||
let rule = rules[0];
|
||||
assert_equals(rule.constructor.name, 'CSSScrollTimelineRule');
|
||||
assert_equals(rule.type, 0);
|
||||
});
|
||||
}, 'CSSRule.type returns 0');
|
||||
|
||||
// CSSScrollTimelineRule.name
|
||||
|
||||
function test_name(specified, expected) {
|
||||
if (typeof(expected) == 'undefined')
|
||||
expected = specified;
|
||||
test_stylesheet(`@scroll-timeline ${specified} { }`, (rules) => {
|
||||
assert_equals(rules.length, 1);
|
||||
assert_equals(rules[0].constructor.name, 'CSSScrollTimelineRule');
|
||||
assert_equals(rules[0].name, expected);
|
||||
}, `CSSScrollTimelineRule.name ${specified}`);
|
||||
}
|
||||
|
||||
test_name('foo');
|
||||
test_name('Foo');
|
||||
test_name('f___123');
|
||||
test_name('a\\9 b', 'a\tb'); // U+0009 CHARACTER TABULATION
|
||||
test_name('"foo"', 'foo');
|
||||
test_name('"none"', 'none');
|
||||
|
||||
// CSSScrollTimelineRule.cssText
|
||||
|
||||
function test_csstext(description, specified, expected) {
|
||||
if (typeof(expected) == 'undefined')
|
||||
expected = specified;
|
||||
test_stylesheet(specified, (rules) => {
|
||||
assert_equals(rules.length, 1);
|
||||
assert_equals(rules[0].constructor.name, 'CSSScrollTimelineRule');
|
||||
assert_equals(rules[0].cssText, expected);
|
||||
}, `CSSScrollTimelineRule.cssText: ${description}`);
|
||||
}
|
||||
|
||||
test_csstext(
|
||||
'empty rule',
|
||||
`@scroll-timeline timeline {}`,
|
||||
`@scroll-timeline timeline { }`);
|
||||
|
||||
// U+0009 CHARACTER TABULATION
|
||||
test_csstext(
|
||||
'escaped name',
|
||||
`@scroll-timeline tab\\9 tab {}`,
|
||||
`@scroll-timeline tab\\9 tab { }`);
|
||||
|
||||
test_csstext(
|
||||
'source descriptor',
|
||||
`@scroll-timeline timeline { source: selector(#foo); }`);
|
||||
|
||||
test_csstext(
|
||||
'orientation descriptor',
|
||||
`@scroll-timeline timeline { orientation: inline; }`);
|
||||
|
||||
// https://github.com/w3c/csswg-drafts/issues/6617
|
||||
test_csstext(
|
||||
'scroll-offsets descriptor (none)',
|
||||
`@scroll-timeline timeline { scroll-offsets: none; }`,
|
||||
`@scroll-timeline timeline { scroll-offsets: none; }`,);
|
||||
|
||||
test_csstext(
|
||||
'scroll-offsets descriptor (auto)',
|
||||
`@scroll-timeline timeline { scroll-offsets: auto; }`);
|
||||
|
||||
test_csstext(
|
||||
'scroll-offsets descriptor (container-based offset, px)',
|
||||
`@scroll-timeline timeline { scroll-offsets: 100px; }`);
|
||||
|
||||
test_csstext(
|
||||
'scroll-offsets descriptor (container-based offset, percentage)',
|
||||
`@scroll-timeline timeline { scroll-offsets: 100%; }`);
|
||||
|
||||
test_csstext(
|
||||
'scroll-offsets descriptor (element offset)',
|
||||
`@scroll-timeline timeline { scroll-offsets: selector(#bar); }`);
|
||||
|
||||
test_csstext(
|
||||
'scroll-offsets descriptor (element offset with edge)',
|
||||
`@scroll-timeline timeline { scroll-offsets: selector(#bar) start; }`);
|
||||
|
||||
test_csstext(
|
||||
'scroll-offsets descriptor (element offset with threshold)',
|
||||
`@scroll-timeline timeline { scroll-offsets: selector(#bar) 1; }`);
|
||||
|
||||
test_csstext(
|
||||
'scroll-offsets descriptor (element offset with edge and threshold)',
|
||||
`@scroll-timeline timeline { scroll-offsets: selector(#bar) start 1; }`);
|
||||
|
||||
test_csstext(
|
||||
'scroll-offsets descriptor (element offset with threshold and edge)',
|
||||
`@scroll-timeline timeline { scroll-offsets: selector(#bar) 1 start; }`,
|
||||
`@scroll-timeline timeline { scroll-offsets: selector(#bar) start 1; }`);
|
||||
|
||||
test_csstext(
|
||||
'scroll-offsets descriptor (multiple offsets)',
|
||||
`@scroll-timeline timeline { scroll-offsets: auto, selector(#bar) start 1; }`);
|
||||
|
||||
test_csstext(
|
||||
'defaults',
|
||||
`@scroll-timeline timeline { source: auto; orientation: auto; scroll-offsets: none; }`);
|
||||
|
||||
test_csstext(
|
||||
'order',
|
||||
`@scroll-timeline timeline { orientation: auto; source: auto; scroll-offsets: none; }`,
|
||||
`@scroll-timeline timeline { source: auto; orientation: auto; scroll-offsets: none; }`);
|
||||
|
||||
// CSSScrollTimelineRule.source
|
||||
|
||||
function test_source(specified, expected) {
|
||||
test_descriptor('source', specified, expected);
|
||||
}
|
||||
|
||||
test_source('selector(#foo)');
|
||||
test_source('selector( #foo )', 'selector(#foo)');
|
||||
test_source(' selector(#foo) ', 'selector(#foo)');
|
||||
test_source('none');
|
||||
test_source(' none ', 'none');
|
||||
test_source('selector(#a\\9 b)');
|
||||
test_source('auto');
|
||||
|
||||
test_source('#foo', 'auto');
|
||||
test_source('', 'auto');
|
||||
test_source('element(#foo)', 'auto');
|
||||
test_source('selector(#foo more)', 'auto');
|
||||
test_source('selector(html)', 'auto');
|
||||
test_source('selector(foo)', 'auto');
|
||||
test_source('selector(:before)', 'auto');
|
||||
test_source('selector(*)', 'auto');
|
||||
test_source('selector(.a)', 'auto');
|
||||
test_source('selector(.a, .b)', 'auto');
|
||||
|
||||
// CSSScrollTimelineRule.orientation
|
||||
|
||||
function test_orientation(specified, expected) {
|
||||
test_descriptor('orientation', specified, expected);
|
||||
}
|
||||
|
||||
test_orientation('auto');
|
||||
test_orientation('block');
|
||||
test_orientation('inline');
|
||||
test_orientation('horizontal');
|
||||
test_orientation('vertical');
|
||||
test_orientation(' vertical ', 'vertical');
|
||||
|
||||
test_orientation('', 'auto');
|
||||
test_orientation('foo', 'auto');
|
||||
test_orientation('10px', 'auto');
|
||||
test_orientation('red', 'auto');
|
||||
|
||||
// CSSScrollTimelineRule.scrollOffsets
|
||||
|
||||
function test_offsets(specified, expected) {
|
||||
test_descriptor('scroll-offsets', specified, expected);
|
||||
}
|
||||
|
||||
test_offsets('none');
|
||||
test_offsets(' none ', 'none');
|
||||
test_offsets('', 'none');
|
||||
test_offsets('red', 'none');
|
||||
test_offsets('#fff', 'none');
|
||||
test_offsets('unset', 'none');
|
||||
test_offsets('unknown(#foo)', 'none');
|
||||
test_offsets('start', 'none');
|
||||
test_offsets('end', 'none');
|
||||
test_offsets('3', 'none');
|
||||
test_offsets('selector(#foo) 3 start 10', 'none');
|
||||
test_offsets('0%, 100%, selector(.a)', 'none');
|
||||
test_offsets('selector(#foo) 3 end, start', 'none');
|
||||
|
||||
test_offsets('auto');
|
||||
test_offsets('10em');
|
||||
test_offsets('10%');
|
||||
test_offsets('calc(1px + 1%)', ['calc(1px + 1%)', 'calc(1% + 1px)']);
|
||||
test_offsets('selector(#foo)');
|
||||
test_offsets(' selector(#foo)', 'selector(#foo)');
|
||||
test_offsets('selector(#foo) start');
|
||||
test_offsets('selector(#foo) start 3');
|
||||
test_offsets('selector(#foo) 3');
|
||||
test_offsets('selector(#foo) 3.5');
|
||||
test_offsets('selector(#foo) end');
|
||||
test_offsets('selector(#foo) end 3');
|
||||
test_offsets('selector(#foo) 3 end', 'selector(#foo) end 3');
|
||||
test_offsets(' auto , auto ', 'auto, auto');
|
||||
test_offsets('10%, 100px');
|
||||
test_offsets('auto, 100%');
|
||||
test_offsets('0%, selector( #foo) 3 end ', "0%, selector(#foo) end 3");
|
||||
test_offsets('selector(#foo) end 3, selector(#bar)');
|
||||
test_offsets('0%, auto, selector(#foo) start, auto, selector(#bar) 12.3');
|
||||
|
||||
</script>
|
|
@ -1,10 +1,11 @@
|
|||
<!DOCTYPE HTML>
|
||||
<html class="reftest-wait">
|
||||
<title>The default scroll-timeline at rule in the iframe for print</title>
|
||||
<link rel="help" href="https://drafts.csswg.org/scroll-animations-1/#scroll-timeline-at-rule">
|
||||
<title>The default scroll() timeline in the iframe for print</title>
|
||||
<link rel="help" href="https://drafts.csswg.org/scroll-animations-1/#scroll-notation">
|
||||
<link rel="help" href="https://drafts.csswg.org/css-animations-2/#animation-timeline">
|
||||
<meta name="assert" content="CSS animation correctly updates values when using the default scroll-timeline at rule">
|
||||
<link rel="match" href="at-scroll-timeline-default-descriptors-iframe-ref.html">
|
||||
<meta name="assert" content="CSS animation correctly updates values when using the default scroll() timeline">
|
||||
<link rel="match" href="scroll-timeline-default-iframe-ref.html">
|
||||
<meta name="fuzzy" content="25;100">
|
||||
|
||||
<iframe id="target" width="400" height="400" srcdoc='
|
||||
<html>
|
||||
|
@ -13,11 +14,6 @@
|
|||
from { transform: translateY(0px); }
|
||||
to { transform: translateY(200px); }
|
||||
}
|
||||
@scroll-timeline test-timeline {
|
||||
source: auto;
|
||||
orientation: auto;
|
||||
scroll-offsets: none;
|
||||
}
|
||||
html {
|
||||
min-height: 100%;
|
||||
padding-bottom: 100px;
|
||||
|
@ -27,7 +23,7 @@
|
|||
height: 100px;
|
||||
background-color: green;
|
||||
animation: update 1s linear;
|
||||
animation-timeline: test-timeline;
|
||||
animation-timeline: scroll();
|
||||
}
|
||||
#covered {
|
||||
width: 100px;
|
|
@ -1,5 +1,5 @@
|
|||
<!DOCTYPE html>
|
||||
<title>Reference for default @scroll-timeline</title>
|
||||
<title>Reference for default scroll() timeline</title>
|
||||
<iframe width="400" height="400" srcdoc='
|
||||
<html>
|
||||
<style>
|
|
@ -1,10 +1,10 @@
|
|||
<!DOCTYPE HTML>
|
||||
<html class="reftest-wait">
|
||||
<title>The default scroll-timeline at rule in the iframe</title>
|
||||
<link rel="help" href="https://drafts.csswg.org/scroll-animations-1/#scroll-timeline-at-rule">
|
||||
<title>The default scroll() timeline in the iframe</title>
|
||||
<link rel="help" href="https://drafts.csswg.org/scroll-animations-1/#scroll-notation">
|
||||
<link rel="help" href="https://drafts.csswg.org/css-animations-2/#animation-timeline">
|
||||
<meta name="assert" content="CSS animation correctly updates values when using the default scroll-timeline at rule">
|
||||
<link rel="match" href="at-scroll-timeline-default-descriptors-iframe-ref.html">
|
||||
<meta name="assert" content="CSS animation correctly updates values when using the default scroll() timeline">
|
||||
<link rel="match" href="scroll-timeline-default-iframe-ref.html">
|
||||
|
||||
<iframe id="target" width="400" height="400" srcdoc='
|
||||
<html>
|
||||
|
@ -13,11 +13,6 @@
|
|||
from { transform: translateY(0px); }
|
||||
to { transform: translateY(200px); }
|
||||
}
|
||||
@scroll-timeline test-timeline {
|
||||
source: auto;
|
||||
orientation: auto;
|
||||
scroll-offsets: none;
|
||||
}
|
||||
html {
|
||||
min-height: 100%;
|
||||
padding-bottom: 100px;
|
||||
|
@ -27,7 +22,7 @@
|
|||
height: 100px;
|
||||
background-color: green;
|
||||
animation: update 1s linear;
|
||||
animation-timeline: test-timeline;
|
||||
animation-timeline: scroll();
|
||||
}
|
||||
#covered {
|
||||
width: 100px;
|
|
@ -1,10 +1,10 @@
|
|||
<!DOCTYPE HTML>
|
||||
<html class="reftest-wait">
|
||||
<title>The default scroll-timeline at rule</title>
|
||||
<link rel="help" href="https://drafts.csswg.org/scroll-animations-1/#scroll-timeline-at-rule">
|
||||
<title>The default scroll() timeline for print</title>
|
||||
<link rel="help" href="https://drafts.csswg.org/scroll-animations-1/#scroll-notation">
|
||||
<link rel="help" href="https://drafts.csswg.org/css-animations-2/#animation-timeline">
|
||||
<meta name="assert" content="CSS animation correctly updates values when using the default scroll-timeline at rule">
|
||||
<link rel="match" href="at-scroll-timeline-default-descriptors-ref.html">
|
||||
<meta name="assert" content="CSS animation correctly updates values when using the default scroll() timeline">
|
||||
<link rel="match" href="scroll-timeline-default-ref.html">
|
||||
|
||||
<style>
|
||||
@keyframes update {
|
||||
|
@ -12,12 +12,6 @@
|
|||
to { transform: translateY(200px); }
|
||||
}
|
||||
|
||||
@scroll-timeline test-timeline {
|
||||
source: auto;
|
||||
orientation: auto;
|
||||
scroll-offsets: none;
|
||||
}
|
||||
|
||||
html {
|
||||
min-height: 100%;
|
||||
padding-bottom: 100px;
|
||||
|
@ -28,7 +22,7 @@
|
|||
height: 100px;
|
||||
background-color: green;
|
||||
animation: update 1s linear;
|
||||
animation-timeline: test-timeline;
|
||||
animation-timeline: scroll();
|
||||
}
|
||||
|
||||
#covered {
|
||||
|
@ -45,17 +39,24 @@
|
|||
|
||||
<div id="box"></div>
|
||||
<div id="covered"></div>
|
||||
|
||||
<script src="/web-animations/testcommon.js"></script>
|
||||
<script>
|
||||
window.addEventListener('load', function() {
|
||||
document.documentElement.addEventListener('TestRendered', async () => {
|
||||
runTest();
|
||||
}, { once: true });
|
||||
|
||||
async function runTest() {
|
||||
const scroller = document.scrollingElement;
|
||||
|
||||
await waitForCompositorReady();
|
||||
|
||||
// Move the scroller to the halfway point.
|
||||
const maxScroll = scroller.scrollHeight - scroller.clientHeight;
|
||||
scroller.scrollTop = 0.5 * maxScroll;
|
||||
|
||||
window.requestAnimationFrame(() => {
|
||||
document.documentElement.classList.remove("reftest-wait");
|
||||
});
|
||||
});
|
||||
await waitForNextFrame();
|
||||
await waitForNextFrame();
|
||||
|
||||
document.documentElement.classList.remove("reftest-wait");
|
||||
}
|
||||
</script>
|
|
@ -0,0 +1,63 @@
|
|||
<html class="reftest-wait">
|
||||
<title>The default scroll() timeline in quirks mode</title>
|
||||
<link rel="help" href="https://drafts.csswg.org/scroll-animations-1/#scroll-notation">
|
||||
<link rel="help" href="https://drafts.csswg.org/css-animations-2/#animation-timeline">
|
||||
<meta name="assert" content="CSS animation correctly updates values when using the default scroll() timeline">
|
||||
<link rel="match" href="scroll-timeline-default-ref.html">
|
||||
|
||||
<style>
|
||||
@keyframes update {
|
||||
from { transform: translateY(0px); }
|
||||
to { transform: translateY(200px); }
|
||||
}
|
||||
|
||||
html {
|
||||
min-height: 100%;
|
||||
padding-bottom: 100px;
|
||||
}
|
||||
|
||||
#box {
|
||||
width: 100px;
|
||||
height: 100px;
|
||||
background-color: green;
|
||||
animation: update 1s linear;
|
||||
animation-timeline: scroll();
|
||||
}
|
||||
|
||||
#covered {
|
||||
width: 100px;
|
||||
height: 100px;
|
||||
background-color: red;
|
||||
}
|
||||
|
||||
* {
|
||||
margin-top: 0px;
|
||||
margin-bottom: 0px;
|
||||
}
|
||||
</style>
|
||||
|
||||
<div id="box"></div>
|
||||
<div id="covered"></div>
|
||||
<script src="/web-animations/testcommon.js"></script>
|
||||
<script>
|
||||
document.documentElement.addEventListener('TestRendered', async () => {
|
||||
runTest();
|
||||
}, { once: true });
|
||||
|
||||
async function runTest() {
|
||||
const scroller = document.scrollingElement;
|
||||
|
||||
await waitForCompositorReady();
|
||||
|
||||
// Move the scroller to the halfway point. Then advance to the next frame
|
||||
// to pick up the new timeline time.
|
||||
const maxScroll = scroller.scrollHeight - scroller.clientHeight;
|
||||
scroller.scrollTop = 0.5 * maxScroll;
|
||||
|
||||
await waitForNextFrame();
|
||||
await waitForNextFrame();
|
||||
|
||||
document.documentElement.classList.remove("reftest-wait");
|
||||
}
|
||||
|
||||
</script>
|
|
@ -1,5 +1,5 @@
|
|||
<!DOCTYPE html>
|
||||
<title>Reference for default @scroll-timeline</title>
|
||||
<title>Reference for default scroll() timeline</title>
|
||||
<style>
|
||||
html {
|
||||
min-height: 100%;
|
|
@ -1,5 +1,5 @@
|
|||
<!DOCTYPE html>
|
||||
<title>Reference for default @scroll-timeline with vertical-rl</title>
|
||||
<title>Reference for default scroll() timeline with vertical-rl</title>
|
||||
<meta name="viewport" content="width=device-width,initial-scale=1,minimum-scale=1">
|
||||
<style>
|
||||
html {
|
|
@ -1,12 +1,12 @@
|
|||
<!DOCTYPE HTML>
|
||||
<html class="reftest-wait">
|
||||
<title>The default scroll-timeline at rule with writing-mode:vertical-rl</title>
|
||||
<title>The default scroll() timeline with writing-mode:vertical-rl</title>
|
||||
<meta name="viewport" content="width=device-width,initial-scale=1,minimum-scale=1">
|
||||
<link rel="help" href="https://drafts.csswg.org/scroll-animations-1/#scroll-timeline-at-rule">
|
||||
<link rel="help" href="https://drafts.csswg.org/scroll-animations-1/#scroll-notation">
|
||||
<link rel="help" href="https://drafts.csswg.org/css-animations-2/#animation-timeline">
|
||||
<meta name="assert" content="CSS animation correctly updates values when using
|
||||
the default scroll-timeline at rule with writing-mode:vertical-rl">
|
||||
<link rel="match" href="at-scroll-timeline-default-descriptors-writing-mode-rl-ref.html">
|
||||
the default scroll() timeline with writing-mode:vertical-rl">
|
||||
<link rel="match" href="scroll-timeline-default-writing-mode-rl-ref.html">
|
||||
|
||||
<style>
|
||||
@keyframes update {
|
||||
|
@ -14,12 +14,6 @@
|
|||
to { transform: translateX(-200px); }
|
||||
}
|
||||
|
||||
@scroll-timeline test-timeline {
|
||||
source: auto;
|
||||
orientation: auto;
|
||||
scroll-offsets: none;
|
||||
}
|
||||
|
||||
html {
|
||||
min-block-size: 100%;
|
||||
padding-block-end: 100px;
|
||||
|
@ -31,7 +25,7 @@
|
|||
height: 100px;
|
||||
background-color: green;
|
||||
animation: update 1s linear;
|
||||
animation-timeline: test-timeline;
|
||||
animation-timeline: scroll();
|
||||
}
|
||||
|
||||
#covered {
|
||||
|
@ -48,16 +42,24 @@
|
|||
<div id="box"></div>
|
||||
<div id="covered"></div>
|
||||
|
||||
<script src="/web-animations/testcommon.js"></script>
|
||||
<script>
|
||||
window.addEventListener('load', function() {
|
||||
document.documentElement.addEventListener('TestRendered', async () => {
|
||||
runTest();
|
||||
}, { once: true });
|
||||
|
||||
async function runTest() {
|
||||
const scroller = document.scrollingElement;
|
||||
|
||||
await waitForCompositorReady();
|
||||
|
||||
// Move the scroller to the halfway point.
|
||||
const maxScroll = scroller.scrollWidth - scroller.clientWidth;
|
||||
scroller.scrollLeft = -0.5 * maxScroll;
|
||||
|
||||
window.requestAnimationFrame(() => {
|
||||
document.documentElement.classList.remove("reftest-wait");
|
||||
});
|
||||
});
|
||||
await waitForNextFrame();
|
||||
await waitForNextFrame();
|
||||
|
||||
document.documentElement.classList.remove("reftest-wait");
|
||||
}
|
||||
</script>
|
|
@ -1,10 +1,10 @@
|
|||
<!DOCTYPE HTML>
|
||||
<html class="reftest-wait">
|
||||
<title>The default scroll-timeline at rule for print</title>
|
||||
<link rel="help" href="https://drafts.csswg.org/scroll-animations-1/#scroll-timeline-at-rule">
|
||||
<title>The default scroll() timeline</title>
|
||||
<link rel="help" href="https://drafts.csswg.org/scroll-animations-1/#scroll-notation">
|
||||
<link rel="help" href="https://drafts.csswg.org/css-animations-2/#animation-timeline">
|
||||
<meta name="assert" content="CSS animation correctly updates values when using the default scroll-timeline at rule">
|
||||
<link rel="match" href="at-scroll-timeline-default-descriptors-ref.html">
|
||||
<meta name="assert" content="CSS animation correctly updates values when using the default scroll() timeline">
|
||||
<link rel="match" href="scroll-timeline-default-ref.html">
|
||||
|
||||
<style>
|
||||
@keyframes update {
|
||||
|
@ -12,12 +12,6 @@
|
|||
to { transform: translateY(200px); }
|
||||
}
|
||||
|
||||
@scroll-timeline test-timeline {
|
||||
source: auto;
|
||||
orientation: auto;
|
||||
scroll-offsets: none;
|
||||
}
|
||||
|
||||
html {
|
||||
min-height: 100%;
|
||||
padding-bottom: 100px;
|
||||
|
@ -28,7 +22,7 @@
|
|||
height: 100px;
|
||||
background-color: green;
|
||||
animation: update 1s linear;
|
||||
animation-timeline: test-timeline;
|
||||
animation-timeline: scroll();
|
||||
}
|
||||
|
||||
#covered {
|
||||
|
@ -46,16 +40,24 @@
|
|||
<div id="box"></div>
|
||||
<div id="covered"></div>
|
||||
|
||||
<script src="/web-animations/testcommon.js"></script>
|
||||
<script>
|
||||
window.addEventListener('load', function() {
|
||||
document.documentElement.addEventListener('TestRendered', async () => {
|
||||
runTest();
|
||||
}, { once: true });
|
||||
|
||||
async function runTest() {
|
||||
const scroller = document.scrollingElement;
|
||||
|
||||
await waitForCompositorReady();
|
||||
|
||||
// Move the scroller to the halfway point.
|
||||
const maxScroll = scroller.scrollHeight - scroller.clientHeight;
|
||||
scroller.scrollTop = 0.5 * maxScroll;
|
||||
|
||||
window.requestAnimationFrame(() => {
|
||||
document.documentElement.classList.remove("reftest-wait");
|
||||
});
|
||||
});
|
||||
await waitForNextFrame();
|
||||
await waitForNextFrame();
|
||||
|
||||
document.documentElement.classList.remove("reftest-wait");
|
||||
}
|
||||
</script>
|
|
@ -0,0 +1,29 @@
|
|||
<!-- Quirks mode -->
|
||||
<title>Tests the document scroller in quirks mode</title>
|
||||
<link rel="help" href="https://drafts.csswg.org/scroll-animations-1/#scroll-notation">
|
||||
<link rel="help" href="https://bugs.chromium.org/p/chromium/issues/detail?id=1180575">
|
||||
<link rel="author" href="mailto:andruud@chromium.org">
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
<script src="/scroll-animations/scroll-timelines/testcommon.js"></script>
|
||||
<script src="/css/css-animations/support/testcommon.js"></script>
|
||||
<script src="support/testcommon.js"></script>
|
||||
<style>
|
||||
@keyframes anim {
|
||||
from { z-index: 100; }
|
||||
to { z-index: 100; }
|
||||
}
|
||||
#element {
|
||||
animation: anim forwards scroll(root);
|
||||
}
|
||||
</style>
|
||||
<div id=element></div>
|
||||
|
||||
<script>
|
||||
'use strict';
|
||||
|
||||
promise_test(async () => {
|
||||
await waitForCSSScrollTimelineStyle();
|
||||
assert_equals(getComputedStyle(element).zIndex, "100");
|
||||
});
|
||||
</script>
|
|
@ -1,15 +1,17 @@
|
|||
<!DOCTYPE html>
|
||||
<link rel="help" src="https://drafts.csswg.org/scroll-animations-1/#scroll-timeline-at-rule">
|
||||
<meta name="viewport" content="width=device-width,initial-scale=1,minimum-scale=1">
|
||||
<link rel="help" src="https://drafts.csswg.org/scroll-animations-1/#scroll-timelines">
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
<script src="/web-animations/testcommon.js"></script>
|
||||
<script src="support/testcommon.js"></script>
|
||||
<style>
|
||||
#scrollers > div {
|
||||
overflow: scroll;
|
||||
main > div {
|
||||
overflow: hidden;
|
||||
width: 100px;
|
||||
height: 100px;
|
||||
}
|
||||
#scrollers > div > div {
|
||||
main > div > div {
|
||||
height: 200px;
|
||||
}
|
||||
@keyframes expand {
|
||||
|
@ -27,11 +29,11 @@
|
|||
animation-timing-function: steps(10, end);
|
||||
}
|
||||
</style>
|
||||
<div id=scrollers>
|
||||
<main>
|
||||
<div id=scroller1><div></div></div>
|
||||
<div id=scroller2><div></div></div>
|
||||
</div>
|
||||
<div id=container></div>
|
||||
<div id=container></div>
|
||||
</main>
|
||||
<script>
|
||||
// Force layout of scrollers.
|
||||
scroller1.offsetTop;
|
||||
|
@ -49,35 +51,6 @@
|
|||
return element;
|
||||
}
|
||||
|
||||
function insertSheet(text) {
|
||||
let style = document.createElement('style');
|
||||
style.textContent = text;
|
||||
container.append(style);
|
||||
return style;
|
||||
}
|
||||
|
||||
// Insert an @scroll-timeline rule given 'options', where each option
|
||||
// has a reasonable default.
|
||||
function insertScrollTimeline(options) {
|
||||
if (typeof(options) == 'undefined')
|
||||
options = {};
|
||||
if (typeof(options.name) == 'undefined')
|
||||
options.name = 'timeline';
|
||||
if (typeof(options.source) == 'undefined')
|
||||
options.source = 'selector(#scroller1)';
|
||||
if (typeof(options.start) == 'undefined')
|
||||
options.start = '0px';
|
||||
if (typeof(options.end) == 'undefined')
|
||||
options.end = '100px';
|
||||
return insertSheet(`
|
||||
@scroll-timeline ${options.name} {
|
||||
source: ${options.source};
|
||||
start: ${options.start};
|
||||
end: ${options.end};
|
||||
}
|
||||
`);
|
||||
}
|
||||
|
||||
// Runs a test with dynamically added/removed elements or CSS rules.
|
||||
// Each test is instantiated twice: once for the initial style resolve where
|
||||
// the DOM change was effectuated, and once after scrolling.
|
||||
|
@ -91,13 +64,16 @@
|
|||
} finally {
|
||||
while (container.firstChild)
|
||||
container.firstChild.remove();
|
||||
scroller1.style = '';
|
||||
scroller2.style = '';
|
||||
}
|
||||
}, description);
|
||||
};
|
||||
|
||||
// Verify that the computed style is as expected immediately after the
|
||||
// rule change took place.
|
||||
// Verify that the computed style is as expected after a full frame update
|
||||
// following the rule change took place.
|
||||
instantiate(async (element, expected) => {
|
||||
await waitForCSSScrollTimelineStyle();
|
||||
assert_equals(getComputedStyle(element).width, expected);
|
||||
}, description + ' [immediate]');
|
||||
|
||||
|
@ -120,43 +96,57 @@
|
|||
await assert_width(element, '100px');
|
||||
|
||||
// Switch to scroll timeline.
|
||||
let sheet1 = insertScrollTimeline();
|
||||
let sheet2 = insertSheet('#element { animation-timeline: timeline; }');
|
||||
scroller1.style.scrollTimelineName = 'timeline';
|
||||
element.style.animationTimeline = 'timeline';
|
||||
await assert_width(element, '120px');
|
||||
|
||||
// Switching from ScrollTimeline -> DocumentTimeline should preserve
|
||||
// current time.
|
||||
sheet1.remove();
|
||||
sheet2.remove();
|
||||
scroller1.style = '';
|
||||
element.style = '';
|
||||
await assert_width(element, '120px');
|
||||
}, 'Switching between document and scroll timelines');
|
||||
|
||||
dynamic_rule_test(async (t, assert_width) => {
|
||||
let element = insertElement();
|
||||
|
||||
// Note: #scroller1 is at 20%, and #scroller2 is at 40%.
|
||||
insertScrollTimeline({name: 'timeline1', source: 'selector(#scroller1)'});
|
||||
insertScrollTimeline({name: 'timeline2', source: 'selector(#scroller2)'});
|
||||
// Flush style and create the animation with play pending.
|
||||
getComputedStyle(element).animation;
|
||||
|
||||
insertSheet(`
|
||||
.tl1 { animation-timeline: timeline1; }
|
||||
.tl2 { animation-timeline: timeline2; }
|
||||
`);
|
||||
let anim = element.getAnimations()[0];
|
||||
assert_true(anim.pending, "The animation is in play pending");
|
||||
|
||||
// Switch to scroll timeline for a pending animation.
|
||||
scroller1.style.scrollTimelineName = 'timeline';
|
||||
element.style.animationTimeline = 'timeline';
|
||||
|
||||
await anim.ready;
|
||||
assert_false(anim.pending, "The animation is not pending");
|
||||
|
||||
await assert_width(element, '120px');
|
||||
}, 'Switching pending animation from document to scroll timelines');
|
||||
|
||||
dynamic_rule_test(async (t, assert_width) => {
|
||||
let element = insertElement();
|
||||
|
||||
// Note: #scroller1 is at 20%, and #scroller2 is at 40%.
|
||||
scroller1.style.scrollTimelineName = 'timeline1';
|
||||
scroller2.style.scrollTimelineName = 'timeline2';
|
||||
|
||||
await assert_width(element, '100px');
|
||||
|
||||
element.classList.add('tl1');
|
||||
element.style.animationTimeline = 'timeline1';
|
||||
await assert_width(element, '120px');
|
||||
|
||||
element.classList.add('tl2');
|
||||
element.style.animationTimeline = 'timeline2';
|
||||
await assert_width(element, '140px');
|
||||
|
||||
element.classList.remove('tl2');
|
||||
element.style.animationTimeline = 'timeline1';
|
||||
await assert_width(element, '120px');
|
||||
|
||||
// Switching from ScrollTimeline -> DocumentTimeline should preserve
|
||||
// current time.
|
||||
element.classList.remove('tl1');
|
||||
element.style.animationTimeline = '';
|
||||
await assert_width(element, '120px');
|
||||
|
||||
}, 'Changing computed value of animation-timeline changes effective timeline');
|
||||
|
@ -164,124 +154,95 @@
|
|||
dynamic_rule_test(async (t, assert_width) => {
|
||||
let element = insertElement();
|
||||
|
||||
insertScrollTimeline({source: 'selector(#scroller1)'});
|
||||
|
||||
insertSheet(`
|
||||
.scroll { animation-timeline: timeline; }
|
||||
.none { animation-timeline: none; }
|
||||
`);
|
||||
scroller1.style.scrollTimelineName = 'timeline';
|
||||
|
||||
// DocumentTimeline applies by default.
|
||||
await assert_width(element, '100px');
|
||||
|
||||
// DocumentTimeline -> none
|
||||
element.classList.add('none');
|
||||
element.style.animationTimeline = 'none';
|
||||
await assert_width(element, '0px');
|
||||
|
||||
// none -> DocumentTimeline
|
||||
element.classList.remove('none');
|
||||
element.style.animationTimeline = '';
|
||||
await assert_width(element, '100px');
|
||||
|
||||
// DocumentTimeline -> ScrollTimeline
|
||||
element.classList.add('scroll');
|
||||
element.style.animationTimeline = 'timeline';
|
||||
await assert_width(element, '120px');
|
||||
|
||||
// ScrollTimeline -> none
|
||||
element.classList.add('none');
|
||||
await assert_width(element, '0px');
|
||||
element.style.animationTimeline = 'none';
|
||||
await assert_width(element, '120px');
|
||||
|
||||
// none -> ScrollTimeline
|
||||
element.classList.remove('none');
|
||||
element.style.animationTimeline = 'timeline';
|
||||
await assert_width(element, '120px');
|
||||
}, 'Changing to/from animation-timeline:none');
|
||||
|
||||
|
||||
dynamic_rule_test(async (t, assert_width) => {
|
||||
let element = insertElement();
|
||||
insertSheet('#element { animation-timeline: timeline; }');
|
||||
|
||||
element.style.animationTimeline = 'timeline';
|
||||
|
||||
// Unknown animation-timeline, current time held at zero.
|
||||
await assert_width(element, '100px');
|
||||
|
||||
insertScrollTimeline({source: 'selector(#scroller1)'});
|
||||
scroller1.style.scrollTimelineName = 'timeline';
|
||||
await assert_width(element, '120px');
|
||||
|
||||
insertScrollTimeline({source: 'selector(#scroller2)'});
|
||||
scroller2.style.scrollTimelineName = 'timeline';
|
||||
await assert_width(element, '140px');
|
||||
}, 'Changing the source descriptor switches effective timeline');
|
||||
}, 'Changing scroll-timeline on preceding elements affects target element');
|
||||
|
||||
|
||||
dynamic_rule_test(async (t, assert_width) => {
|
||||
let element = insertElement();
|
||||
insertSheet('#element { animation-timeline: timeline; }');
|
||||
|
||||
// Unknown animation-timeline, current time held at zero.
|
||||
await assert_width(element, '100px');
|
||||
|
||||
insertScrollTimeline({start: '0px'});
|
||||
await assert_width(element, '120px');
|
||||
|
||||
insertScrollTimeline({start: '50px'});
|
||||
await assert_width(element, '0px');
|
||||
}, 'Changing the start descriptor switches effective timeline');
|
||||
|
||||
dynamic_rule_test(async (t, assert_width) => {
|
||||
let element = insertElement();
|
||||
insertSheet('#element { animation-timeline: timeline; }');
|
||||
|
||||
// Unknown animation-timeline, current time held at zero.
|
||||
await assert_width(element, '100px');
|
||||
|
||||
insertScrollTimeline({end: '100px'});
|
||||
await assert_width(element, '120px');
|
||||
|
||||
insertScrollTimeline({end: '10px'});
|
||||
await assert_width(element, '0px');
|
||||
}, 'Changing the end descriptor switches effective timeline');
|
||||
|
||||
dynamic_rule_test(async (t, assert_width) => {
|
||||
let element = insertElement();
|
||||
let reverse = insertSheet('#element { animation-direction: reverse; }');
|
||||
insertSheet('#element { animation-timeline: timeline; }');
|
||||
element.style.animationDirection = 'reverse';
|
||||
element.style.animationTimeline = 'timeline';
|
||||
|
||||
// Unknown animation-timeline, current time held at zero.
|
||||
await assert_width(element, '200px');
|
||||
|
||||
// Note: #scroller1 is at 20%.
|
||||
insertScrollTimeline({source: 'selector(#scroller1)'});
|
||||
scroller1.style.scrollTimelineName = 'timeline';
|
||||
await assert_width(element, '180px');
|
||||
|
||||
// Note: #scroller1 is at 40%.
|
||||
insertScrollTimeline({source: 'selector(#scroller2)'});
|
||||
// Note: #scroller2 is at 40%.
|
||||
scroller2.style.scrollTimelineName = 'timeline';
|
||||
await assert_width(element, '160px');
|
||||
|
||||
reverse.remove();
|
||||
element.style.animationDirection = '';
|
||||
await assert_width(element, '140px');
|
||||
}, 'Reverse animation direction');
|
||||
|
||||
dynamic_rule_test(async (t, assert_width) => {
|
||||
let element = insertElement();
|
||||
insertSheet('#element { animation-timeline: timeline; }');
|
||||
element.style.animationTimeline = 'timeline';
|
||||
|
||||
// Unknown animation-timeline, current time held at zero.
|
||||
await assert_width(element, '100px');
|
||||
|
||||
// Note: #scroller1 is at 20%.
|
||||
insertScrollTimeline({source: 'selector(#scroller1)'});
|
||||
scroller1.style.scrollTimelineName = 'timeline';
|
||||
await assert_width(element, '120px');
|
||||
|
||||
let paused = insertSheet('#element { animation-play-state: paused; }');
|
||||
element.style.animationPlayState = 'paused';
|
||||
|
||||
// We should still be at the same position after pausing.
|
||||
await assert_width(element, '120px');
|
||||
|
||||
// Note: #scroller1 is at 40%.
|
||||
insertScrollTimeline({source: 'selector(#scroller2)'});
|
||||
// Note: #scroller2 is at 40%.
|
||||
scroller2.style.scrollTimelineName = 'timeline';
|
||||
|
||||
// Even when switching timelines, we should be at the same position until
|
||||
// we unpause.
|
||||
await assert_width(element, '120px');
|
||||
|
||||
// Unpausing should synchronize to the scroll position.
|
||||
paused.remove();
|
||||
element.style.animationPlayState = '';
|
||||
await assert_width(element, '140px');
|
||||
}, 'Switching timelines while paused');
|
||||
|
||||
|
@ -289,20 +250,18 @@
|
|||
let element = insertElement();
|
||||
|
||||
// Note: #scroller1 is at 20%.
|
||||
insertScrollTimeline({source: 'selector(#scroller1)'});
|
||||
scroller1.style.scrollTimelineName = 'timeline';
|
||||
|
||||
await assert_width(element, '100px');
|
||||
|
||||
insertSheet(`#element {
|
||||
animation-timeline: timeline;
|
||||
animation-play-state: paused;
|
||||
}`);
|
||||
element.style.animationTimeline = 'timeline';
|
||||
element.style.animationPlayState = 'paused';
|
||||
|
||||
// Pausing should happen before the timeline is modified. (Tentative).
|
||||
// https://github.com/w3c/csswg-drafts/issues/5653
|
||||
await assert_width(element, '100px');
|
||||
|
||||
insertSheet('#element { animation-play-state: running; }');
|
||||
element.style.animationPlayState = 'running';
|
||||
await assert_width(element, '120px');
|
||||
}, 'Switching timelines and pausing at the same time');
|
||||
</script>
|
|
@ -1,5 +1,5 @@
|
|||
<!DOCTYPE html>
|
||||
<title>Reference for default @scroll-timeline</title>
|
||||
<title>Reference for the default scroll() timeline</title>
|
||||
<style>
|
||||
html {
|
||||
min-height: 100%;
|
|
@ -1,12 +1,12 @@
|
|||
<!DOCTYPE html>
|
||||
<html class="reftest-wait">
|
||||
<title>The default scroll-timeline at rule when the frame size changed</title>
|
||||
<link rel="help" href="https://drafts.csswg.org/scroll-animations-1/#scroll-timeline-at-rule">
|
||||
<title>The default scroll() timeline when the frame size changed</title>
|
||||
<link rel="help" href="https://drafts.csswg.org/scroll-animations-1/#scroll-notation">
|
||||
<link rel="help" href="https://drafts.csswg.org/css-animations-2/#animation-timeline">
|
||||
<meta name="assert" content="CSS animation correctly updates values when using
|
||||
the default scroll-timeline at rule and update the
|
||||
the default scroll() timeline and update the
|
||||
frame size">
|
||||
<link rel="match" href="at-scroll-timeline-frame-size-changed-ref.html">
|
||||
<link rel="match" href="scroll-timeline-frame-size-changed-ref.html">
|
||||
|
||||
<style>
|
||||
@keyframes update {
|
||||
|
@ -14,12 +14,6 @@
|
|||
to { transform: translateY(200px); }
|
||||
}
|
||||
|
||||
@scroll-timeline test-timeline {
|
||||
source: auto;
|
||||
orientation: auto;
|
||||
scroll-offsets: none;
|
||||
}
|
||||
|
||||
html {
|
||||
min-height: 100%;
|
||||
padding-bottom: 100px;
|
||||
|
@ -30,7 +24,7 @@
|
|||
height: 100px;
|
||||
background-color: green;
|
||||
animation: update 1s linear;
|
||||
animation-timeline: test-timeline;
|
||||
animation-timeline: scroll();
|
||||
}
|
||||
|
||||
#covered {
|
||||
|
@ -48,21 +42,26 @@
|
|||
<div id="box"></div>
|
||||
<div id="covered"></div>
|
||||
|
||||
<script src="/web-animations/testcommon.js"></script>
|
||||
<script>
|
||||
window.addEventListener('load', function() {
|
||||
document.documentElement.addEventListener('TestRendered', async () => {
|
||||
runTest();
|
||||
}, { once: true });
|
||||
|
||||
async function runTest() {
|
||||
const scroller = document.scrollingElement;
|
||||
|
||||
await waitForCompositorReady();
|
||||
|
||||
// Move the scroller to the 25% point.
|
||||
const maxScroll = scroller.scrollHeight - scroller.clientHeight;
|
||||
scroller.scrollTop = 0.25 * maxScroll;
|
||||
await waitForNextFrame();
|
||||
|
||||
window.requestAnimationFrame(() => {
|
||||
// Update scroll range to make the current position become 50% point.
|
||||
scroller.style.paddingBottom = "50px";
|
||||
// Update scroll range to make the current position become 50% point.
|
||||
scroller.style.paddingBottom = "50px";
|
||||
await waitForNextFrame();
|
||||
|
||||
window.requestAnimationFrame(() => {
|
||||
document.documentElement.classList.remove("reftest-wait");
|
||||
});
|
||||
});
|
||||
});
|
||||
document.documentElement.classList.remove("reftest-wait");
|
||||
}
|
||||
</script>
|
|
@ -0,0 +1,71 @@
|
|||
<!DOCTYPE html>
|
||||
<title>scroll-timeline and container queries</title>
|
||||
<link rel="help" src="https://drafts.csswg.org/scroll-animations-1/#scroll-timeline-shorthand">
|
||||
<link rel="help" src="https://drafts.csswg.org/css-contain-3/#container-queries">
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
<script src="/web-animations/testcommon.js"></script>
|
||||
<script src="support/testcommon.js"></script>
|
||||
<style>
|
||||
#outer {
|
||||
height: 100px;
|
||||
width: 150px;
|
||||
}
|
||||
|
||||
#container {
|
||||
container-type: size;
|
||||
}
|
||||
|
||||
#scroller {
|
||||
overflow: auto;
|
||||
width: auto;
|
||||
height: 100px;
|
||||
}
|
||||
#scroller > div {
|
||||
height: 200px;
|
||||
}
|
||||
|
||||
/* This does not apply initially. */
|
||||
@container (width > 200px) {
|
||||
#scroller {
|
||||
scroll-timeline: timeline;
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes expand {
|
||||
from { background-color: rgb(100, 100, 100); }
|
||||
to { background-color: rgb(200, 200, 200); }
|
||||
}
|
||||
#element {
|
||||
height: 10px;
|
||||
width: 10px;
|
||||
animation: expand 10s linear timeline;
|
||||
background-color: rgb(0, 0, 0);
|
||||
}
|
||||
</style>
|
||||
<div id=outer>
|
||||
<div id=container>
|
||||
<div id=scroller>
|
||||
<div></div>
|
||||
</div>
|
||||
<div id=element>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<script>
|
||||
promise_test(async (t) => {
|
||||
element.offsetTop;
|
||||
scroller.scrollTop = 50;
|
||||
await waitForNextFrame();
|
||||
// Unknown timeline, time held at zero.
|
||||
assert_equals(getComputedStyle(element).backgroundColor, 'rgb(100, 100, 100)');
|
||||
// This causes the timeline to be created.
|
||||
outer.style.width = '250px';
|
||||
// Check value with getComputedStyle immediately, which is the unanimated
|
||||
// value since the scroll timeline is inactive before the next frame.
|
||||
assert_equals(getComputedStyle(element).backgroundColor, 'rgb(0, 0, 0)');
|
||||
// Also check value after one frame.
|
||||
await waitForNextFrame();
|
||||
assert_equals(getComputedStyle(element).backgroundColor, 'rgb(150, 150, 150)');
|
||||
}, 'Timeline appearing via container queries');
|
||||
</script>
|
|
@ -1,6 +1,5 @@
|
|||
<!DOCTYPE html>
|
||||
<link rel="help" src="https://drafts.csswg.org/scroll-animations-1/#scroll-timeline-at-rule">
|
||||
<link rel="help" src="https://drafts.csswg.org/scroll-animations-1/#phase-algorithm">
|
||||
<link rel="help" src="https://drafts.csswg.org/scroll-animations-1/#scroll-timelines">
|
||||
<link rel="help" src="https://drafts.csswg.org/scroll-animations-1/#avoiding-cycles">
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
|
@ -24,24 +23,18 @@
|
|||
animation-timeline: timeline;
|
||||
}
|
||||
</style>
|
||||
<div id="container"></div>
|
||||
<div id=element></div>
|
||||
<div id="container">
|
||||
<div id=element></div>
|
||||
</div>
|
||||
<script>
|
||||
|
||||
promise_test(async (t) => {
|
||||
let div = document.createElement('div');
|
||||
div.setAttribute('id', 'scroller');
|
||||
div.style.scrollTimeline = 'timeline';
|
||||
div.innerHTML = '<div id=contents></div>';
|
||||
try {
|
||||
container.innerHTML = `
|
||||
<div id=scroller>
|
||||
<div id=contents></div>
|
||||
</div>
|
||||
<style>
|
||||
@scroll-timeline timeline {
|
||||
source: selector(#scroller);
|
||||
start: 0px;
|
||||
end: 100px;
|
||||
}
|
||||
</style>
|
||||
`;
|
||||
container.insertBefore(div, element);
|
||||
|
||||
// The source has no layout box at the time the scroll timeline is created.
|
||||
assert_equals(getComputedStyle(element).width, '0px');
|
||||
|
@ -51,7 +44,7 @@ promise_test(async (t) => {
|
|||
// The timeline should now be active, and the animation should apply:
|
||||
assert_equals(getComputedStyle(element).width, '100px');
|
||||
} finally {
|
||||
container.innerHTML = '';
|
||||
div.remove();
|
||||
}
|
||||
}, 'Animation does not apply when timeline is initially inactive');
|
||||
|
|
@ -1,5 +1,5 @@
|
|||
<!DOCTYPE html>
|
||||
<title>Reference for @scroll-timeline with inline orientation</title>
|
||||
<title>Reference for scroll timeline with inline orientation and root scroller</title>
|
||||
<meta name="viewport" content="width=device-width,initial-scale=1,minimum-scale=1">
|
||||
<style>
|
||||
html {
|
|
@ -1,12 +1,12 @@
|
|||
<!DOCTYPE HTML>
|
||||
<html class="reftest-wait">
|
||||
<title>The scroll-timeline at rule with inline orientation and default source</title>
|
||||
<title>Scroll timeline with inline orientation and root scroller</title>
|
||||
<meta name="viewport" content="width=device-width,initial-scale=1,minimum-scale=1">
|
||||
<link rel="help" href="https://drafts.csswg.org/scroll-animations-1/#scroll-timeline-at-rule">
|
||||
<link rel="help" href="https://drafts.csswg.org/scroll-animations-1/#scroll-notation">
|
||||
<link rel="help" href="https://drafts.csswg.org/scroll-animations-1/#descdef-scroll-timeline-orientation">
|
||||
<link rel="help" href="https://drafts.csswg.org/css-animations-2/#animation-timeline">
|
||||
<meta name="assert" content="CSS animation correctly updates values when using the inline orientation">
|
||||
<link rel="match" href="at-scroll-timeline-inline-orientation-ref.html">
|
||||
<link rel="match" href="scroll-timeline-inline-orientation-ref.html">
|
||||
|
||||
<style>
|
||||
@keyframes update {
|
||||
|
@ -14,12 +14,6 @@
|
|||
to { transform: translateX(200px); }
|
||||
}
|
||||
|
||||
@scroll-timeline test-timeline {
|
||||
source: auto;
|
||||
orientation: inline;
|
||||
scroll-offsets: none;
|
||||
}
|
||||
|
||||
html {
|
||||
min-width: 100%;
|
||||
padding-right: 100px;
|
||||
|
@ -31,7 +25,7 @@
|
|||
height: 100px;
|
||||
background-color: green;
|
||||
animation: update 1s linear;
|
||||
animation-timeline: test-timeline;
|
||||
animation-timeline: scroll(inline root);
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
|
@ -51,16 +45,24 @@
|
|||
<div id="box"></div>
|
||||
<div id="covered"></div>
|
||||
|
||||
<script src="/web-animations/testcommon.js"></script>
|
||||
<script>
|
||||
window.addEventListener('load', function() {
|
||||
document.documentElement.addEventListener('TestRendered', async () => {
|
||||
runTest();
|
||||
}, { once: true });
|
||||
|
||||
async function runTest() {
|
||||
const scroller = document.scrollingElement;
|
||||
|
||||
await waitForCompositorReady();
|
||||
|
||||
// Move the scroller to the halfway point.
|
||||
const maxScroll = scroller.scrollWidth - scroller.clientWidth;
|
||||
scroller.scrollLeft = 0.5 * maxScroll;
|
||||
|
||||
window.requestAnimationFrame(() => {
|
||||
document.documentElement.classList.remove("reftest-wait");
|
||||
});
|
||||
});
|
||||
await waitForNextFrame();
|
||||
await waitForNextFrame();
|
||||
|
||||
document.documentElement.classList.remove("reftest-wait");
|
||||
}
|
||||
</script>
|
|
@ -14,12 +14,6 @@
|
|||
from { height: 100px; }
|
||||
to { height: 100px; }
|
||||
}
|
||||
@scroll-timeline timeline1 {
|
||||
source: selector(#scroller1);
|
||||
}
|
||||
@scroll-timeline timeline2 {
|
||||
source: selector(#scroller2);
|
||||
}
|
||||
main {
|
||||
height: 0px;
|
||||
overflow: hidden;
|
||||
|
@ -40,18 +34,19 @@
|
|||
animation: expand_height 10s timeline2;
|
||||
}
|
||||
</style>
|
||||
<main id=main></main>
|
||||
<div id=element1></div>
|
||||
<div>
|
||||
<div id=element2></div>
|
||||
</div>
|
||||
<main id=main>
|
||||
<div id=element1></div>
|
||||
<div>
|
||||
<div id=element2></div>
|
||||
</div>
|
||||
</main>
|
||||
<script>
|
||||
function insertScroller(id) {
|
||||
function insertScroller(timeline_name) {
|
||||
let scroller = document.createElement('div');
|
||||
scroller.setAttribute('id', id);
|
||||
scroller.setAttribute('class', 'scroller');
|
||||
scroller.classList.add('scroller');
|
||||
scroller.style.scrollTimeline = timeline_name;
|
||||
scroller.append(document.createElement('div'));
|
||||
main.append(scroller);
|
||||
main.insertBefore(scroller, element1);
|
||||
}
|
||||
|
||||
promise_test(async () => {
|
||||
|
@ -60,15 +55,15 @@
|
|||
let events1 = [];
|
||||
let events2 = [];
|
||||
|
||||
insertScroller('scroller1');
|
||||
// Even though #scroller1 was just inserted into the DOM, |timeline1|
|
||||
insertScroller('timeline1');
|
||||
// Even though the scroller was just inserted into the DOM, |timeline1|
|
||||
// remains inactive until the next frame.
|
||||
//
|
||||
// https://drafts.csswg.org/scroll-animations-1/#avoiding-cycles
|
||||
assert_equals(getComputedStyle(element1).width, '1px');
|
||||
(new ResizeObserver(entries => {
|
||||
events1.push(entries);
|
||||
insertScroller('scroller2');
|
||||
insertScroller('timeline2');
|
||||
assert_equals(getComputedStyle(element2).height, '1px');
|
||||
})).observe(element1);
|
||||
|
|
@ -0,0 +1,34 @@
|
|||
<!DOCTYPE html>
|
||||
<link rel="help" href="https://github.com/w3c/csswg-drafts/issues/6674">
|
||||
<link rel="help" href="https://drafts.csswg.org/scroll-animations-1/rewrite#scroll-timeline-name">
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
<script src="/css/support/computed-testcommon.js"></script>
|
||||
</head>
|
||||
<style>
|
||||
#outer { scroll-timeline-name: foo; }
|
||||
#target { scroll-timeline-name: bar; }
|
||||
</style>
|
||||
<div id="outer">
|
||||
<div id="target"></div>
|
||||
</div>
|
||||
<script>
|
||||
test_computed_value('scroll-timeline-name', 'initial', 'none');
|
||||
test_computed_value('scroll-timeline-name', 'inherit', 'foo');
|
||||
test_computed_value('scroll-timeline-name', 'unset', 'none');
|
||||
test_computed_value('scroll-timeline-name', 'revert', 'none');
|
||||
test_computed_value('scroll-timeline-name', 'none');
|
||||
test_computed_value('scroll-timeline-name', 'test');
|
||||
test_computed_value('scroll-timeline-name', 'tEst');
|
||||
|
||||
test(() => {
|
||||
let style = getComputedStyle(document.getElementById('target'));
|
||||
assert_not_equals(Array.from(style).indexOf('scroll-timeline-name'), -1);
|
||||
}, 'The scroll-timeline-name property shows up in CSSStyleDeclaration enumeration');
|
||||
|
||||
test(() => {
|
||||
let style = document.getElementById('target').style;
|
||||
assert_not_equals(style.cssText.indexOf('scroll-timeline-name'), -1);
|
||||
}, 'The scroll-timeline-name property shows up in CSSStyleDeclaration.cssText');
|
||||
|
||||
</script>
|
|
@ -0,0 +1,30 @@
|
|||
<!DOCTYPE html>
|
||||
<link rel="help" href="https://github.com/w3c/csswg-drafts/issues/6674">
|
||||
<link rel="help" href="https://drafts.csswg.org/scroll-animations-1/rewrite#scroll-timeline-name">
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
<script src="/css/support/parsing-testcommon.js"></script>
|
||||
</head>
|
||||
<div id="target"></div>
|
||||
|
||||
<script>
|
||||
|
||||
test_valid_value('scroll-timeline-name', 'initial');
|
||||
test_valid_value('scroll-timeline-name', 'inherit');
|
||||
test_valid_value('scroll-timeline-name', 'unset');
|
||||
test_valid_value('scroll-timeline-name', 'revert');
|
||||
|
||||
test_valid_value('scroll-timeline-name', 'none');
|
||||
test_valid_value('scroll-timeline-name', 'abc');
|
||||
test_valid_value('scroll-timeline-name', ' abc', 'abc');
|
||||
test_valid_value('scroll-timeline-name', 'aBc');
|
||||
test_valid_value('scroll-timeline-name', 'auto');
|
||||
|
||||
test_invalid_value('scroll-timeline-name', 'default');
|
||||
test_invalid_value('scroll-timeline-name', '10px');
|
||||
test_invalid_value('scroll-timeline-name', 'foo bar');
|
||||
test_invalid_value('scroll-timeline-name', '"foo" "bar"');
|
||||
test_invalid_value('scroll-timeline-name', 'rgb(1, 2, 3)');
|
||||
test_invalid_value('scroll-timeline-name', '#fefefe');
|
||||
|
||||
</script>
|
|
@ -1,23 +1,19 @@
|
|||
<!DOCTYPE html>
|
||||
<meta charset=utf-8>
|
||||
<title>The default scroll-timeline at rule with paused animations</title>
|
||||
<link rel="help" href="https://drafts.csswg.org/scroll-animations-1/#scroll-timeline-at-rule">
|
||||
<title>Scroll timeline with paused animations</title>
|
||||
<link rel="help" href="https://drafts.csswg.org/scroll-animations-1/#scroll-notation">
|
||||
<link rel="help" href="https://drafts.csswg.org/css-animations/#animation-play-state">
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
<script src="/scroll-animations/scroll-timelines/testcommon.js"></script>
|
||||
<script src="/css/css-animations/support/testcommon.js"></script>
|
||||
<script src="support/testcommon.js"></script>
|
||||
<style>
|
||||
@keyframes anim {
|
||||
from { width: 100px; }
|
||||
to { width: 200px; }
|
||||
}
|
||||
|
||||
@scroll-timeline timeline {
|
||||
source: auto;
|
||||
orientation: auto;
|
||||
scroll-offsets: none;
|
||||
}
|
||||
|
||||
.fill-vh {
|
||||
width: 100px;
|
||||
height: 100vh;
|
||||
|
@ -28,40 +24,66 @@
|
|||
<script>
|
||||
'use strict';
|
||||
|
||||
test(t => {
|
||||
const div = addDiv(t, { style: 'width: 50px; height: 100px;' });
|
||||
const filling = addDiv(t, { class: 'fill-vh' });
|
||||
const scroller = document.scrollingElement;
|
||||
getComputedStyle(document.scrollingElement).height
|
||||
|
||||
div.style.animation = 'anim 100s linear timeline paused';
|
||||
assert_equals(getComputedStyle(div).width, '100px');
|
||||
|
||||
const maxScroll = scroller.scrollHeight - scroller.clientHeight;
|
||||
scroller.scrollTop = maxScroll;
|
||||
assert_equals(getComputedStyle(div).width, '100px');
|
||||
|
||||
async function resetScrollPosition() {
|
||||
// Reset to 0 so we don't affect following tests.
|
||||
document.scrollingElement.scrollTop = 0;
|
||||
}, 'Test that the scroll animation is paused');
|
||||
return waitForNextFrame();
|
||||
}
|
||||
|
||||
test(t => {
|
||||
promise_test(async t => {
|
||||
const div = addDiv(t, { style: 'width: 50px; height: 100px;' });
|
||||
const filling = addDiv(t, { class: 'fill-vh' });
|
||||
const scroller = document.scrollingElement;
|
||||
getComputedStyle(document.scrollingElement).height
|
||||
t.add_cleanup(resetScrollPosition);
|
||||
|
||||
div.style.animation = 'anim 100s linear timeline';
|
||||
div.style.animation = 'anim 100s linear paused scroll(root)';
|
||||
await waitForCSSScrollTimelineStyle();
|
||||
|
||||
const anim = div.getAnimations()[0];
|
||||
await anim.ready;
|
||||
assert_percents_equal(anim.currentTime, 0, 'timeline time reset');
|
||||
assert_equals(getComputedStyle(div).width, '100px');
|
||||
|
||||
const maxScroll = scroller.scrollHeight - scroller.clientHeight;
|
||||
scroller.scrollTop = maxScroll;
|
||||
await waitForNextFrame();
|
||||
assert_equals(getComputedStyle(div).width, '100px');
|
||||
|
||||
}, 'Test that the scroll animation is paused');
|
||||
|
||||
promise_test(async t => {
|
||||
const div = addDiv(t, { style: 'width: 50px; height: 100px;' });
|
||||
const filling = addDiv(t, { class: 'fill-vh' });
|
||||
const scroller = document.scrollingElement;
|
||||
await waitForNextFrame();
|
||||
|
||||
div.style.animation = 'anim 100s linear forwards scroll(root)';
|
||||
await waitForCSSScrollTimelineStyle();
|
||||
|
||||
const anim = div.getAnimations()[0];
|
||||
await anim.ready;
|
||||
assert_percents_equal(anim.currentTime, 0, 'timeline time reset');
|
||||
assert_equals(getComputedStyle(div).width, '100px');
|
||||
|
||||
await waitForNextFrame();
|
||||
const maxScroll = scroller.scrollHeight - scroller.clientHeight;
|
||||
scroller.scrollTop = maxScroll;
|
||||
await waitForNextFrame();
|
||||
assert_equals(getComputedStyle(div).width, '200px');
|
||||
|
||||
div.style.animationPlayState = "paused";
|
||||
getComputedStyle(div).animationPlayState;
|
||||
|
||||
div.style.animationPlayState = 'paused';
|
||||
assert_equals(anim.playState, 'paused');
|
||||
assert_equals(getComputedStyle(div).width, '200px',
|
||||
'Current time preserved when pause-pending.');
|
||||
assert_true(anim.pending,
|
||||
'Pending state after changing animationPlayState');
|
||||
await anim.ready;
|
||||
assert_equals(getComputedStyle(div).width, '200px',
|
||||
'Current time preserved when paused.');
|
||||
assert_percents_equal(anim.timeline.currentTime, 100);
|
||||
document.scrollingElement.scrollTop = 0;
|
||||
await waitForNextFrame();
|
||||
assert_percents_equal(anim.timeline.currentTime, 0);
|
||||
assert_equals(getComputedStyle(div).width, '200px');
|
||||
}, 'Test that the scroll animation is paused by updating animation-play-state');
|
||||
|
|
@ -1,23 +1,20 @@
|
|||
<!DOCTYPE html>
|
||||
<meta charset=utf-8>
|
||||
<title>The default scroll-timeline at rule with animation moving from end point</title>
|
||||
<link rel="help" href="https://drafts.csswg.org/scroll-animations-1/#scroll-timeline-at-rule">
|
||||
<title>Root-scrolling timeline with animation moving from end point</title>
|
||||
<link rel="help" href="https://drafts.csswg.org/scroll-animations-1/#scroll-notation">
|
||||
<link rel="help" href="https://drafts.csswg.org/web-animations/#update-an-animations-finished-state">
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
<script src="/css/css-animations/support/testcommon.js"></script>
|
||||
<script src="/scroll-animations/scroll-timelines/testcommon.js"></script>
|
||||
<script src="support/testcommon.js"></script>
|
||||
|
||||
<style>
|
||||
@keyframes anim {
|
||||
from { width: 100px; }
|
||||
to { width: 200px; }
|
||||
}
|
||||
|
||||
@scroll-timeline timeline {
|
||||
source: auto;
|
||||
orientation: auto;
|
||||
scroll-offsets: none;
|
||||
}
|
||||
|
||||
.fill-vh {
|
||||
width: 100px;
|
||||
height: 100vh;
|
||||
|
@ -28,21 +25,34 @@
|
|||
<script>
|
||||
'use strict';
|
||||
|
||||
test(t => {
|
||||
promise_test(async t => {
|
||||
const div = addDiv(t, { style: 'width: 50px; height: 100px;' });
|
||||
const filling = addDiv(t, { class: 'fill-vh' });
|
||||
const scroller = document.scrollingElement;
|
||||
getComputedStyle(document.scrollingElement).height;
|
||||
scroller.scrollTop = 0;
|
||||
await waitForNextFrame();
|
||||
|
||||
div.style.animation = 'anim 100s linear timeline';
|
||||
assert_equals(getComputedStyle(div).width, '100px');
|
||||
div.style.animation = 'anim 100s linear scroll(root)';
|
||||
await waitForCSSScrollTimelineStyle();
|
||||
|
||||
const anim = div.getAnimations()[0];
|
||||
await anim.ready;
|
||||
assert_percents_equal(anim.timeline.currentTime, 0,
|
||||
'Timeline time when animation is ready');
|
||||
assert_equals(getComputedStyle(div).width, '100px',
|
||||
'Width at animation start');
|
||||
|
||||
await waitForNextFrame();
|
||||
const maxScroll = scroller.scrollHeight - scroller.clientHeight;
|
||||
scroller.scrollTop = maxScroll;
|
||||
assert_equals(getComputedStyle(div).width, '200px');
|
||||
await waitForNextFrame();
|
||||
assert_equals(getComputedStyle(div).width, '200px',
|
||||
'Width at scroll limit');
|
||||
|
||||
document.scrollingElement.scrollTop = 0;
|
||||
assert_equals(getComputedStyle(div).width, '100px');
|
||||
await waitForNextFrame();
|
||||
assert_equals(getComputedStyle(div).width, '100px',
|
||||
'Width after reset to scroll top');
|
||||
}, 'Test that the scroll animation is still responsive after moving from 100%');
|
||||
|
||||
</script>
|
|
@ -1,14 +1,14 @@
|
|||
<!DOCTYPE html>
|
||||
<link rel="help" src="https://drafts.csswg.org/scroll-animations-1/#scroll-timeline-at-rule">
|
||||
<link rel="help" src="https://drafts.csswg.org/scroll-animations-1/#avoiding-cycles">
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
<script src="/web-animations/testcommon.js"></script>
|
||||
<style>
|
||||
#scroller {
|
||||
overflow: scroll;
|
||||
overflow: hidden;
|
||||
width: 100px;
|
||||
height: 100px;
|
||||
scroll-timeline: timeline;
|
||||
}
|
||||
#contents {
|
||||
height: 200px;
|
||||
|
@ -17,11 +17,6 @@
|
|||
from { width: 100px; }
|
||||
to { width: 200px; }
|
||||
}
|
||||
@scroll-timeline timeline {
|
||||
source: selector(#scroller);
|
||||
start: 0px;
|
||||
end: 100px;
|
||||
}
|
||||
#element {
|
||||
width: 0px;
|
||||
animation: expand 10s linear;
|
|
@ -0,0 +1,41 @@
|
|||
<!DOCTYPE html>
|
||||
<link rel="help" href="https://github.com/w3c/csswg-drafts/issues/6674">
|
||||
<link rel="help" href="https://drafts.csswg.org/scroll-animations-1/rewrite#scroll-timeline-axis">
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
<script src="/css/support/computed-testcommon.js"></script>
|
||||
<script src="/css/support/parsing-testcommon.js"></script>
|
||||
<script src="/css/support/shorthand-testcommon.js"></script>
|
||||
<div id="target"></div>
|
||||
<script>
|
||||
test_valid_value('scroll-timeline', 'block none', 'block');
|
||||
test_valid_value('scroll-timeline', 'none inline', 'inline');
|
||||
test_valid_value('scroll-timeline', 'horizontal abc');
|
||||
test_valid_value('scroll-timeline', 'inline abc');
|
||||
test_valid_value('scroll-timeline', 'inline aBc');
|
||||
test_valid_value('scroll-timeline', 'vertical none', 'vertical');
|
||||
test_valid_value('scroll-timeline', 'inline inline');
|
||||
test_valid_value('scroll-timeline', 'abc');
|
||||
test_valid_value('scroll-timeline', 'inline');
|
||||
|
||||
test_invalid_value('scroll-timeline', '');
|
||||
test_invalid_value('scroll-timeline', 'abc abc');
|
||||
|
||||
test_computed_value('scroll-timeline', 'block none', 'block');
|
||||
test_computed_value('scroll-timeline', 'abc inline', 'inline abc');
|
||||
test_computed_value('scroll-timeline', 'none vertical', 'vertical');
|
||||
test_computed_value('scroll-timeline', 'horizontal abc');
|
||||
test_computed_value('scroll-timeline', 'vertical vertical');
|
||||
test_computed_value('scroll-timeline', 'abc');
|
||||
|
||||
test_shorthand_value('scroll-timeline', 'vertical abc',
|
||||
{
|
||||
'scroll-timeline-axis': 'vertical',
|
||||
'scroll-timeline-name': 'abc',
|
||||
});
|
||||
test_shorthand_value('scroll-timeline', 'horizontal inline',
|
||||
{
|
||||
'scroll-timeline-axis': 'horizontal',
|
||||
'scroll-timeline-name': 'inline',
|
||||
});
|
||||
</script>
|
|
@ -0,0 +1,49 @@
|
|||
<!DOCTYPE html>
|
||||
<title>scroll-timeline and container queries</title>
|
||||
<link rel="help" src="https://drafts.csswg.org/scroll-animations-1/#scroll-timeline-shorthand">
|
||||
<link rel="help" src="https://drafts.csswg.org/css-contain-3/#container-queries">
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
<script src="/web-animations/testcommon.js"></script>
|
||||
<script src="support/testcommon.js"></script>
|
||||
<style>
|
||||
#scroller {
|
||||
overflow: auto;
|
||||
width: auto;
|
||||
height: 100px;
|
||||
}
|
||||
#scroller > div {
|
||||
height: 200px;
|
||||
}
|
||||
|
||||
@keyframes anim {
|
||||
from { background-color: rgb(100, 100, 100); }
|
||||
to { background-color: rgb(200, 200, 200); }
|
||||
}
|
||||
#element {
|
||||
height: 10px;
|
||||
width: 10px;
|
||||
animation: anim 10s linear timeline;
|
||||
background-color: rgb(0, 0, 0);
|
||||
}
|
||||
</style>
|
||||
<div>
|
||||
<div id=scroller>
|
||||
<div></div>
|
||||
</div>
|
||||
<div>
|
||||
<div id=element></div>
|
||||
</div>
|
||||
</div>
|
||||
<script>
|
||||
promise_test(async (t) => {
|
||||
element.offsetTop;
|
||||
scroller.scrollTop = 50;
|
||||
await waitForNextFrame();
|
||||
// Unknown timeline, time held at zero.
|
||||
assert_equals(getComputedStyle(element).backgroundColor, 'rgb(100, 100, 100)');
|
||||
scroller.style.scrollTimeline = 'timeline';
|
||||
await waitForCSSScrollTimelineStyle();
|
||||
assert_equals(getComputedStyle(element).backgroundColor, 'rgb(150, 150, 150)');
|
||||
}, 'Timelines appearing on preceding siblings are visible to getComputedStyle');
|
||||
</script>
|
|
@ -1,6 +1,6 @@
|
|||
<!DOCTYPE html>
|
||||
<html class="reftest-wait">
|
||||
<title>Reference for @scroll-timeline with a specified scroller</title>
|
||||
<title>Reference for scroll timeline with a specified scroller</title>
|
||||
<style>
|
||||
#scroller {
|
||||
overflow: scroll;
|
|
@ -1,10 +1,10 @@
|
|||
<!DOCTYPE HTML>
|
||||
<html class="reftest-wait">
|
||||
<title>The scroll-timeline at rule with a specified scroller for print</title>
|
||||
<link rel="help" href="https://drafts.csswg.org/scroll-animations-1/#scroll-timeline-at-rule">
|
||||
<title>A scroll timeline with a specified scroller for print</title>
|
||||
<link rel="help" href="https://drafts.csswg.org/scroll-animations-1/#scroll-timelines">
|
||||
<link rel="help" href="https://drafts.csswg.org/css-animations-2/#animation-timeline">
|
||||
<meta name="assert" content="CSS animation correctly updates values when using the a specified scroller">
|
||||
<link rel="match" href="at-scroll-timeline-specified-scroller-print-ref.html">
|
||||
<meta name="assert" content="CSS animation correctly updates values when using a specified scroller">
|
||||
<link rel="match" href="scroll-timeline-specified-scroller-print-ref.html">
|
||||
|
||||
<style>
|
||||
@keyframes anim {
|
||||
|
@ -12,13 +12,8 @@
|
|||
to { transform: translateX(100px); }
|
||||
}
|
||||
|
||||
@scroll-timeline timeline {
|
||||
source: selector(#scroller);
|
||||
orientation: auto;
|
||||
scroll-offsets: none;
|
||||
}
|
||||
|
||||
#scroller {
|
||||
scroll-timeline: timeline;
|
||||
overflow: scroll;
|
||||
width: 100px;
|
||||
height: 100px;
|
|
@ -0,0 +1,14 @@
|
|||
'use strict';
|
||||
|
||||
/**
|
||||
* Returns a Promise that is resolved after a CSS scroll timeline is created (as
|
||||
* the result of a style change) and a snapshot has been taken, so that the
|
||||
* animation style is correctly reflected by getComputedStyle().
|
||||
* Technically, this only takes a full frame update. We implement this as two
|
||||
* requestAnimationFrame callbacks because the result will be available at the
|
||||
* beginning of the second frame.
|
||||
*/
|
||||
async function waitForCSSScrollTimelineStyle() {
|
||||
await waitForNextFrame();
|
||||
await waitForNextFrame();
|
||||
}
|
|
@ -0,0 +1,208 @@
|
|||
<!DOCTYPE html>
|
||||
<title>Animations using view-timeline</title>
|
||||
<link rel="help" src="https://drafts.csswg.org/scroll-animations-1/#view-timelines-named">
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
<script src="/web-animations/testcommon.js"></script>
|
||||
<style>
|
||||
@keyframes anim {
|
||||
from { z-index: 0; }
|
||||
to { z-index: 100; }
|
||||
}
|
||||
.vertical-scroller {
|
||||
overflow: auto;
|
||||
width: 100px;
|
||||
height: 100px;
|
||||
}
|
||||
.vertical-scroller > div {
|
||||
height: 50px;
|
||||
z-index: -1;
|
||||
}
|
||||
.horizontal-scroller {
|
||||
overflow: auto;
|
||||
width: 100px;
|
||||
height: 100px;
|
||||
writing-mode: vertical-lr;
|
||||
}
|
||||
.horizontal-scroller > div {
|
||||
width: 50px;
|
||||
z-index: -1;
|
||||
}
|
||||
</style>
|
||||
<main id=main></main>
|
||||
<script>
|
||||
function inflate(t, template) {
|
||||
t.add_cleanup(() => main.replaceChildren());
|
||||
main.append(template.content.cloneNode(true));
|
||||
}
|
||||
async function scrollTop(e, value) {
|
||||
e.scrollTop = value;
|
||||
await waitForNextFrame();
|
||||
}
|
||||
async function scrollLeft(e, value) {
|
||||
e.scrollLeft = value;
|
||||
await waitForNextFrame();
|
||||
}
|
||||
</script>
|
||||
|
||||
<template id=default_view_timeline>
|
||||
<style>
|
||||
#target {
|
||||
view-timeline: t1;
|
||||
animation: anim 1s linear t1;
|
||||
}
|
||||
</style>
|
||||
<div id=scroller class=vertical-scroller>
|
||||
<div></div> <!-- [0px, 50px] -->
|
||||
<div></div> <!-- [50px, 100px] -->
|
||||
<div></div> <!-- [100px, 150px] -->
|
||||
<div id=target></div> <!-- [150px, 200px] -->
|
||||
<div></div> <!-- [200px, 250px] -->
|
||||
<div></div> <!-- [250px, 300px] -->
|
||||
<div></div> <!-- [300px, 350px] -->
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
promise_test(async (t) => {
|
||||
inflate(t, default_view_timeline);
|
||||
assert_equals(getComputedStyle(target).zIndex, '-1');
|
||||
await scrollTop(scroller, 25);
|
||||
assert_equals(getComputedStyle(target).zIndex, '-1');
|
||||
await scrollTop(scroller, 50); // 0% (enter 0%)
|
||||
assert_equals(getComputedStyle(target).zIndex, '0');
|
||||
await scrollTop(scroller, 125); // 50%
|
||||
assert_equals(getComputedStyle(target).zIndex, '50');
|
||||
await scrollTop(scroller, 200); // 100% (exit 100%)
|
||||
assert_equals(getComputedStyle(target).zIndex, '100');
|
||||
await scrollTop(scroller, 225);
|
||||
assert_equals(getComputedStyle(target).zIndex, '-1');
|
||||
}, 'Default view-timeline');
|
||||
</script>
|
||||
|
||||
<template id=horizontal_timeline>
|
||||
<style>
|
||||
#target {
|
||||
view-timeline: t1 horizontal;
|
||||
animation: anim 1s linear t1;
|
||||
}
|
||||
</style>
|
||||
<div id=scroller class=horizontal-scroller>
|
||||
<div></div> <!-- [0px, 50px] -->
|
||||
<div></div> <!-- [50px, 100px] -->
|
||||
<div></div> <!-- [100px, 150px] -->
|
||||
<div id=target></div> <!-- [150px, 200px] -->
|
||||
<div></div> <!-- [200px, 250px] -->
|
||||
<div></div> <!-- [250px, 300px] -->
|
||||
<div></div> <!-- [300px, 350px] -->
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
promise_test(async (t) => {
|
||||
inflate(t, horizontal_timeline);
|
||||
assert_equals(getComputedStyle(target).zIndex, '-1');
|
||||
await scrollLeft(scroller, 25);
|
||||
assert_equals(getComputedStyle(target).zIndex, '-1');
|
||||
await scrollLeft(scroller, 50); // 0% (enter 0%)
|
||||
assert_equals(getComputedStyle(target).zIndex, '0');
|
||||
await scrollLeft(scroller, 125); // 50%
|
||||
assert_equals(getComputedStyle(target).zIndex, '50');
|
||||
await scrollLeft(scroller, 200); // 100% (exit 100%)
|
||||
assert_equals(getComputedStyle(target).zIndex, '100');
|
||||
await scrollLeft(scroller, 225);
|
||||
assert_equals(getComputedStyle(target).zIndex, '-1');
|
||||
}, 'Horizontal view-timeline');
|
||||
</script>
|
||||
|
||||
<template id=multiple_timelines>
|
||||
<style>
|
||||
#timelines {
|
||||
view-timeline: tv vertical, th horizontal;
|
||||
background-color: red;
|
||||
}
|
||||
#scroller {
|
||||
width: 100px;
|
||||
height: 100px;
|
||||
overflow: hidden;
|
||||
display: grid;
|
||||
grid-template-columns: 50px 50px 50px 50px 50px 50px 50px;
|
||||
grid-template-row: 50px 50px 50px 50px 50px 50px 50px;
|
||||
}
|
||||
#scroller > div {
|
||||
z-index: -1;
|
||||
width: 50px;
|
||||
height: 50px;
|
||||
}
|
||||
#target_v { animation: anim 1s linear tv; }
|
||||
#target_h { animation: anim 1s linear th; }
|
||||
</style>
|
||||
<div id=scroller>
|
||||
<!-- Created dynamically -->
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
promise_test(async (t) => {
|
||||
inflate(t, multiple_timelines);
|
||||
|
||||
// Create a 350px x 350px grid (7x7 items of 50x50px each), with the
|
||||
// timelines at item [3,3], an element attached to the horizontal timeline
|
||||
// at [4,3], and an element attached to the vertical timeline at [3,4].
|
||||
|
||||
// x x x x x x x
|
||||
// x x x x x x x
|
||||
// x x x x x x x
|
||||
// x x x T H x x
|
||||
// x x x V x x x
|
||||
// x x x x x x x
|
||||
// x x x x x x x
|
||||
// x x x x x x x
|
||||
|
||||
let grid_size = 7;
|
||||
for (let i = 0; i < (grid_size*grid_size); ++i) {
|
||||
let div = document.createElement('div');
|
||||
if (i == (3 * grid_size + 3))
|
||||
div.id = 'timelines';
|
||||
if (i == (3 * grid_size + 4))
|
||||
div.id = 'target_h';
|
||||
if (i == (4 * grid_size + 3))
|
||||
div.id = 'target_v';
|
||||
scroller.append(div);
|
||||
}
|
||||
|
||||
assert_equals(getComputedStyle(target_v).zIndex, '-1');
|
||||
assert_equals(getComputedStyle(target_h).zIndex, '-1');
|
||||
|
||||
// First scroll vertically.
|
||||
await scrollTop(scroller, 25);
|
||||
assert_equals(getComputedStyle(target_v).zIndex, '-1');
|
||||
assert_equals(getComputedStyle(target_h).zIndex, '-1');
|
||||
await scrollTop(scroller, 50); // 0% (enter 0%)
|
||||
assert_equals(getComputedStyle(target_v).zIndex, '0');
|
||||
assert_equals(getComputedStyle(target_h).zIndex, '-1');
|
||||
await scrollTop(scroller, 125); // 50%
|
||||
assert_equals(getComputedStyle(target_v).zIndex, '50');
|
||||
assert_equals(getComputedStyle(target_h).zIndex, '-1');
|
||||
await scrollTop(scroller, 200); // 100% (exit 100%)
|
||||
assert_equals(getComputedStyle(target_v).zIndex, '100');
|
||||
assert_equals(getComputedStyle(target_h).zIndex, '-1');
|
||||
await scrollTop(scroller, 225);
|
||||
assert_equals(getComputedStyle(target_v).zIndex, '-1');
|
||||
assert_equals(getComputedStyle(target_h).zIndex, '-1');
|
||||
|
||||
// Then horizontally.
|
||||
await scrollLeft(scroller, 25);
|
||||
assert_equals(getComputedStyle(target_v).zIndex, '-1');
|
||||
assert_equals(getComputedStyle(target_h).zIndex, '-1');
|
||||
await scrollLeft(scroller, 50); // 0% (enter 0%)
|
||||
assert_equals(getComputedStyle(target_v).zIndex, '-1');
|
||||
assert_equals(getComputedStyle(target_h).zIndex, '0');
|
||||
await scrollLeft(scroller, 125); // 50%
|
||||
assert_equals(getComputedStyle(target_v).zIndex, '-1');
|
||||
assert_equals(getComputedStyle(target_h).zIndex, '50');
|
||||
await scrollLeft(scroller, 200); // 100% (exit 100%)
|
||||
assert_equals(getComputedStyle(target_v).zIndex, '-1');
|
||||
assert_equals(getComputedStyle(target_h).zIndex, '100');
|
||||
await scrollLeft(scroller, 225);
|
||||
assert_equals(getComputedStyle(target_v).zIndex, '-1');
|
||||
assert_equals(getComputedStyle(target_h).zIndex, '-1');
|
||||
}, 'Multiple view-timelines on the same element');
|
||||
</script>
|
|
@ -0,0 +1,37 @@
|
|||
<!DOCTYPE html>
|
||||
<link rel="help" href="https://drafts.csswg.org/scroll-animations-1/#view-timeline-axis">
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
<script src="/css/support/computed-testcommon.js"></script>
|
||||
</head>
|
||||
<style>
|
||||
#outer { view-timeline-axis: block, inline; }
|
||||
#target { view-timeline-axis: vertical; }
|
||||
</style>
|
||||
<div id=outer>
|
||||
<div id=target></div>
|
||||
</div>
|
||||
<script>
|
||||
test_computed_value('view-timeline-axis', 'initial', 'block');
|
||||
test_computed_value('view-timeline-axis', 'inherit', 'block, inline');
|
||||
test_computed_value('view-timeline-axis', 'unset', 'block');
|
||||
test_computed_value('view-timeline-axis', 'revert', 'block');
|
||||
test_computed_value('view-timeline-axis', 'block');
|
||||
test_computed_value('view-timeline-axis', 'inline');
|
||||
test_computed_value('view-timeline-axis', 'vertical');
|
||||
test_computed_value('view-timeline-axis', 'horizontal');
|
||||
test_computed_value('view-timeline-axis', 'block, inline');
|
||||
test_computed_value('view-timeline-axis', 'inline, block');
|
||||
test_computed_value('view-timeline-axis', 'block, vertical, horizontal, inline');
|
||||
test_computed_value('view-timeline-axis', 'inline, inline, inline, inline');
|
||||
|
||||
test(() => {
|
||||
let style = getComputedStyle(document.getElementById('target'));
|
||||
assert_not_equals(Array.from(style).indexOf('view-timeline-axis'), -1);
|
||||
}, 'The view-timeline-axis property shows up in CSSStyleDeclaration enumeration');
|
||||
|
||||
test(() => {
|
||||
let style = document.getElementById('target').style;
|
||||
assert_not_equals(style.cssText.indexOf('view-timeline-axis'), -1);
|
||||
}, 'The view-timeline-axis property shows up in CSSStyleDeclaration.cssText');
|
||||
</script>
|
|
@ -0,0 +1,29 @@
|
|||
<!DOCTYPE html>
|
||||
<link rel="help" href="https://drafts.csswg.org/scroll-animations-1/#view-timeline-axis">
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
<script src="/css/support/parsing-testcommon.js"></script>
|
||||
</head>
|
||||
<div id="target"></div>
|
||||
<script>
|
||||
test_valid_value('view-timeline-axis', 'initial');
|
||||
test_valid_value('view-timeline-axis', 'inherit');
|
||||
test_valid_value('view-timeline-axis', 'unset');
|
||||
test_valid_value('view-timeline-axis', 'revert');
|
||||
|
||||
test_valid_value('view-timeline-axis', 'block');
|
||||
test_valid_value('view-timeline-axis', 'inline');
|
||||
test_valid_value('view-timeline-axis', 'vertical');
|
||||
test_valid_value('view-timeline-axis', 'horizontal');
|
||||
test_valid_value('view-timeline-axis', 'block, inline');
|
||||
test_valid_value('view-timeline-axis', 'inline, block');
|
||||
test_valid_value('view-timeline-axis', 'block, vertical, horizontal, inline');
|
||||
test_valid_value('view-timeline-axis', 'inline, inline, inline, inline');
|
||||
|
||||
test_invalid_value('view-timeline-axis', 'abc');
|
||||
test_invalid_value('view-timeline-axis', '10px');
|
||||
test_invalid_value('view-timeline-axis', 'auto');
|
||||
test_invalid_value('view-timeline-axis', 'none');
|
||||
test_invalid_value('view-timeline-axis', 'block inline');
|
||||
test_invalid_value('view-timeline-axis', 'block / inline');
|
||||
</script>
|
|
@ -0,0 +1,140 @@
|
|||
<!DOCTYPE html>
|
||||
<title>Animations using named timeline ranges</title>
|
||||
<link rel="help" src="https://drafts.csswg.org/scroll-animations-1/#named-timeline-range">
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
<script src="/web-animations/testcommon.js"></script>
|
||||
<style>
|
||||
@keyframes anim {
|
||||
from { z-index: 0; background-color: skyblue;}
|
||||
to { z-index: 100; background-color: coral; }
|
||||
}
|
||||
#scroller {
|
||||
border: 10px solid lightgray;
|
||||
overflow-y: scroll;
|
||||
width: 200px;
|
||||
height: 200px;
|
||||
}
|
||||
#target {
|
||||
margin: 800px 0px;
|
||||
width: 100px;
|
||||
height: 100px;
|
||||
z-index: -1;
|
||||
background-color: green;
|
||||
}
|
||||
</style>
|
||||
<main id=main>
|
||||
</main>
|
||||
<template>
|
||||
<div id=scroller>
|
||||
<div id=target></div>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
function inflate(t, template) {
|
||||
t.add_cleanup(() => main.replaceChildren());
|
||||
main.append(template.content.cloneNode(true));
|
||||
}
|
||||
async function scrollTop(e, value) {
|
||||
e.scrollTop = value;
|
||||
await waitForNextFrame();
|
||||
}
|
||||
async function waitForAnimationReady(target) {
|
||||
await waitForNextFrame();
|
||||
await Promise.all(target.getAnimations().map(x => x.promise));
|
||||
}
|
||||
async function assertValueAt(scroller, target, args) {
|
||||
await waitForAnimationReady(target);
|
||||
await scrollTop(scroller, args.scrollTop);
|
||||
assert_equals(getComputedStyle(target).zIndex, args.expected.toString());
|
||||
}
|
||||
function test_animation_delay(options) {
|
||||
promise_test(async (t) => {
|
||||
inflate(t, document.querySelector('template'));
|
||||
let scroller = main.querySelector('#scroller');
|
||||
let target = main.querySelector('#target');
|
||||
|
||||
target.style.viewTimeline = 't1 block';
|
||||
// TODO(crbug.com/1375998): Create the timeline in a separate frame to
|
||||
// work around a bug.
|
||||
await waitForNextFrame();
|
||||
|
||||
target.style.animation = 'anim 10s linear t1';
|
||||
target.style.animationDelayStart = options.startDelay;
|
||||
target.style.animationDelayEnd = options.endDelay;
|
||||
|
||||
// Accommodates floating point precision errors at the endpoints.
|
||||
target.style.animationFillMode = 'both';
|
||||
|
||||
// 0%
|
||||
await assertValueAt(scroller, target,
|
||||
{ scrollTop: options.rangeStart, expected: 0 });
|
||||
// 50%
|
||||
await assertValueAt(scroller, target,
|
||||
{ scrollTop: (options.rangeStart + options.rangeEnd) / 2, expected: 50 });
|
||||
// 100%
|
||||
await assertValueAt(scroller, target,
|
||||
{ scrollTop: options.rangeEnd, expected: 100 });
|
||||
|
||||
// Test before/after phases (need to clear the fill mode for that).
|
||||
target.style.animationFillMode = 'initial';
|
||||
await assertValueAt(scroller, target,
|
||||
{ scrollTop: options.rangeStart - 10, expected: -1 });
|
||||
await assertValueAt(scroller, target,
|
||||
{ scrollTop: options.rangeEnd + 10, expected: -1 });
|
||||
// Check 50% again without fill mode.
|
||||
await assertValueAt(scroller, target,
|
||||
{ scrollTop: (options.rangeStart + options.rangeEnd) / 2, expected: 50 });
|
||||
|
||||
}, `Animation with delays [${options.startDelay}, ${options.endDelay}]`);
|
||||
}
|
||||
|
||||
test_animation_delay({
|
||||
startDelay: 'initial',
|
||||
endDelay: 'initial',
|
||||
rangeStart: 600,
|
||||
rangeEnd: 900
|
||||
});
|
||||
|
||||
test_animation_delay({
|
||||
startDelay: 'cover 0%',
|
||||
endDelay: 'cover 100%',
|
||||
rangeStart: 600,
|
||||
rangeEnd: 900
|
||||
});
|
||||
|
||||
test_animation_delay({
|
||||
startDelay: 'contain 0%',
|
||||
endDelay: 'contain 100%',
|
||||
rangeStart: 700,
|
||||
rangeEnd: 800
|
||||
});
|
||||
|
||||
test_animation_delay({
|
||||
startDelay: 'enter 0%',
|
||||
endDelay: 'enter 100%',
|
||||
rangeStart: 600,
|
||||
rangeEnd: 700
|
||||
});
|
||||
|
||||
test_animation_delay({
|
||||
startDelay: 'exit 0%',
|
||||
endDelay: 'exit 100%',
|
||||
rangeStart: 800,
|
||||
rangeEnd: 900
|
||||
});
|
||||
|
||||
test_animation_delay({
|
||||
startDelay: 'contain -50%',
|
||||
endDelay: 'enter 200%',
|
||||
rangeStart: 650,
|
||||
rangeEnd: 800
|
||||
});
|
||||
|
||||
test_animation_delay({
|
||||
startDelay: 'enter 0%',
|
||||
endDelay: 'exit 100%',
|
||||
rangeStart: 600,
|
||||
rangeEnd: 900
|
||||
});
|
||||
</script>
|
|
@ -0,0 +1,177 @@
|
|||
<!DOCTYPE html>
|
||||
<title>Changes to view-timeline are reflected in dependent elements</title>
|
||||
<link rel="help" src="https://drafts.csswg.org/scroll-animations-1/#view-timeline-shorthand">
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
<script src="/web-animations/testcommon.js"></script>
|
||||
<script src="support/testcommon.js"></script>
|
||||
<style>
|
||||
@keyframes anim {
|
||||
from { z-index: 0; }
|
||||
to { z-index: 100; }
|
||||
}
|
||||
.scroller {
|
||||
overflow: hidden;
|
||||
width: 100px;
|
||||
height: 100px;
|
||||
}
|
||||
.scroller > div {
|
||||
height: 100px;
|
||||
}
|
||||
#target {
|
||||
height: 0px;
|
||||
z-index: -1;
|
||||
}
|
||||
</style>
|
||||
<main id=main></main>
|
||||
<script>
|
||||
function inflate(t, template) {
|
||||
t.add_cleanup(() => main.replaceChildren());
|
||||
main.append(template.content.cloneNode(true));
|
||||
main.offsetTop;
|
||||
}
|
||||
async function scrollTop(e, value) {
|
||||
e.scrollTop = value;
|
||||
await waitForNextFrame();
|
||||
}
|
||||
async function scrollLeft(e, value) {
|
||||
e.scrollLeft = value;
|
||||
await waitForNextFrame();
|
||||
}
|
||||
</script>
|
||||
|
||||
<template id=dynamic_view_timeline_name>
|
||||
<style>
|
||||
.timeline {
|
||||
view-timeline-name: t1;
|
||||
}
|
||||
#target {
|
||||
animation: anim 1s linear t1;
|
||||
}
|
||||
</style>
|
||||
<div id=scroller class=scroller>
|
||||
<div id=div75></div>
|
||||
<div id=div25></div>
|
||||
<div id=div_before></div>
|
||||
<div id=target></div>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
promise_test(async (t) => {
|
||||
inflate(t, dynamic_view_timeline_name);
|
||||
|
||||
await scrollTop(scroller, 50);
|
||||
|
||||
// scrollTop=50 is 75% for div75.
|
||||
div75.classList.add('timeline');
|
||||
await waitForCSSScrollTimelineStyle();
|
||||
assert_equals(getComputedStyle(target).zIndex, '75');
|
||||
|
||||
// scrollTop=50 is 25% for div25.
|
||||
div25.classList.add('timeline');
|
||||
await waitForCSSScrollTimelineStyle();
|
||||
assert_equals(getComputedStyle(target).zIndex, '25');
|
||||
|
||||
// scrollTop=50 is before the timeline start for div_before.
|
||||
div_before.classList.add('timeline');
|
||||
await waitForCSSScrollTimelineStyle();
|
||||
assert_equals(getComputedStyle(target).zIndex, '-1');
|
||||
// Scroll to 25% (for div_before) to verify that we're linked to that
|
||||
// timeline.
|
||||
await scrollTop(scroller, 150);
|
||||
assert_equals(getComputedStyle(target).zIndex, '25');
|
||||
|
||||
// Now we should be back to div25's timeline, although with the new
|
||||
// scrollTop=150, it's actually at 75%.
|
||||
div_before.classList.remove('timeline');
|
||||
await waitForCSSScrollTimelineStyle();
|
||||
assert_equals(getComputedStyle(target).zIndex, '75');
|
||||
}, 'Dynamically changing view-timeline-name');
|
||||
</script>
|
||||
|
||||
<template id=dynamic_view_timeline_axis>
|
||||
<style>
|
||||
#timeline {
|
||||
width: 100px;
|
||||
height: 100px;
|
||||
margin: 100px;
|
||||
view-timeline-name: t1;
|
||||
}
|
||||
#target {
|
||||
animation: anim 1s linear t1;
|
||||
}
|
||||
</style>
|
||||
<div id=scroller class=scroller>
|
||||
<div id=timeline style="background: red;"></div>
|
||||
<div id=target></div>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
promise_test(async (t) => {
|
||||
inflate(t, dynamic_view_timeline_axis);
|
||||
|
||||
await scrollTop(scroller, 50); // 25% (vertical)
|
||||
await scrollLeft(scroller, 20); // 10% (horizontal)
|
||||
|
||||
assert_equals(getComputedStyle(target).zIndex, '25');
|
||||
timeline.style.viewTimelineAxis = 'horizontal';
|
||||
await waitForCSSScrollTimelineStyle();
|
||||
assert_equals(getComputedStyle(target).zIndex, '10');
|
||||
}, 'Dynamically changing view-timeline-axis');
|
||||
</script>
|
||||
|
||||
<template id=dynamic_view_timeline_inset>
|
||||
<style>
|
||||
#timeline {
|
||||
width: 100px;
|
||||
height: 100px;
|
||||
margin: 100px;
|
||||
view-timeline-name: t1;
|
||||
}
|
||||
#target {
|
||||
animation: anim 1s linear t1;
|
||||
}
|
||||
</style>
|
||||
<div id=scroller class=scroller>
|
||||
<div id=timeline style="background: red;"></div>
|
||||
<div id=target></div>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
promise_test(async (t) => {
|
||||
inflate(t, dynamic_view_timeline_inset);
|
||||
|
||||
await scrollTop(scroller, 50); // 25% (without inset).
|
||||
|
||||
assert_equals(getComputedStyle(target).zIndex, '25');
|
||||
timeline.style.viewTimelineInset = '0px 50px';
|
||||
await waitForCSSScrollTimelineStyle();
|
||||
assert_equals(getComputedStyle(target).zIndex, '0');
|
||||
}, 'Dynamically changing view-timeline-inset');
|
||||
</script>
|
||||
|
||||
<template id=timeline_display_none>
|
||||
<style>
|
||||
#timeline {
|
||||
view-timeline-name: t1;
|
||||
}
|
||||
#target {
|
||||
animation: anim 1s linear t1;
|
||||
}
|
||||
</style>
|
||||
<div id=scroller class=scroller>
|
||||
<div></div>
|
||||
<div id=timeline></div>
|
||||
<div id=target></div>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
promise_test(async (t) => {
|
||||
inflate(t, timeline_display_none);
|
||||
|
||||
await scrollTop(scroller, 50);
|
||||
assert_equals(getComputedStyle(target).zIndex, '25');
|
||||
timeline.style.display = 'none';
|
||||
assert_equals(getComputedStyle(target).zIndex, '-1');
|
||||
}, 'Element with view-timeline becoming display:none');
|
||||
</script>
|
|
@ -0,0 +1,740 @@
|
|||
<!DOCTYPE html>
|
||||
<title>Animations using view-timeline-inset</title>
|
||||
<link rel="help" src="https://drafts.csswg.org/scroll-animations-1/#propdef-view-timeline-inset">
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
<script src="/web-animations/testcommon.js"></script>
|
||||
<style>
|
||||
@keyframes anim {
|
||||
from { z-index: 0; }
|
||||
to { z-index: 100; }
|
||||
}
|
||||
#scroller {
|
||||
overflow: hidden;
|
||||
width: 80px;
|
||||
height: 100px;
|
||||
}
|
||||
#target {
|
||||
margin: 150px;
|
||||
width: 50px;
|
||||
height: 50px;
|
||||
z-index: -1;
|
||||
}
|
||||
</style>
|
||||
<main id=main></main>
|
||||
<script>
|
||||
function inflate(t, template) {
|
||||
t.add_cleanup(() => main.replaceChildren());
|
||||
main.append(template.content.cloneNode(true));
|
||||
}
|
||||
async function scrollTop(e, value) {
|
||||
e.scrollTop = value;
|
||||
await waitForNextFrame();
|
||||
}
|
||||
async function scrollLeft(e, value) {
|
||||
e.scrollLeft = value;
|
||||
await waitForNextFrame();
|
||||
}
|
||||
async function assertValueAt(scroller, target, args) {
|
||||
if (args.scrollTop !== undefined)
|
||||
await scrollTop(scroller, args.scrollTop);
|
||||
if (args.scrollLeft !== undefined)
|
||||
await scrollLeft(scroller, args.scrollLeft);
|
||||
assert_equals(getComputedStyle(target).zIndex, args.expected.toString());
|
||||
}
|
||||
</script>
|
||||
|
||||
<!--
|
||||
Explanation of scroll positions
|
||||
===============================
|
||||
|
||||
Please note the following:
|
||||
|
||||
- The scroller has a width x height of 80x100px.
|
||||
- The content is 50x50px with a 150px margin on all sides.
|
||||
In other words, the size of the scroller content is 200x200px.
|
||||
|
||||
This means that, for vertical direction scrolling, assuming no insets:
|
||||
|
||||
- The start offset is 50px (scroller height + 50px is 150px, which consumes
|
||||
exactly the margin of the content).
|
||||
- The end offset is 200px (this is where the bottom edge of the scroller has
|
||||
just cleared the content).
|
||||
- The halfway point is (50px + 200px) / 2 = 125px.
|
||||
|
||||
For horizontal direction scrolling, assuming no insets:
|
||||
|
||||
- The start offset is 70px (scroller width + 70px is 150px, which consumes
|
||||
exactly the margin of the content).
|
||||
- The end offset is 200px (this is where the left edge of the scroller has
|
||||
just cleared the content).
|
||||
- The halfway point is (70px + 200px) / 2 = 135px.
|
||||
|
||||
The start and end insets will adjust the start and end offsets accordingly,
|
||||
and the expectations in this file explicitly write out those adjustments.
|
||||
For example, if the start offset is normally 50px, but there's an inset of
|
||||
10px, we'll expect 50px + 10px rather than 60px.
|
||||
|
||||
Halfway-point expectations write out the adjustment from the "normal"
|
||||
halfway-point, e.g. for start-inset:10px and end-inset:20px, we expect
|
||||
"125px + 5px" since (20-10)/2 == 5.
|
||||
|
||||
Finally, note that for right-to-left and bottom-to-top scrolling directions
|
||||
scroll offsets go the in the negative direction. This is why some expectations
|
||||
negate all the offsets.
|
||||
-->
|
||||
|
||||
<template id=test_one_value>
|
||||
<style>
|
||||
#target {
|
||||
view-timeline: t1;
|
||||
view-timeline-inset: 10px;
|
||||
animation: anim 1s linear t1;
|
||||
}
|
||||
</style>
|
||||
<div id=scroller class=vertical>
|
||||
<div id=target></div>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
promise_test(async (t) => {
|
||||
inflate(t, test_one_value);
|
||||
await assertValueAt(scroller, target, { scrollTop:50, expected:-1 });
|
||||
await assertValueAt(scroller, target, { scrollTop:50 + 10, expected:0 }); // 0%
|
||||
await assertValueAt(scroller, target, { scrollTop:125 + 0, expected:50 }); // 50%
|
||||
await assertValueAt(scroller, target, { scrollTop:200 - 10, expected:100 }); // 100%
|
||||
await assertValueAt(scroller, target, { scrollTop:200, expected:-1 });
|
||||
}, 'view-timeline-inset with one value');
|
||||
</script>
|
||||
|
||||
<template id=test_two_values>
|
||||
<style>
|
||||
#target {
|
||||
view-timeline: t1;
|
||||
view-timeline-inset: 10px 20px;
|
||||
animation: anim 1s linear t1;
|
||||
}
|
||||
</style>
|
||||
<div id=scroller class=vertical>
|
||||
<div id=target></div>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
promise_test(async (t) => {
|
||||
inflate(t, test_two_values);
|
||||
await assertValueAt(scroller, target, { scrollTop:50, expected:-1 });
|
||||
await assertValueAt(scroller, target, { scrollTop:50 + 20, expected:0 }); // 0%
|
||||
await assertValueAt(scroller, target, { scrollTop:125 + 5, expected:50 }); // 50%
|
||||
await assertValueAt(scroller, target, { scrollTop:200 - 10, expected:100 }); // 100%
|
||||
await assertValueAt(scroller, target, { scrollTop:200, expected:-1 });
|
||||
}, 'view-timeline-inset with two values');
|
||||
</script>
|
||||
|
||||
<template id=test_em_values>
|
||||
<style>
|
||||
#target {
|
||||
font-size: 10px;
|
||||
view-timeline: t1;
|
||||
view-timeline-inset: 10px 2em;
|
||||
animation: anim 1s linear t1;
|
||||
}
|
||||
</style>
|
||||
<div id=scroller class=vertical>
|
||||
<div id=target></div>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
promise_test(async (t) => {
|
||||
inflate(t, test_em_values);
|
||||
await assertValueAt(scroller, target, { scrollTop:50, expected:-1 });
|
||||
await assertValueAt(scroller, target, { scrollTop:50 + 20, expected:0 }); // 0%
|
||||
await assertValueAt(scroller, target, { scrollTop:125 + 5, expected:50 }); // 50%
|
||||
await assertValueAt(scroller, target, { scrollTop:200 - 10, expected:100 }); // 100%
|
||||
await assertValueAt(scroller, target, { scrollTop:200, expected:-1 });
|
||||
}, 'view-timeline-inset with em values');
|
||||
</script>
|
||||
|
||||
<template id=test_percentage_values>
|
||||
<style>
|
||||
#target {
|
||||
font-size: 10px;
|
||||
view-timeline: t1;
|
||||
view-timeline-inset: calc(5px + max(1%, 5%)) 20%;
|
||||
animation: anim 1s linear t1;
|
||||
}
|
||||
</style>
|
||||
<div id=scroller class=vertical>
|
||||
<div id=target></div>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
promise_test(async (t) => {
|
||||
inflate(t, test_percentage_values);
|
||||
await assertValueAt(scroller, target, { scrollTop:50, expected:-1 });
|
||||
await assertValueAt(scroller, target, { scrollTop:50 + 20, expected:0 }); // 0%
|
||||
await assertValueAt(scroller, target, { scrollTop:125 + 5, expected:50 }); // 50%
|
||||
await assertValueAt(scroller, target, { scrollTop:200 - 10, expected:100 }); // 100%
|
||||
await assertValueAt(scroller, target, { scrollTop:200, expected:-1 });
|
||||
}, 'view-timeline-inset with percentage values');
|
||||
</script>
|
||||
|
||||
<template id=test_outset>
|
||||
<style>
|
||||
#target {
|
||||
view-timeline: t1;
|
||||
view-timeline-inset: -10px -20px;
|
||||
animation: anim 1s linear t1;
|
||||
}
|
||||
</style>
|
||||
<div id=scroller class=vertical>
|
||||
<div id=target></div>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
promise_test(async (t) => {
|
||||
inflate(t, test_outset);
|
||||
await assertValueAt(scroller, target, { scrollTop:20, expected:-1 });
|
||||
await assertValueAt(scroller, target, { scrollTop:50 - 20, expected:0 }); // 0%
|
||||
await assertValueAt(scroller, target, { scrollTop:125 - 5, expected:50 }); // 50%
|
||||
await assertValueAt(scroller, target, { scrollTop:200 + 10, expected:100 }); // 100%
|
||||
await assertValueAt(scroller, target, { scrollTop:220, expected:-1 });
|
||||
}, 'view-timeline-inset with negative values');
|
||||
</script>
|
||||
|
||||
<template id=test_horizontal>
|
||||
<style>
|
||||
#target {
|
||||
view-timeline: t1 horizontal;
|
||||
view-timeline-inset: 10px 20px;
|
||||
animation: anim 1s linear t1;
|
||||
}
|
||||
</style>
|
||||
<div id=scroller>
|
||||
<div id=target></div>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
promise_test(async (t) => {
|
||||
inflate(t, test_horizontal);
|
||||
await assertValueAt(scroller, target, { scrollLeft:20, expected:-1 });
|
||||
await assertValueAt(scroller, target, { scrollLeft:70 + 20, expected:0 }); // 0%
|
||||
await assertValueAt(scroller, target, { scrollLeft:135 + 5, expected:50 }); // 50%
|
||||
await assertValueAt(scroller, target, { scrollLeft:200 - 10, expected:100 }); // 100%
|
||||
await assertValueAt(scroller, target, { scrollLeft:200, expected:-1 });
|
||||
}, 'view-timeline-inset with horizontal scroller');
|
||||
</script>
|
||||
|
||||
<template id=test_block>
|
||||
<style>
|
||||
#target {
|
||||
view-timeline: t1 block;
|
||||
view-timeline-inset: 10px 20px;
|
||||
animation: anim 1s linear t1;
|
||||
}
|
||||
</style>
|
||||
<div id=scroller>
|
||||
<div id=target></div>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
promise_test(async (t) => {
|
||||
inflate(t, test_block);
|
||||
await assertValueAt(scroller, target, { scrollTop:50, expected:-1 });
|
||||
await assertValueAt(scroller, target, { scrollTop:50 + 20, expected:0 }); // 0%
|
||||
await assertValueAt(scroller, target, { scrollTop:125 + 5, expected:50 }); // 50%
|
||||
await assertValueAt(scroller, target, { scrollTop:200 - 10, expected:100 }); // 100%
|
||||
await assertValueAt(scroller, target, { scrollTop:200, expected:-1 });
|
||||
}, 'view-timeline-inset with block scroller');
|
||||
</script>
|
||||
|
||||
<template id=test_inline>
|
||||
<style>
|
||||
#target {
|
||||
view-timeline: t1 inline;
|
||||
view-timeline-inset: 10px 20px;
|
||||
animation: anim 1s linear t1;
|
||||
}
|
||||
</style>
|
||||
<div id=scroller>
|
||||
<div id=target></div>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
promise_test(async (t) => {
|
||||
inflate(t, test_inline);
|
||||
await assertValueAt(scroller, target, { scrollLeft:20, expected:-1 });
|
||||
await assertValueAt(scroller, target, { scrollLeft:70 + 20, expected:0 }); // 0%
|
||||
await assertValueAt(scroller, target, { scrollLeft:135 + 5, expected:50 }); // 50%
|
||||
await assertValueAt(scroller, target, { scrollLeft:200 - 10, expected:100 }); // 100%
|
||||
await assertValueAt(scroller, target, { scrollLeft:200, expected:-1 });
|
||||
}, 'view-timeline-inset with inline scroller');
|
||||
</script>
|
||||
|
||||
<template id=test_auto_block>
|
||||
<style>
|
||||
#scroller {
|
||||
scroll-padding-block: 10px 20px;
|
||||
}
|
||||
#target {
|
||||
view-timeline: t1 block;
|
||||
view-timeline-inset: auto auto;
|
||||
animation: anim 1s linear t1;
|
||||
}
|
||||
</style>
|
||||
<div id=scroller>
|
||||
<div id=target></div>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
promise_test(async (t) => {
|
||||
inflate(t, test_auto_block);
|
||||
await assertValueAt(scroller, target, { scrollTop:50, expected:-1 });
|
||||
await assertValueAt(scroller, target, { scrollTop:50 + 20, expected:0 }); // 0%
|
||||
await assertValueAt(scroller, target, { scrollTop:125 + 5, expected:50 }); // 50%
|
||||
await assertValueAt(scroller, target, { scrollTop:200 - 10, expected:100 }); // 100%
|
||||
await assertValueAt(scroller, target, { scrollTop:200, expected:-1 });
|
||||
}, 'view-timeline-inset:auto, block');
|
||||
</script>
|
||||
|
||||
<template id=test_auto_block_vertical_lr>
|
||||
<style>
|
||||
#scroller {
|
||||
scroll-padding-block: 10px 20px;
|
||||
writing-mode: vertical-lr;
|
||||
}
|
||||
#target {
|
||||
view-timeline: t1 block;
|
||||
view-timeline-inset: auto auto;
|
||||
animation: anim 1s linear t1;
|
||||
}
|
||||
</style>
|
||||
<div id=scroller>
|
||||
<div id=target></div>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
promise_test(async (t) => {
|
||||
inflate(t, test_auto_block_vertical_lr);
|
||||
await assertValueAt(scroller, target, { scrollLeft:20, expected:-1 });
|
||||
await assertValueAt(scroller, target, { scrollLeft:70 + 20, expected:0 }); // 0%
|
||||
await assertValueAt(scroller, target, { scrollLeft:135 + 5, expected:50 }); // 50%
|
||||
await assertValueAt(scroller, target, { scrollLeft:200 - 10, expected:100 }); // 100%
|
||||
await assertValueAt(scroller, target, { scrollLeft:200, expected:-1 });
|
||||
}, 'view-timeline-inset:auto, block, vertical-lr');
|
||||
</script>
|
||||
|
||||
<template id=test_auto_block_vertical_rl>
|
||||
<style>
|
||||
#scroller {
|
||||
scroll-padding-block: 10px 20px;
|
||||
writing-mode: vertical-rl;
|
||||
}
|
||||
#target {
|
||||
view-timeline: t1 block;
|
||||
view-timeline-inset: auto auto;
|
||||
animation: anim 1s linear t1;
|
||||
}
|
||||
</style>
|
||||
<div id=scroller>
|
||||
<div id=target></div>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
promise_test(async (t) => {
|
||||
inflate(t, test_auto_block_vertical_rl);
|
||||
// Note: this represents horizontal scrolling from right to left.
|
||||
await assertValueAt(scroller, target, { scrollLeft:-20, expected:-1 });
|
||||
await assertValueAt(scroller, target, { scrollLeft:-(70 + 20), expected:0 }); // 0%
|
||||
await assertValueAt(scroller, target, { scrollLeft:-(135 + 5), expected:50 }); // 50%
|
||||
await assertValueAt(scroller, target, { scrollLeft:-(200 - 10), expected:100 }); // 100%
|
||||
await assertValueAt(scroller, target, { scrollLeft:-200, expected:-1 });
|
||||
}, 'view-timeline-inset:auto, block, vertical-rl');
|
||||
</script>
|
||||
|
||||
<template id=test_auto_inline>
|
||||
<style>
|
||||
#scroller {
|
||||
scroll-padding-inline: 10px 20px;
|
||||
}
|
||||
#target {
|
||||
view-timeline: t1 inline;
|
||||
view-timeline-inset: auto auto;
|
||||
animation: anim 1s linear t1;
|
||||
}
|
||||
</style>
|
||||
<div id=scroller>
|
||||
<div id=target></div>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
promise_test(async (t) => {
|
||||
inflate(t, test_auto_inline);
|
||||
await assertValueAt(scroller, target, { scrollLeft:20, expected:-1 });
|
||||
await assertValueAt(scroller, target, { scrollLeft:70 + 20, expected:0 }); // 0%
|
||||
await assertValueAt(scroller, target, { scrollLeft:135 + 5, expected:50 }); // 50%
|
||||
await assertValueAt(scroller, target, { scrollLeft:200 - 10, expected:100 }); // 100%
|
||||
await assertValueAt(scroller, target, { scrollLeft:200, expected:-1 });
|
||||
}, 'view-timeline-inset:auto, inline');
|
||||
</script>
|
||||
|
||||
<template id=test_auto_inline_vertical_rl>
|
||||
<style>
|
||||
#scroller {
|
||||
scroll-padding-inline: 10px 20px;
|
||||
writing-mode: vertical-rl;
|
||||
}
|
||||
#target {
|
||||
view-timeline: t1 inline;
|
||||
view-timeline-inset: auto auto;
|
||||
animation: anim 1s linear t1;
|
||||
}
|
||||
</style>
|
||||
<div id=scroller>
|
||||
<div id=target></div>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
promise_test(async (t) => {
|
||||
inflate(t, test_auto_inline_vertical_rl);
|
||||
await assertValueAt(scroller, target, { scrollTop:50, expected:-1 });
|
||||
await assertValueAt(scroller, target, { scrollTop:50 + 20, expected:0 }); // 0%
|
||||
await assertValueAt(scroller, target, { scrollTop:125 + 5, expected:50 }); // 50%
|
||||
await assertValueAt(scroller, target, { scrollTop:200 - 10, expected:100 }); // 100%
|
||||
await assertValueAt(scroller, target, { scrollTop:200, expected:-1 });
|
||||
}, 'view-timeline-inset:auto, inline, vertical-rl');
|
||||
</script>
|
||||
|
||||
<template id=test_auto_inline_vertical_lr>
|
||||
<style>
|
||||
#scroller {
|
||||
scroll-padding-inline: 10px 20px;
|
||||
writing-mode: vertical-lr;
|
||||
}
|
||||
#target {
|
||||
view-timeline: t1 inline;
|
||||
view-timeline-inset: auto auto;
|
||||
animation: anim 1s linear t1;
|
||||
}
|
||||
</style>
|
||||
<div id=scroller>
|
||||
<div id=target></div>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
promise_test(async (t) => {
|
||||
inflate(t, test_auto_inline_vertical_lr);
|
||||
await assertValueAt(scroller, target, { scrollTop:50, expected:-1 });
|
||||
await assertValueAt(scroller, target, { scrollTop:50 + 20, expected:0 }); // 0%
|
||||
await assertValueAt(scroller, target, { scrollTop:125 + 5, expected:50 }); // 50%
|
||||
await assertValueAt(scroller, target, { scrollTop:200 - 10, expected:100 }); // 100%
|
||||
await assertValueAt(scroller, target, { scrollTop:200, expected:-1 });
|
||||
}, 'view-timeline-inset:auto, inline, vertical-lr');
|
||||
</script>
|
||||
|
||||
<template id=test_auto_inline_rtl>
|
||||
<style>
|
||||
#scroller {
|
||||
scroll-padding-inline: 10px 20px;
|
||||
direction: rtl;
|
||||
}
|
||||
#target {
|
||||
view-timeline: t1 inline;
|
||||
view-timeline-inset: auto auto;
|
||||
animation: anim 1s linear t1;
|
||||
}
|
||||
</style>
|
||||
<div id=scroller>
|
||||
<div id=target></div>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
promise_test(async (t) => {
|
||||
inflate(t, test_auto_inline_rtl);
|
||||
await assertValueAt(scroller, target, { scrollLeft:-20, expected:-1 });
|
||||
await assertValueAt(scroller, target, { scrollLeft:-(70 + 20), expected:0 }); // 0%
|
||||
await assertValueAt(scroller, target, { scrollLeft:-(135 + 5), expected:50 }); // 50%
|
||||
await assertValueAt(scroller, target, { scrollLeft:-(200 - 10), expected:100 }); // 100%
|
||||
await assertValueAt(scroller, target, { scrollLeft:-200, expected:-1 });
|
||||
}, 'view-timeline-inset:auto, inline, rtl');
|
||||
</script>
|
||||
|
||||
<template id=test_auto_inline_vertical_rl_rtl>
|
||||
<style>
|
||||
#scroller {
|
||||
scroll-padding-inline: 10px 20px;
|
||||
writing-mode: vertical-rl;
|
||||
direction: rtl;
|
||||
}
|
||||
#target {
|
||||
view-timeline: t1 inline;
|
||||
view-timeline-inset: auto auto;
|
||||
animation: anim 1s linear t1;
|
||||
}
|
||||
</style>
|
||||
<div id=scroller>
|
||||
<div id=target></div>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
promise_test(async (t) => {
|
||||
inflate(t, test_auto_inline_vertical_rl_rtl);
|
||||
await assertValueAt(scroller, target, { scrollTop:-50, expected:-1 });
|
||||
await assertValueAt(scroller, target, { scrollTop:-(50 + 20), expected:0 }); // 0%
|
||||
await assertValueAt(scroller, target, { scrollTop:-(125 + 5), expected:50 }); // 50%
|
||||
await assertValueAt(scroller, target, { scrollTop:-(200 - 10), expected:100 }); // 100%
|
||||
await assertValueAt(scroller, target, { scrollTop:-200, expected:-1 });
|
||||
}, 'view-timeline-inset:auto, inline, vertical-rl, rtl');
|
||||
</script>
|
||||
|
||||
<template id=test_auto_inline_vertical_lr_rtl>
|
||||
<style>
|
||||
#scroller {
|
||||
scroll-padding-inline: 10px 20px;
|
||||
writing-mode: vertical-lr;
|
||||
direction: rtl;
|
||||
}
|
||||
#target {
|
||||
view-timeline: t1 inline;
|
||||
view-timeline-inset: auto auto;
|
||||
animation: anim 1s linear t1;
|
||||
}
|
||||
</style>
|
||||
<div id=scroller>
|
||||
<div id=target></div>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
promise_test(async (t) => {
|
||||
inflate(t, test_auto_inline_vertical_lr_rtl);
|
||||
await assertValueAt(scroller, target, { scrollTop:-50, expected:-1 });
|
||||
await assertValueAt(scroller, target, { scrollTop:-(50 + 20), expected:0 }); // 0%
|
||||
await assertValueAt(scroller, target, { scrollTop:-(125 + 5), expected:50 }); // 50%
|
||||
await assertValueAt(scroller, target, { scrollTop:-(200 - 10), expected:100 }); // 100%
|
||||
await assertValueAt(scroller, target, { scrollTop:-200, expected:-1 });
|
||||
}, 'view-timeline-inset:auto, inline, vertical-lr, rtl');
|
||||
</script>
|
||||
|
||||
<template id=test_auto_vertical>
|
||||
<style>
|
||||
#scroller {
|
||||
scroll-padding-block: 10px 20px;
|
||||
}
|
||||
#target {
|
||||
view-timeline: t1 vertical;
|
||||
view-timeline-inset: auto auto;
|
||||
animation: anim 1s linear t1;
|
||||
}
|
||||
</style>
|
||||
<div id=scroller>
|
||||
<div id=target></div>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
promise_test(async (t) => {
|
||||
inflate(t, test_auto_vertical);
|
||||
await assertValueAt(scroller, target, { scrollTop:50, expected:-1 });
|
||||
await assertValueAt(scroller, target, { scrollTop:50 + 20, expected:0 }); // 0%
|
||||
await assertValueAt(scroller, target, { scrollTop:125 + 5, expected:50 }); // 50%
|
||||
await assertValueAt(scroller, target, { scrollTop:200 - 10, expected:100 }); // 100%
|
||||
await assertValueAt(scroller, target, { scrollTop:200, expected:-1 });
|
||||
}, 'view-timeline-inset:auto, vertical');
|
||||
</script>
|
||||
|
||||
<template id=test_auto_vertical_vertical_rl>
|
||||
<style>
|
||||
#scroller {
|
||||
scroll-padding-inline: 10px 20px;
|
||||
writing-mode: vertical-rl;
|
||||
}
|
||||
#target {
|
||||
view-timeline: t1 vertical;
|
||||
view-timeline-inset: auto auto;
|
||||
animation: anim 1s linear t1;
|
||||
}
|
||||
</style>
|
||||
<div id=scroller>
|
||||
<div id=target></div>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
promise_test(async (t) => {
|
||||
inflate(t, test_auto_vertical_vertical_rl);
|
||||
await assertValueAt(scroller, target, { scrollTop:50, expected:-1 });
|
||||
await assertValueAt(scroller, target, { scrollTop:50 + 20, expected:0 }); // 0%
|
||||
await assertValueAt(scroller, target, { scrollTop:125 + 5, expected:50 }); // 50%
|
||||
await assertValueAt(scroller, target, { scrollTop:200 - 10, expected:100 }); // 100%
|
||||
await assertValueAt(scroller, target, { scrollTop:200, expected:-1 });
|
||||
}, 'view-timeline-inset:auto, vertical, vertical-rl');
|
||||
</script>
|
||||
|
||||
<template id=test_auto_vertical_vertical_rl_rtl>
|
||||
<style>
|
||||
#scroller {
|
||||
scroll-padding-inline: 10px 20px;
|
||||
writing-mode: vertical-rl;
|
||||
direction: rtl;
|
||||
}
|
||||
#target {
|
||||
view-timeline: t1 vertical;
|
||||
view-timeline-inset: auto auto;
|
||||
animation: anim 1s linear t1;
|
||||
}
|
||||
</style>
|
||||
<div id=scroller>
|
||||
<div id=target></div>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
promise_test(async (t) => {
|
||||
inflate(t, test_auto_vertical_vertical_rl_rtl);
|
||||
await assertValueAt(scroller, target, { scrollTop:-50, expected:-1 });
|
||||
await assertValueAt(scroller, target, { scrollTop:-(50 + 20), expected:0 }); // 0%
|
||||
await assertValueAt(scroller, target, { scrollTop:-(125 + 5), expected:50 }); // 50%
|
||||
await assertValueAt(scroller, target, { scrollTop:-(200 - 10), expected:100 }); // 100%
|
||||
await assertValueAt(scroller, target, { scrollTop:-200, expected:-1 });
|
||||
}, 'view-timeline-inset:auto, vertical, vertical-rl, rtl');
|
||||
</script>
|
||||
|
||||
<template id=test_auto_horizontal>
|
||||
<style>
|
||||
#scroller {
|
||||
scroll-padding-inline: 10px 20px;
|
||||
}
|
||||
#target {
|
||||
view-timeline: t1 horizontal;
|
||||
view-timeline-inset: auto auto;
|
||||
animation: anim 1s linear t1;
|
||||
}
|
||||
</style>
|
||||
<div id=scroller>
|
||||
<div id=target></div>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
promise_test(async (t) => {
|
||||
inflate(t, test_auto_horizontal);
|
||||
await assertValueAt(scroller, target, { scrollLeft:20, expected:-1 });
|
||||
await assertValueAt(scroller, target, { scrollLeft:70 + 20, expected:0 }); // 0%
|
||||
await assertValueAt(scroller, target, { scrollLeft:135 + 5, expected:50 }); // 50%
|
||||
await assertValueAt(scroller, target, { scrollLeft:200 - 10, expected:100 }); // 100%
|
||||
await assertValueAt(scroller, target, { scrollLeft:200, expected:-1 });
|
||||
}, 'view-timeline-inset:auto, horizontal');
|
||||
</script>
|
||||
|
||||
<template id=test_auto_horizontal_rtl>
|
||||
<style>
|
||||
#scroller {
|
||||
scroll-padding-inline: 10px 20px;
|
||||
direction: rtl;
|
||||
}
|
||||
#target {
|
||||
view-timeline: t1 horizontal;
|
||||
view-timeline-inset: auto auto;
|
||||
animation: anim 1s linear t1;
|
||||
}
|
||||
</style>
|
||||
<div id=scroller>
|
||||
<div id=target></div>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
promise_test(async (t) => {
|
||||
inflate(t, test_auto_horizontal_rtl);
|
||||
await assertValueAt(scroller, target, { scrollLeft:-20, expected:-1 });
|
||||
await assertValueAt(scroller, target, { scrollLeft:-(70 + 20), expected:0 }); // 0%
|
||||
await assertValueAt(scroller, target, { scrollLeft:-(135 + 5), expected:50 }); // 50%
|
||||
await assertValueAt(scroller, target, { scrollLeft:-(200 - 10), expected:100 }); // 100%
|
||||
await assertValueAt(scroller, target, { scrollLeft:-200, expected:-1 });
|
||||
}, 'view-timeline-inset:auto, horizontal, rtl');
|
||||
</script>
|
||||
|
||||
<template id=test_auto_horizontal_vertical_lr>
|
||||
<style>
|
||||
#scroller {
|
||||
scroll-padding-block: 10px 20px;
|
||||
writing-mode: vertical-lr;
|
||||
}
|
||||
#target {
|
||||
view-timeline: t1 horizontal;
|
||||
view-timeline-inset: auto auto;
|
||||
animation: anim 1s linear t1;
|
||||
}
|
||||
</style>
|
||||
<div id=scroller>
|
||||
<div id=target></div>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
promise_test(async (t) => {
|
||||
inflate(t, test_auto_horizontal_vertical_lr);
|
||||
await assertValueAt(scroller, target, { scrollLeft:20, expected:-1 });
|
||||
await assertValueAt(scroller, target, { scrollLeft:70 + 20, expected:0 }); // 0%
|
||||
await assertValueAt(scroller, target, { scrollLeft:135 + 5, expected:50 }); // 50%
|
||||
await assertValueAt(scroller, target, { scrollLeft:200 - 10, expected:100 }); // 100%
|
||||
await assertValueAt(scroller, target, { scrollLeft:200, expected:-1 });
|
||||
}, 'view-timeline-inset:auto, horizontal, vertical-lr');
|
||||
</script>
|
||||
|
||||
<template id=test_auto_horizontal_vertical_rl>
|
||||
<style>
|
||||
#scroller {
|
||||
scroll-padding-block: 10px 20px;
|
||||
writing-mode: vertical-rl;
|
||||
}
|
||||
#target {
|
||||
view-timeline: t1 horizontal;
|
||||
view-timeline-inset: auto auto;
|
||||
animation: anim 1s linear t1;
|
||||
}
|
||||
</style>
|
||||
<div id=scroller>
|
||||
<div id=target></div>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
promise_test(async (t) => {
|
||||
inflate(t, test_auto_horizontal_vertical_rl);
|
||||
await assertValueAt(scroller, target, { scrollLeft:-20, expected:-1 });
|
||||
await assertValueAt(scroller, target, { scrollLeft:-(70 + 20), expected:0 }); // 0%
|
||||
await assertValueAt(scroller, target, { scrollLeft:-(135 + 5), expected:50 }); // 50%
|
||||
await assertValueAt(scroller, target, { scrollLeft:-(200 - 10), expected:100 }); // 100%
|
||||
await assertValueAt(scroller, target, { scrollLeft:-200, expected:-1 });
|
||||
}, 'view-timeline-inset:auto, horizontal, vertical-rl');
|
||||
</script>
|
||||
|
||||
<template id=test_auto_mix>
|
||||
<style>
|
||||
#scroller {
|
||||
font-size: 10px;
|
||||
scroll-padding-block: 50px calc(10% + 1em);
|
||||
}
|
||||
#target {
|
||||
view-timeline: t1;
|
||||
view-timeline-inset: 10% auto;
|
||||
animation: anim 1s linear t1;
|
||||
}
|
||||
</style>
|
||||
<div id=scroller>
|
||||
<div id=target></div>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
promise_test(async (t) => {
|
||||
inflate(t, test_auto_mix);
|
||||
// Note: 10% of scroller height 100px is 10px, and 1em with font-size:10px
|
||||
// is also 10px. Hence we expect the end inset specified as calc(10% + 1em)
|
||||
// to be 20px.
|
||||
await assertValueAt(scroller, target, { scrollTop:50, expected:-1 });
|
||||
await assertValueAt(scroller, target, { scrollTop:50 + 20, expected:0 }); // 0%
|
||||
await assertValueAt(scroller, target, { scrollTop:125 + 5, expected:50 }); // 50%
|
||||
await assertValueAt(scroller, target, { scrollTop:200 - 10, expected:100 }); // 100%
|
||||
await assertValueAt(scroller, target, { scrollTop:200, expected:-1 });
|
||||
}, 'view-timeline-inset:auto, mix');
|
||||
</script>
|
||||
|
||||
<!--
|
||||
TODO: How to test view-timeline:auto + scroll-padding:auto? The UA may
|
||||
in theory use any value in that case.
|
||||
|
||||
https://drafts.csswg.org/css-scroll-snap-1/#valdef-scroll-padding-auto
|
||||
-->
|
|
@ -0,0 +1,41 @@
|
|||
<!DOCTYPE html>
|
||||
<link rel="help" href="https://drafts.csswg.org/scroll-animations-1/#view-timeline-inset">
|
||||
<link rel="help" href="https://github.com/w3c/csswg-drafts/issues/7243">
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
<script src="/css/support/computed-testcommon.js"></script>
|
||||
<style>
|
||||
#outer { font-size:10px; }
|
||||
#outer { view-timeline-inset: 1px 2px, auto 3px; }
|
||||
#target { view-timeline-inset: 42px; }
|
||||
</style>
|
||||
<div id=outer>
|
||||
<div id=target></div>
|
||||
</div>
|
||||
<script>
|
||||
test_computed_value('view-timeline-inset', 'initial', '0px');
|
||||
test_computed_value('view-timeline-inset', 'inherit', '1px 2px, auto 3px');
|
||||
test_computed_value('view-timeline-inset', 'unset', '0px');
|
||||
test_computed_value('view-timeline-inset', 'revert', '0px');
|
||||
test_computed_value('view-timeline-inset', '1px');
|
||||
test_computed_value('view-timeline-inset', '1%');
|
||||
test_computed_value('view-timeline-inset', 'calc(1% + 1px)');
|
||||
test_computed_value('view-timeline-inset', '1px 2px');
|
||||
test_computed_value('view-timeline-inset', '1px 2em', '1px 20px');
|
||||
test_computed_value('view-timeline-inset', 'calc(1px + 1em) 2px', '11px 2px');
|
||||
test_computed_value('view-timeline-inset', '1px 2px, 3px 4px');
|
||||
test_computed_value('view-timeline-inset', '1px auto, auto 4px');
|
||||
test_computed_value('view-timeline-inset', '1px, 2px, 3px');
|
||||
test_computed_value('view-timeline-inset', '1px 1px, 2px 3px', '1px, 2px 3px');
|
||||
test_computed_value('view-timeline-inset', 'auto auto, auto auto', 'auto, auto');
|
||||
|
||||
test(() => {
|
||||
let style = getComputedStyle(document.getElementById('target'));
|
||||
assert_not_equals(Array.from(style).indexOf('view-timeline-inset'), -1);
|
||||
}, 'The view-timeline-inset property shows up in CSSStyleDeclaration enumeration');
|
||||
|
||||
test(() => {
|
||||
let style = document.getElementById('target').style;
|
||||
assert_not_equals(style.cssText.indexOf('view-timeline-inset'), -1);
|
||||
}, 'The view-timeline-inset property shows up in CSSStyleDeclaration.cssText');
|
||||
</script>
|
|
@ -0,0 +1,34 @@
|
|||
<!DOCTYPE html>
|
||||
<link rel="help" href="https://drafts.csswg.org/scroll-animations-1/#view-timeline-inset">
|
||||
<link rel="help" href="https://github.com/w3c/csswg-drafts/issues/7243">
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
<script src="/css/support/parsing-testcommon.js"></script>
|
||||
<div id="target"></div>
|
||||
<script>
|
||||
test_valid_value('view-timeline-inset', 'initial');
|
||||
test_valid_value('view-timeline-inset', 'inherit');
|
||||
test_valid_value('view-timeline-inset', 'unset');
|
||||
test_valid_value('view-timeline-inset', 'revert');
|
||||
|
||||
test_valid_value('view-timeline-inset', '1px');
|
||||
test_valid_value('view-timeline-inset', '1px 2px');
|
||||
test_valid_value('view-timeline-inset', '1px 2em');
|
||||
test_valid_value('view-timeline-inset', 'calc(1em + 1px) 2px');
|
||||
test_valid_value('view-timeline-inset', '1px 2px, 3px 4px');
|
||||
test_valid_value('view-timeline-inset', '1px auto, auto 4px');
|
||||
test_valid_value('view-timeline-inset', '1px, 2px, 3px');
|
||||
test_valid_value('view-timeline-inset', '1px 1px, 2px 3px', '1px, 2px 3px');
|
||||
test_valid_value('view-timeline-inset', 'auto auto, auto auto', 'auto, auto');
|
||||
|
||||
test_invalid_value('view-timeline-inset', 'none');
|
||||
test_invalid_value('view-timeline-inset', 'foo bar');
|
||||
test_invalid_value('view-timeline-inset', '"foo" "bar"');
|
||||
test_invalid_value('view-timeline-inset', 'rgb(1, 2, 3)');
|
||||
test_invalid_value('view-timeline-inset', '#fefefe');
|
||||
test_invalid_value('view-timeline-inset', '1px 2px 3px');
|
||||
test_invalid_value('view-timeline-inset', '1px 2px auto');
|
||||
test_invalid_value('view-timeline-inset', 'auto 2px 3px');
|
||||
test_invalid_value('view-timeline-inset', 'auto auto auto');
|
||||
test_invalid_value('view-timeline-inset', '1px / 2px');
|
||||
</script>
|
|
@ -0,0 +1,292 @@
|
|||
<!DOCTYPE html>
|
||||
<title>Named view-timeline lookup</title>
|
||||
<link rel="help" src="https://drafts.csswg.org/scroll-animations-1/#view-timelines-named">
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
<script src="/web-animations/testcommon.js"></script>
|
||||
<style>
|
||||
@keyframes anim {
|
||||
from { z-index: 0; }
|
||||
to { z-index: 100; }
|
||||
}
|
||||
.scroller {
|
||||
overflow: auto;
|
||||
width: 100px;
|
||||
height: 100px;
|
||||
}
|
||||
.scroller > div {
|
||||
height: 25px;
|
||||
z-index: -1;
|
||||
}
|
||||
</style>
|
||||
<main id=main></main>
|
||||
<script>
|
||||
function inflate(t, template) {
|
||||
t.add_cleanup(() => main.replaceChildren());
|
||||
main.append(template.content.cloneNode(true));
|
||||
main.offsetTop;
|
||||
}
|
||||
</script>
|
||||
|
||||
<template id=timeline_self>
|
||||
<style>
|
||||
#target {
|
||||
height: 0px;
|
||||
view-timeline: t1;
|
||||
animation: anim 1s linear t1;
|
||||
}
|
||||
</style>
|
||||
<div id=scroller class=scroller>
|
||||
<div id=target></div>
|
||||
<div></div>
|
||||
<div></div>
|
||||
<div></div>
|
||||
<div></div>
|
||||
<div></div>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
promise_test(async (t) => {
|
||||
inflate(t, timeline_self);
|
||||
await waitForNextFrame();
|
||||
assert_equals(getComputedStyle(target).zIndex, '100');
|
||||
}, 'view-timeline on self');
|
||||
</script>
|
||||
|
||||
<template id=timeline_preceding_sibling>
|
||||
<style>
|
||||
#timeline {
|
||||
height: 0px;
|
||||
view-timeline: t1;
|
||||
}
|
||||
#target {
|
||||
animation: anim 1s linear t1;
|
||||
}
|
||||
</style>
|
||||
<div id=scroller class=scroller>
|
||||
<div></div>
|
||||
<div id=timeline></div>
|
||||
<div></div>
|
||||
<div></div>
|
||||
<div id=target></div>
|
||||
<div></div>
|
||||
<div></div>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
promise_test(async (t) => {
|
||||
inflate(t, timeline_preceding_sibling);
|
||||
await waitForNextFrame();
|
||||
assert_equals(getComputedStyle(target).zIndex, '75');
|
||||
}, 'view-timeline on preceding sibling');
|
||||
</script>
|
||||
|
||||
<template id=timeline_ancestor>
|
||||
<style>
|
||||
#timeline {
|
||||
height: 0px;
|
||||
view-timeline: t1;
|
||||
}
|
||||
#target {
|
||||
animation: anim 1s linear t1;
|
||||
}
|
||||
</style>
|
||||
<div id=scroller class=scroller>
|
||||
<div></div>
|
||||
<div></div>
|
||||
<div></div>
|
||||
<div id=timeline>
|
||||
<div>
|
||||
<div id=target></div>
|
||||
</div>
|
||||
</div>
|
||||
<div></div>
|
||||
<div></div>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
promise_test(async (t) => {
|
||||
inflate(t, timeline_ancestor);
|
||||
await waitForNextFrame();
|
||||
assert_equals(getComputedStyle(target).zIndex, '25');
|
||||
}, 'view-timeline on ancestor');
|
||||
</script>
|
||||
|
||||
<template id=timeline_ancestor_sibling>
|
||||
<style>
|
||||
#timeline {
|
||||
height: 0px;
|
||||
view-timeline: t1;
|
||||
}
|
||||
#target {
|
||||
animation: anim 1s linear t1;
|
||||
}
|
||||
</style>
|
||||
<div id=scroller class=scroller>
|
||||
<div></div>
|
||||
<div id=timeline></div>
|
||||
<div></div>
|
||||
<div>
|
||||
<div>
|
||||
<div id=target></div>
|
||||
</div>
|
||||
</div>
|
||||
<div></div>
|
||||
<div></div>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
promise_test(async (t) => {
|
||||
inflate(t, timeline_ancestor_sibling);
|
||||
await waitForNextFrame();
|
||||
assert_equals(getComputedStyle(target).zIndex, '75');
|
||||
}, 'view-timeline on ancestor sibling');
|
||||
</script>
|
||||
|
||||
<template id=timeline_ancestor_sibling_closest>
|
||||
<style>
|
||||
#timeline1, #timeline2 {
|
||||
height: 0px;
|
||||
view-timeline: t1;
|
||||
}
|
||||
#target {
|
||||
animation: anim 1s linear t1;
|
||||
}
|
||||
</style>
|
||||
<div id=scroller class=scroller>
|
||||
<div></div>
|
||||
<div id=timeline1></div>
|
||||
<div></div>
|
||||
<div id=timeline2></div>
|
||||
<div>
|
||||
<div>
|
||||
<div id=target></div>
|
||||
</div>
|
||||
</div>
|
||||
<div></div>
|
||||
<div></div>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
promise_test(async (t) => {
|
||||
inflate(t, timeline_ancestor_sibling_closest);
|
||||
await waitForNextFrame();
|
||||
assert_equals(getComputedStyle(target).zIndex, '50');
|
||||
}, 'view-timeline on ancestor sibling, closest wins');
|
||||
</script>
|
||||
|
||||
<template id=timeline_ancestor_sibling_skips_nonmatching>
|
||||
<style>
|
||||
#timeline1 {
|
||||
height: 0px;
|
||||
view-timeline: t1;
|
||||
}
|
||||
#timeline2 {
|
||||
height: 0px;
|
||||
view-timeline: t2;
|
||||
}
|
||||
#target {
|
||||
animation: anim 1s linear t1;
|
||||
}
|
||||
</style>
|
||||
<div id=scroller class=scroller>
|
||||
<div></div>
|
||||
<div id=timeline1></div>
|
||||
<div></div>
|
||||
<div id=timeline2></div>
|
||||
<div>
|
||||
<div>
|
||||
<div id=target></div>
|
||||
</div>
|
||||
</div>
|
||||
<div></div>
|
||||
<div></div>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
promise_test(async (t) => {
|
||||
inflate(t, timeline_ancestor_sibling_skips_nonmatching);
|
||||
await waitForNextFrame();
|
||||
assert_equals(getComputedStyle(target).zIndex, '75');
|
||||
}, 'view-timeline on ancestor sibling, skips nonmatching names');
|
||||
</script>
|
||||
|
||||
<template id=timeline_ancestor_closer_scroll_timeline_wins>
|
||||
<style>
|
||||
#timeline {
|
||||
height: 0px;
|
||||
view-timeline: t1;
|
||||
}
|
||||
#scroll {
|
||||
overflow: auto;
|
||||
scroll-timeline: t1;
|
||||
}
|
||||
#scroll > div {
|
||||
height: 50px;
|
||||
}
|
||||
#target {
|
||||
animation: anim 1s linear t1;
|
||||
}
|
||||
</style>
|
||||
<div id=scroller class=scroller>
|
||||
<div></div>
|
||||
<div id=timeline></div>
|
||||
<div></div>
|
||||
<div id=scroll>
|
||||
<div></div>
|
||||
</div>
|
||||
<div>
|
||||
<div>
|
||||
<div id=target></div>
|
||||
</div>
|
||||
</div>
|
||||
<div></div>
|
||||
<div></div>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
promise_test(async (t) => {
|
||||
inflate(t, timeline_ancestor_closer_scroll_timeline_wins);
|
||||
await waitForNextFrame();
|
||||
assert_equals(getComputedStyle(target).zIndex, '0');
|
||||
}, 'view-timeline on ancestor sibling, closer scroll-timeline wins');
|
||||
</script>
|
||||
|
||||
|
||||
<template id=timeline_ancestor_view_timeline_wins_on_same_element>
|
||||
<style>
|
||||
#timelines {
|
||||
height: 0px;
|
||||
view-timeline: t1;
|
||||
scroll-timeline: t1;
|
||||
overflow: auto;
|
||||
}
|
||||
#timelines > div {
|
||||
height: 50px;
|
||||
}
|
||||
#target {
|
||||
animation: anim 1s linear t1;
|
||||
}
|
||||
</style>
|
||||
<div id=scroller class=scroller>
|
||||
<div></div>
|
||||
<div id=timelines>
|
||||
<div></div>
|
||||
</div>
|
||||
<div></div>
|
||||
<div>
|
||||
<div>
|
||||
<div id=target></div>
|
||||
</div>
|
||||
</div>
|
||||
<div></div>
|
||||
<div></div>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
promise_test(async (t) => {
|
||||
inflate(t, timeline_ancestor_view_timeline_wins_on_same_element);
|
||||
await waitForNextFrame();
|
||||
assert_equals(getComputedStyle(target).zIndex, '75');
|
||||
}, 'view-timeline on ancestor sibling, view-timeline wins on same element');
|
||||
</script>
|
|
@ -0,0 +1,36 @@
|
|||
<!DOCTYPE html>
|
||||
<link rel="help" href="https://drafts.csswg.org/scroll-animations-1/#view-timeline-name">
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
<script src="/css/support/computed-testcommon.js"></script>
|
||||
</head>
|
||||
<style>
|
||||
#outer { view-timeline-name: foo, bar; }
|
||||
#target { view-timeline-name: faz; }
|
||||
</style>
|
||||
<div id=outer>
|
||||
<div id=target></div>
|
||||
</div>
|
||||
<script>
|
||||
test_computed_value('view-timeline-name', 'initial', 'none');
|
||||
test_computed_value('view-timeline-name', 'inherit', 'foo, bar');
|
||||
test_computed_value('view-timeline-name', 'unset', 'none');
|
||||
test_computed_value('view-timeline-name', 'revert', 'none');
|
||||
test_computed_value('view-timeline-name', 'none');
|
||||
test_computed_value('view-timeline-name', 'foo');
|
||||
test_computed_value('view-timeline-name', 'foo, bar');
|
||||
test_computed_value('view-timeline-name', 'bar, foo');
|
||||
test_computed_value('view-timeline-name', 'a, b, c, D, e');
|
||||
test_computed_value('view-timeline-name', 'none, none');
|
||||
test_computed_value('view-timeline-name', 'a, b, c, none, d, e');
|
||||
|
||||
test(() => {
|
||||
let style = getComputedStyle(document.getElementById('target'));
|
||||
assert_not_equals(Array.from(style).indexOf('view-timeline-name'), -1);
|
||||
}, 'The view-timeline-name property shows up in CSSStyleDeclaration enumeration');
|
||||
|
||||
test(() => {
|
||||
let style = document.getElementById('target').style;
|
||||
assert_not_equals(style.cssText.indexOf('view-timeline-name'), -1);
|
||||
}, 'The view-timeline-name property shows up in CSSStyleDeclaration.cssText');
|
||||
</script>
|
|
@ -0,0 +1,30 @@
|
|||
<!DOCTYPE html>
|
||||
<link rel="help" href="https://drafts.csswg.org/scroll-animations-1/#view-timeline-name">
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
<script src="/css/support/parsing-testcommon.js"></script>
|
||||
<div id="target"></div>
|
||||
<script>
|
||||
test_valid_value('view-timeline-name', 'initial');
|
||||
test_valid_value('view-timeline-name', 'inherit');
|
||||
test_valid_value('view-timeline-name', 'unset');
|
||||
test_valid_value('view-timeline-name', 'revert');
|
||||
|
||||
test_valid_value('view-timeline-name', 'none');
|
||||
test_valid_value('view-timeline-name', 'abc');
|
||||
test_valid_value('view-timeline-name', ' abc', 'abc');
|
||||
test_valid_value('view-timeline-name', 'abc ', 'abc');
|
||||
test_valid_value('view-timeline-name', 'aBc');
|
||||
test_valid_value('view-timeline-name', 'foo, bar');
|
||||
test_valid_value('view-timeline-name', 'bar, foo');
|
||||
test_valid_value('view-timeline-name', 'none, none');
|
||||
test_valid_value('view-timeline-name', 'a, none, b');
|
||||
test_valid_value('view-timeline-name', 'auto');
|
||||
|
||||
test_invalid_value('view-timeline-name', 'default');
|
||||
test_invalid_value('view-timeline-name', '10px');
|
||||
test_invalid_value('view-timeline-name', 'foo bar');
|
||||
test_invalid_value('view-timeline-name', '"foo" "bar"');
|
||||
test_invalid_value('view-timeline-name', 'rgb(1, 2, 3)');
|
||||
test_invalid_value('view-timeline-name', '#fefefe');
|
||||
</script>
|
|
@ -0,0 +1,104 @@
|
|||
<!DOCTYPE html>
|
||||
<link rel="help" href="https://drafts.csswg.org/scroll-animations-1/#view-timeline-shorthand">
|
||||
<link rel="help" href="https://github.com/w3c/csswg-drafts/issues/7627">
|
||||
<link rel="help" href="https://github.com/w3c/csswg-drafts/pull/7694">
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
<script src="/css/support/computed-testcommon.js"></script>
|
||||
<script src="/css/support/parsing-testcommon.js"></script>
|
||||
<script src="/css/support/shorthand-testcommon.js"></script>
|
||||
<div id="target"></div>
|
||||
<script>
|
||||
test_valid_value('view-timeline', 'abcd');
|
||||
test_valid_value('view-timeline', 'none block', 'none');
|
||||
test_valid_value('view-timeline', 'none inline');
|
||||
|
||||
// view-timeline-name: inline/block/horizontal/vertical.
|
||||
test_valid_value('view-timeline', 'inline block', 'inline');
|
||||
test_valid_value('view-timeline', 'block block', 'block');
|
||||
test_valid_value('view-timeline', 'vertical block', 'vertical');
|
||||
test_valid_value('view-timeline', 'horizontal block', 'horizontal');
|
||||
|
||||
test_valid_value('view-timeline', 'a, b, c');
|
||||
test_valid_value('view-timeline', 'a inline, b block, c vertical', 'a inline, b, c vertical');
|
||||
test_valid_value('view-timeline', 'auto');
|
||||
|
||||
test_invalid_value('view-timeline', 'abc abc');
|
||||
test_invalid_value('view-timeline', 'block none');
|
||||
test_invalid_value('view-timeline', 'none none');
|
||||
test_invalid_value('view-timeline', 'default');
|
||||
test_invalid_value('view-timeline', ',');
|
||||
test_invalid_value('view-timeline', ',,block,,');
|
||||
|
||||
test_computed_value('view-timeline', 'abcd');
|
||||
test_computed_value('view-timeline', 'none block', 'none');
|
||||
test_computed_value('view-timeline', 'none inline');
|
||||
test_computed_value('view-timeline', 'inline block', 'inline');
|
||||
test_computed_value('view-timeline', 'block block', 'block');
|
||||
test_computed_value('view-timeline', 'vertical block', 'vertical');
|
||||
test_computed_value('view-timeline', 'horizontal block', 'horizontal');
|
||||
test_computed_value('view-timeline', 'a, b, c');
|
||||
test_computed_value('view-timeline', 'a inline, b block, c vertical', 'a inline, b, c vertical');
|
||||
|
||||
test_shorthand_value('view-timeline', 'abc vertical',
|
||||
{
|
||||
'view-timeline-name': 'abc',
|
||||
'view-timeline-axis': 'vertical',
|
||||
});
|
||||
test_shorthand_value('view-timeline', 'abc vertical, def',
|
||||
{
|
||||
'view-timeline-name': 'abc, def',
|
||||
'view-timeline-axis': 'vertical, block',
|
||||
});
|
||||
test_shorthand_value('view-timeline', 'abc, def',
|
||||
{
|
||||
'view-timeline-name': 'abc, def',
|
||||
'view-timeline-axis': 'block, block',
|
||||
});
|
||||
test_shorthand_value('view-timeline', 'inline horizontal',
|
||||
{
|
||||
'view-timeline-name': 'inline',
|
||||
'view-timeline-axis': 'horizontal',
|
||||
});
|
||||
|
||||
function test_shorthand_contraction(shorthand, longhands, expected) {
|
||||
let longhands_fmt = Object.entries(longhands).map((e) => `${e[0]}:${e[1]}`).join(';');
|
||||
test((t) => {
|
||||
t.add_cleanup(() => {
|
||||
for (let shorthand of Object.keys(longhands))
|
||||
target.style.removeProperty(shorthand);
|
||||
});
|
||||
for (let [shorthand, value] of Object.entries(longhands))
|
||||
target.style.setProperty(shorthand, value);
|
||||
assert_equals(target.style.getPropertyValue(shorthand), expected, 'Declared value');
|
||||
assert_equals(getComputedStyle(target).getPropertyValue(shorthand), expected, 'Computed value');
|
||||
}, `Shorthand contraction of ${longhands_fmt}`);
|
||||
}
|
||||
|
||||
test_shorthand_contraction('view-timeline', {
|
||||
'view-timeline-name': 'abc',
|
||||
'view-timeline-axis': 'inline',
|
||||
}, 'abc inline');
|
||||
|
||||
test_shorthand_contraction('view-timeline', {
|
||||
'view-timeline-name': 'a, b',
|
||||
'view-timeline-axis': 'inline, block',
|
||||
}, 'a inline, b');
|
||||
|
||||
test_shorthand_contraction('view-timeline', {
|
||||
'view-timeline-name': 'none, none',
|
||||
'view-timeline-axis': 'block, block',
|
||||
}, 'none, none');
|
||||
|
||||
// Longhands with different lengths:
|
||||
|
||||
test_shorthand_contraction('view-timeline', {
|
||||
'view-timeline-name': 'a, b, c',
|
||||
'view-timeline-axis': 'inline, inline',
|
||||
}, '');
|
||||
|
||||
test_shorthand_contraction('view-timeline', {
|
||||
'view-timeline-name': 'a, b',
|
||||
'view-timeline-axis': 'inline, inline, inline',
|
||||
}, '');
|
||||
</script>
|
|
@ -0,0 +1,99 @@
|
|||
<!DOCTYPE html>
|
||||
<title>Used values of view-timeline properties</title>
|
||||
<link rel="help" src="https://drafts.csswg.org/scroll-animations-1/#view-timeline-axis">
|
||||
<link rel="help" src="https://drafts.csswg.org/scroll-animations-1/#view-timeline-name">
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
<script src="/web-animations/testcommon.js"></script>
|
||||
<style>
|
||||
@keyframes anim {
|
||||
from { z-index: 0; }
|
||||
to { z-index: 100; }
|
||||
}
|
||||
.scroller {
|
||||
overflow: hidden;
|
||||
width: 100px;
|
||||
height: 100px;
|
||||
}
|
||||
.scroller > div {
|
||||
width: 300px;
|
||||
height: 300px;
|
||||
z-index: -1;
|
||||
}
|
||||
</style>
|
||||
<main id=main></main>
|
||||
<script>
|
||||
function inflate(t, template) {
|
||||
t.add_cleanup(() => main.replaceChildren());
|
||||
main.append(template.content.cloneNode(true));
|
||||
}
|
||||
async function scrollTop(e, value) {
|
||||
e.scrollTop = value;
|
||||
await waitForNextFrame();
|
||||
}
|
||||
async function scrollLeft(e, value) {
|
||||
e.scrollLeft = value;
|
||||
await waitForNextFrame();
|
||||
}
|
||||
</script>
|
||||
|
||||
<template id=omitted_axis>
|
||||
<style>
|
||||
#target {
|
||||
view-timeline-name: t1, t2; /* Two items */
|
||||
view-timeline-axis: inline; /* One item */
|
||||
animation: anim 1s linear t2;
|
||||
}
|
||||
</style>
|
||||
<div id=scroller class=scroller>
|
||||
<div id=target></div>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
promise_test(async (t) => {
|
||||
inflate(t, omitted_axis);
|
||||
assert_equals(getComputedStyle(target).zIndex, '-1');
|
||||
|
||||
// enter 0% is at scrollTop/Left = -100
|
||||
// exit 100% is at scrollTop/Left = 300
|
||||
// This means that at scrollTop/Left=0, the animation is at 25%.
|
||||
|
||||
await scrollTop(scroller, 0);
|
||||
await scrollLeft(scroller, 0);
|
||||
assert_equals(getComputedStyle(target).zIndex, '25');
|
||||
|
||||
// The timeline should be inline-axis:
|
||||
await scrollTop(scroller, 100); // 50%
|
||||
await scrollLeft(scroller, 40); // 35%
|
||||
assert_equals(getComputedStyle(target).zIndex, '35');
|
||||
}, 'Use the last value from view-timeline-axis if omitted');
|
||||
</script>
|
||||
|
||||
<template id=omitted_inset>
|
||||
<style>
|
||||
#target {
|
||||
view-timeline-name: t1, t2; /* Two items */
|
||||
view-timeline-inset: 100px; /* One item */
|
||||
animation: anim 1s linear t2;
|
||||
}
|
||||
</style>
|
||||
<div id=scroller class=scroller>
|
||||
<div id=target></div>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
promise_test(async (t) => {
|
||||
inflate(t, omitted_inset);
|
||||
assert_equals(getComputedStyle(target).zIndex, '-1');
|
||||
|
||||
// 0% is normally at at scrollTop = -100
|
||||
// 100% is normally at scrollTop/Left = 300
|
||||
// However, we have a 100px inset in both ends, which makes the
|
||||
// range [0, 200].
|
||||
|
||||
await scrollTop(scroller, 0);
|
||||
assert_equals(getComputedStyle(target).zIndex, '0');
|
||||
await scrollTop(scroller, 100); // 50%
|
||||
assert_equals(getComputedStyle(target).zIndex, '50');
|
||||
}, 'Use the last value from view-timeline-inset if omitted');
|
||||
</script>
|
Loading…
Add table
Add a link
Reference in a new issue