| <!DOCTYPE html> |
| <html id="top"> |
| <head> |
| <meta charset="utf-8"> |
| <title>View timeline with sticky during entry/exit</title> |
| <link rel="help" href="https://drafts.csswg.org/scroll-animations-1/#viewtimeline-interface"> |
| <script src="/resources/testharness.js"></script> |
| <script src="/resources/testharnessreport.js"></script> |
| <script src="/web-animations/testcommon.js"></script> |
| <script src="/scroll-animations/scroll-timelines/testcommon.js"></script> |
| <script src="/scroll-animations/view-timelines/testcommon.js"></script> |
| <style> |
| |
| #container { |
| height: 500px; |
| overflow: auto; |
| } |
| .space { |
| height: 550px; |
| } |
| |
| /* top-sticky and bottom-sticky during entry */ |
| .stickycase3 { |
| background: yellow; |
| position: sticky; |
| top: 375px; |
| bottom: -125px; |
| height: 200px; |
| } |
| |
| #target { |
| position: relative; |
| top: 50px; |
| background: orange; |
| height: 100px; |
| } |
| |
| </style> |
| </head> |
| <body> |
| <div id="container"> |
| <div class="space"></div> |
| <div class="space"> |
| <div style="height: 150px"></div> |
| <div id="sticky" class="stickycase3"> |
| <div id="target">Subject</div> |
| </div> |
| </div> |
| <div class="space"></div> |
| </div> |
| <script type="text/javascript"> |
| |
| // The "cover" range would be [STATIC_START, STATIC_END] if we ignored |
| // stickiness (i.e., considered only static position). |
| // |
| // STATIC_START = scroll distance to second spacer (50px) |
| // + position of sticky element within its container (150px) |
| // + position of target within sticky element (50px) |
| // STATIC_END = STATIC_START |
| // + viewport height (500px) |
| // + target height (100px) |
| const STATIC_START = 250; |
| const STATIC_END = 850; |
| |
| // This is how far the sticky element can move upwards when bottom-stuck. |
| const ROOM_ABOVE = 150; |
| |
| // This is how far the sticky element can move downwards when top-stuck. |
| const ROOM_BELOW = 200; |
| |
| const TARGET_HEIGHT = 100; |
| const VIEWPORT_HEIGHT = 500; |
| |
| promise_test(async t => { |
| await runTimelineRangeTest(t, { |
| rangeStart: { rangeName: 'cover', offset: CSS.percent(0) } , |
| rangeEnd: { rangeName: 'cover', offset: CSS.percent(100) }, |
| startOffset: STATIC_START - ROOM_ABOVE, |
| endOffset: STATIC_END + ROOM_BELOW, |
| axis: 'block' |
| }); |
| await runTimelineRangeTest(t, { |
| rangeStart: { rangeName: 'contain', offset: CSS.percent(0) } , |
| rangeEnd: { rangeName: 'contain', offset: CSS.percent(100) }, |
| startOffset: STATIC_START + ROOM_BELOW + TARGET_HEIGHT, |
| endOffset: STATIC_END + ROOM_BELOW - TARGET_HEIGHT, |
| axis: 'block' |
| }); |
| await runTimelineRangeTest(t, { |
| rangeStart: { rangeName: 'entry', offset: CSS.percent(0) }, |
| rangeEnd: { rangeName: 'entry', offset: CSS.percent(100) }, |
| startOffset: STATIC_START - ROOM_ABOVE, |
| endOffset: STATIC_START + ROOM_BELOW + TARGET_HEIGHT, |
| axis: 'block' |
| }); |
| await runTimelineRangeTest(t, { |
| rangeStart: { rangeName: 'entry-crossing', offset: CSS.percent(0) }, |
| rangeEnd: { rangeName: 'entry-crossing', offset: CSS.percent(100) }, |
| startOffset: STATIC_START - ROOM_ABOVE, |
| endOffset: STATIC_START + ROOM_BELOW + TARGET_HEIGHT, |
| axis: 'block' |
| }); |
| await runTimelineRangeTest(t, { |
| rangeStart: { rangeName: 'exit', offset: CSS.percent(0) }, |
| rangeEnd: { rangeName: 'exit', offset: CSS.percent(100) }, |
| startOffset: STATIC_END + ROOM_BELOW - TARGET_HEIGHT, |
| endOffset: STATIC_END + ROOM_BELOW, |
| axis: 'block' |
| }); |
| await runTimelineRangeTest(t, { |
| rangeStart: { rangeName: 'exit-crossing', offset: CSS.percent(0) }, |
| rangeEnd: { rangeName: 'exit-crossing', offset: CSS.percent(100) }, |
| startOffset: STATIC_END + ROOM_BELOW - TARGET_HEIGHT, |
| endOffset: STATIC_END + ROOM_BELOW, |
| axis: 'block' |
| }); |
| }, 'View timeline top-sticky and bottom-sticky during entry.'); |
| |
| </script> |
| </body> |
| </html> |