blob: 0d591ea370778e9c9e54f707f6663db3d67e2587 [file] [log] [blame]
<!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);
time-range: 10s;
start: selector(#offset1);
end: selector(#offset2);
}
@scroll-timeline timeline_end_end {
source: selector(#scroller);
time-range: 10s;
start: selector(#offset1) end;
end: selector(#offset2) end;
}
@scroll-timeline timeline_end_start {
source: selector(#scroller);
time-range: 10s;
start: selector(#offset1) end;
end: selector(#offset2) start;
}
@scroll-timeline timeline_end_1_end {
source: selector(#scroller);
time-range: 10s;
start: selector(#offset1) end 1;
end: selector(#offset2) end;
}
@scroll-timeline timeline_end_start_05 {
source: selector(#scroller);
time-range: 10s;
start: selector(#offset1) end;
end: selector(#offset2) 0.5;
}
@scroll-timeline timeline_start_400px {
source: selector(#scroller);
time-range: 10s;
start: selector(#offset1);
end: 400px;
}
@scroll-timeline timeline_50px_end {
source: selector(#scroller);
time-range: 10s;
start: 50px;
end: selector(#offset2) end;
}
@scroll-timeline timeline_outside {
source: selector(#scroller);
time-range: 10s;
start: selector(#offset_outside);
end: auto;
}
@scroll-timeline timeline_display_none {
source: selector(#scroller);
time-range: 10s;
start: selector(#offset_display_none);
end: auto;
}
@scroll-timeline timeline_null_target {
source: selector(#scroller);
time-range: 10s;
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>