sticky-util.js (4285B)
1 /** 2 * Builds a generic structure that looks like: 3 * 4 * <div class="scroller"> // 100x200 viewport 5 * <div class="contents"> // 100x500 6 * <div class="prepadding"></div> // 100x100 7 * <div class="container"> // 300x300 containing block 8 * <div class="filler"></div> // 100x100 9 * <div class="sticky box"></div> // 100x100 10 * </div> 11 * </div> 12 * </div> 13 * 14 * If the sticky direction is 'left' or 'right', the necessary blocks will be 15 * marked as inline-block and the dimensions above are flipped. 16 * 17 * Returns an 'elements' object which has each of the above elements as an 18 * accessible property. 19 */ 20 function setupStickyTest(stickyDirection, stickyOffset) { 21 const elements = {}; 22 const inline = stickyDirection === 'left' || stickyDirection === 'right'; 23 24 elements.scroller = document.createElement('div'); 25 elements.scroller.style.position = 'relative'; 26 elements.scroller.style.width = (inline ? '200px' : '100px'); 27 elements.scroller.style.height = (inline ? '100px' : '200px'); 28 29 // 'hidden' is used here instead of 'scroll' because this prevents 30 // scrollbars from affecting the size and offset of sticky items. 31 elements.scroller.style.overflow = 'hidden'; 32 33 elements.contents = document.createElement('div'); 34 elements.contents.style.height = (inline ? '100%' : '500px'); 35 elements.contents.style.width = (inline ? '500px' : '100%'); 36 37 elements.prepadding = document.createElement('div'); 38 elements.prepadding.style.height = (inline ? '100%' : '100px'); 39 elements.prepadding.style.width = (inline ? '100px' : '100%'); 40 if (inline) 41 elements.prepadding.style.display = 'inline-block'; 42 43 elements.container = document.createElement('div'); 44 elements.container.style.height = (inline ? '100%' : '300px'); 45 elements.container.style.width = (inline ? '300px' : '100%'); 46 if (inline) 47 elements.container.style.display = 'inline-block'; 48 49 elements.filler = document.createElement('div'); 50 elements.filler.style.height = (inline ? '100%' : '100px'); 51 elements.filler.style.width = (inline ? '100px' : '100%'); 52 if (inline) 53 elements.filler.style.display = 'inline-block'; 54 55 elements.sticky = document.createElement('div'); 56 elements.sticky.style = `${stickyDirection}: ${stickyOffset}px;`; 57 elements.sticky.style.position = 'sticky'; 58 elements.sticky.style.height = (inline ? '100%' : '100px'); 59 elements.sticky.style.width = (inline ? '100px' : '100%'); 60 elements.sticky.style.backgroundColor = 'green'; 61 if (inline) 62 elements.sticky.style.display = 'inline-block'; 63 64 elements.scroller.appendChild(elements.contents); 65 elements.contents.appendChild(elements.prepadding); 66 elements.contents.appendChild(elements.container); 67 elements.container.appendChild(elements.filler); 68 elements.container.appendChild(elements.sticky); 69 70 document.body.appendChild(elements.scroller); 71 72 return elements; 73 } 74 75 /** 76 * Similar to above, but nests a second sticky (named innerSticky) inside the 77 * sticky element. 78 * 79 * In the 'bottom' and 'right' cases, we also inject some padding before the 80 * innerSticky element, to give it something to push into. This inner padding is 81 * not exposed. 82 */ 83 function setupNestedStickyTest(stickyDirection, outerStickyOffset, 84 innerStickyOffset) { 85 const elements = setupStickyTest(stickyDirection, outerStickyOffset); 86 87 const inline = stickyDirection === 'left' || stickyDirection === 'right'; 88 if (stickyDirection === 'bottom' || stickyDirection === 'right') { 89 const innerPadding = document.createElement('div'); 90 innerPadding.style.height = (inline ? '100%' : '50px'); 91 innerPadding.style.width = (inline ? '50px' : '100%'); 92 if (inline) 93 innerPadding.style.display = 'inline-block'; 94 elements.sticky.appendChild(innerPadding); 95 } 96 97 elements.innerSticky = document.createElement('div'); 98 elements.innerSticky.style = `${stickyDirection}: ${innerStickyOffset}px;`; 99 elements.innerSticky.style.position = 'sticky'; 100 elements.innerSticky.style.height = (inline ? '100%' : '50px'); 101 elements.innerSticky.style.width = (inline ? '50px' : '100%'); 102 elements.innerSticky.style.backgroundColor = 'blue'; 103 if (inline) 104 elements.innerSticky.style.display = 'inline-block'; 105 106 elements.sticky.appendChild(elements.innerSticky); 107 108 return elements; 109 }