Source code
Revision control
Copy as Markdown
Other Tools
Test Info:
- This WPT test may be referenced by the following Test IDs:
- /scroll-animations/css/scroll-timeline-inactive.html - WPT Dashboard Interop Dashboard
<!DOCTYPE html>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="/web-animations/testcommon.js"></script>
<style>
@keyframes expand {
from { width: 100px; }
to { width: 200px; }
}
.scroller {
overflow: scroll;
width: 100px;
height: 100px;
}
#main {
timeline-scope: --timeline;
}
</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=basic>
<style>
#timeline {
scroll-timeline: --timeline;
}
#element {
width: 0px;
animation: expand;
animation-timeline: --timeline;
}
</style>
<div id="container">
<div id=timeline class=scroller><div>
<div id=element></div>
</div>
</template>
<script>
promise_test(async (t) => {
await runAndWaitForFrameUpdate(() => {
inflate(t, basic);
});
const animation = document.getAnimations()[0];
assert_true(animation.timeline instanceof ScrollTimeline,
'Timeline successfully set');
assert_equals(getComputedStyle(element).width, '0px');
}, 'Animation does not apply when the timeline is inactive because there is ' +
'no scroll range');
</script>
<template id=dynamically_change_range>
<style>
#timeline {
scroll-timeline: --timeline;
}
#contents {
height: 200px;
}
#contents.shrink {
height: 0px;
}
#element {
width: 0px;
animation: expand;
animation-timeline: --timeline;
}
</style>
<div id="container">
<div id=timeline class=scroller>
<div id="contents"></div>
</div>
<div id=element></div>
</div>
</template>
<script>
promise_test(async (t) => {
let scroller;
let initial_width;
await runAndWaitForFrameUpdate(() => {
inflate(t, dynamically_change_range);
scroller = document.querySelector('.scroller');
scroller.scrollTop = 0;
initial_width = getComputedStyle(element).width;
});
assert_equals(initial_width, '0px',
'Animation not in effect until after next animation frame');
const animation = document.getAnimations()[0];
assert_true(animation.timeline instanceof ScrollTimeline,
'Timeline successfully set');
assert_equals(getComputedStyle(element).width, '100px',
'Style after frame update');
let updated_width;
let updated_scroll_range;
await runAndWaitForFrameUpdate(() => {
// Style change after the first update-cycle for the frame.
// timeline time remains fixed until the next frame.
contents.classList.add('shrink');
updated_width = getComputedStyle(element).width;
udpated_scroll_range = scroller.scrollHeight - scroller.clientHeight;
});
assert_equals(updated_width, '100px',
'Animation progress fixed until next animation frame');
assert_equals(udpated_scroll_range, 0,
'Scroll range after content collapses');
// Timeline is once again inactive.
assert_equals(getComputedStyle(element).width, '0px',
'Timeline time after frame update with zero scroll range');
}, 'Animation does not apply when timeline becomes inactive');
</script>